微服務業務日誌收集方案

背景

日誌內容複雜多樣,如何去收集有價值的日誌是咱們重點關注的。日誌的價值實際上是取決於業務操做的,不一樣的業務場景下相同類型的日誌的價值會大相徑庭。 根據以往的業務實踐,結合企業級的一些業務需求,咱們選定關注如下幾類日誌。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等

總結

通常狀況下咱們會採用多種方式來記錄業務日誌,這個都是根據具體需求來進行評估用哪幾種方式能夠更好的達到產品需求。

相關文章
相關標籤/搜索