天天看點

微服務業務日志收集方案,寫得非常好!

背景

日志内容複雜多樣,如何去收集有價值的日志是我們重點關注的。日志的價值其實是取決于業務操作的,不同的業務場景下相同類型的日志的價值會截然不同。

根據以往的業務實踐,結合企業級的一些業務需求,我們標明關注以下幾類日志。

跟蹤日志【trace.log】 Server引擎的調試日志,用于系統維護人員定位系統運作問題使用。

系統日志【system.log】 大粒度的引擎運作的入口、出口的日志,用于調用棧分析,可以進行性能分析使用。

部署日志【deploy.log】 記錄系統啟動、停止、構件包部署、叢集通知等資訊的日志。

引擎日志【engine.log】 細粒度的引擎運作日志,可以列印上下文資料,用于定位業務問題。

構件包日志【contribution.log】 構件包記錄的業務日志(使用基礎構件庫的日志輸出API寫日志)

這裡我們專門針對系統日志收集讨論幾種收集方案,關注微信公衆号Java技術棧,在背景回複:微服務,可以擷取我整理的 N 篇 微服務系列教程,都是幹貨。

方案一:通過日志元件來收集

這裡是指通過logback、log4j等日志元件來輸出檔案,然後再通過檔案輸出到logstash、kibana等日志元件中,通過這些日志元件來進行可視化統計與分析,這裡需要統一關鍵日志輸出格式友善日後統計搜尋。

優點

操作簡單,收集友善

減少業務依賴

粒度細

缺點

依賴于logstash、kibana

隻能滿足簡單的日志操作,詳細點或者個性化需求操作起來比較複雜

方案二:使用aop來攔截controller

攔截controller層,通過controller中的方法名是否包含insert、update、delete等關鍵字來記錄業務日志。

隻能記錄簡單日志

不同的人命名習慣不一樣,日志可能不準确

方案三:使用注解來,進行稍微精準的業務日志記錄

這個方案粒度可大可小,代碼侵入性也比較小,可操作性比較強,如果需要擷取參數資訊或者傳回值資訊,可以通過注解配置擷取到,可以集合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']")      

操作簡單

較靈活,粒度可大可小

有代碼侵入

個性化需求不滿足

方案四:針對複雜場景或者審計需求手動記錄,侵入性強

如果有些業務共用了方法,需要更小的粒度,或者需要記錄業務資料變更記錄,這時就隻能選擇侵入式較強的方式來記錄日志了,直接在業務代碼中記錄日志,日志系統新貴

Loki

,這個推薦看下。

logClient.logObject(LogObjectType.XXX,id,UserContext.getUserName(),"編輯xxx","xxx變更為xxxxx");      

方案五:記錄sql日志

則可以使用mybatis攔截器來進行,如果沒有使用mybatis,則可以做一個通用的preparestatement以及statement代理。

當然現在已經有很對監控元件可以滿足這個需求,比如說jeager、javamelody、druid等。

總結

一般情況下我們會采用多種方式來記錄業務日志,這個都是根據具體需求來進行評估用哪幾種方式可以更好的達到産品需求。

上一篇: 7.6