微服务业务日志收集方案

背景

日志内容复杂多样,如何去收集有价值的日志是咱们重点关注的。日志的价值实际上是取决于业务操做的,不一样的业务场景下相同类型的日志的价值会大相径庭。 根据以往的业务实践,结合企业级的一些业务需求,咱们选定关注如下几类日志。java

  • 跟踪日志【trace.log】 Server引擎的调试日志,用于系统维护人员定位系统运行问题使用。
  • 系统日志【system.log】 大粒度的引擎运行的入口、出口的日志,用于调用栈分析,能够进行性能分析使用。
  • 部署日志【deploy.log】 记录系统启动、中止、构件包部署、集群通知等信息的日志。
  • 引擎日志【engine.log】 细粒度的引擎运行日志,能够打印上下文数据,用于定位业务问题。
  • 构件包日志【contribution.log】 构件包记录的业务日志(使用基础构件库的日志输出API写日志)

这里咱们专门针对系统日志收集讨论几种收集方案sql

方案一:经过日志组件来收集

这里是指经过logback、log4j等日志组件来输出文件,而后再经过文件输出到logstash、kibana等日志组件中,经过这些日志组件来进行可视化统计与分析,这里须要统一关键日志输出格式方便往后统计搜索。json

优势mybatis

  • 操做简单,收集方便
  • 减小业务依赖
  • 粒度细

缺点app

  • 依赖于logstash、kibana
  • 只能知足简单的日志操做,详细点或者个性化需求操做起来比较复杂

方案二:使用aop来拦截controller

拦截controller层,经过controller中的方法名是否包含insert、update、delete等关键字来记录业务日志。异步

优势性能

  • 操做简单,收集方便

缺点ui

  • 只能记录简单日志
  • 不一样的人命名习惯不同,日志可能不许确

方案三:使用注解来,进行稍微精准的业务日志记录

这个方案粒度可大可小,代码侵入性也比较小,可操做性比较强,若是须要获取参数信息或者返回值信息,能够经过注解配置获取到,能够集合fastjson中的jpath来获取参数值下面有几个伪代码供参考代理

@Slf4j
@Aspect
public class SysLogAspect {

	@Around("@annotation(sysLog)")
	@SneakyThrows
	public Object around(ProceedingJoinPoint point, SysLog sysLog) {
		// 根据系统上下文获取相关数据
		Operation logVo = SysLogUtils.getOperationModel();
		Object obj=null;
		try{
			// 操做方式
			logVo.setOperationName(sysLog.value());
			// 操做时间
			logVo.setOperationTime(new Date());
			logVo.setObjectType(sysLog.objectType().name());
			logVo.setAppName(StringUtils.defaultString(sysLog.appName(),"TSP"));
			// 发送异步日志事件
			obj = point.proceed();
			if(StringUtils.isNotBlank(sysLog.objectIdKey())&&StringUtils.isNotBlank(sysLog.objectNameKey())){
				Map<String,Object> params=Maps.newHashMap();
				params.put("args",point.getArgs());
				params.put("response",obj);
				logVo.setObjectId(getKeyValue(sysLog.objectIdKey(),params));
				logVo.setObjectName(getKeyValue(sysLog.objectNameKey(),params));
			}
		}catch (BusinessException e){
			logVo.setException(e.getMessage());
			throw new Exception(e);
		}catch (RuntimeException e){
			logVo.setException(e.getMessage());
			throw new Exception(e);
		}catch (Exception e){
			logVo.setException(e.getMessage());
			throw new Exception(e);
		}finally {
			ApplicationContextUtils.publishEvent(new OperationEvent(logVo));
		}
		return obj;
	}

	private String getKeyValue(String key,Map<String,Object> params){
		try{
			Object mm= JSONPath.eval(params,key);
			if(mm!=null){
				return mm.toString();
			}
		}catch (Exception e){
			log.error("JSONPath.eval:",e);
		}
		return null;
	}


}

``调试

@SysLog(value = "xxxxxx",objectType = LogObjectType.OFFLINE_THRONG,
        objectIdKey = "$['args'][0][0]['id']",objectNameKey = "$['response'][0][0]['throngName']")

优势

  • 操做简单
  • 较灵活,粒度可大可小

缺点

  • 有代码侵入
  • 个性化需求不知足

方案四:针对复杂场景或者审计需求手动记录,侵入性强

若是有些业务共用了方法,须要更小的粒度,或者须要记录业务数据变动记录,这时就只能选择侵入式较强的方式来记录日志了,直接在业务代码中记录日志

logClient.logObject(LogObjectType.XXX,id,UserContext.getUserName(),"编辑xxx","xxx变动为xxxxx");

方案五:记录sql日志

则可使用mybatis拦截器来进行,若是没有使用mybatis,则能够作一个通用的preparestatement以及statement代理。

固然如今已经有很对监控组件能够知足这个需求,好比说jeager、javamelody、druid等

总结

通常状况下咱们会采用多种方式来记录业务日志,这个都是根据具体需求来进行评估用哪几种方式能够更好的达到产品需求。

相关文章
相关标签/搜索