微服务业务日志收集方案,写得非常好!
作者:lipengxs
鏈接:my.oschina.net/lipengxs/blog/3156247
背景
日志內(nèi)容復(fù)雜多樣,如何去收集有價值的日志是我們重點(diǎn)關(guān)注的。日志的價值其實(shí)是取決于業(yè)務(wù)操作的,不同的業(yè)務(wù)場景下相同類型的日志的價值會截然不同。
根據(jù)以往的業(yè)務(wù)實(shí)踐,結(jié)合企業(yè)級的一些業(yè)務(wù)需求,我們選定關(guān)注以下幾類日志。
跟蹤日志【trace.log】 Server引擎的調(diào)試日志,用于系統(tǒng)維護(hù)人員定位系統(tǒng)運(yùn)行問題使用。
系統(tǒng)日志【system.log】 大粒度的引擎運(yùn)行的入口、出口的日志,用于調(diào)用棧分析,可以進(jìn)行性能分析使用。
部署日志【deploy.log】 記錄系統(tǒng)啟動、停止、構(gòu)件包部署、集群通知等信息的日志。
引擎日志【engine.log】 細(xì)粒度的引擎運(yùn)行日志,可以打印上下文數(shù)據(jù),用于定位業(yè)務(wù)問題。
構(gòu)件包日志【contribution.log】 構(gòu)件包記錄的業(yè)務(wù)日志(使用基礎(chǔ)構(gòu)件庫的日志輸出API寫日志)
這里我們專門針對系統(tǒng)日志收集討論幾種收集方案,關(guān)注微信公眾號Java技術(shù)棧,在后臺回復(fù):微服務(wù),可以獲取我整理的 N 篇 微服務(wù)系列教程,都是干貨。
方案一:通過日志組件來收集
這里是指通過logback、log4j等日志組件來輸出文件,然后再通過文件輸出到logstash、kibana等日志組件中,通過這些日志組件來進(jìn)行可視化統(tǒng)計(jì)與分析,這里需要統(tǒng)一關(guān)鍵日志輸出格式方便日后統(tǒng)計(jì)搜索。
優(yōu)點(diǎn)
操作簡單,收集方便
減少業(yè)務(wù)依賴
粒度細(xì)
缺點(diǎn)
依賴于logstash、kibana
只能滿足簡單的日志操作,詳細(xì)點(diǎn)或者個性化需求操作起來比較復(fù)雜
方案二:使用aop來攔截controller
攔截controller層,通過controller中的方法名是否包含insert、update、delete等關(guān)鍵字來記錄業(yè)務(wù)日志。
優(yōu)點(diǎn)
操作簡單,收集方便
缺點(diǎn)
只能記錄簡單日志
不同的人命名習(xí)慣不一樣,日志可能不準(zhǔn)確
方案三:使用注解來,進(jìn)行稍微精準(zhǔn)的業(yè)務(wù)日志記錄
這個方案粒度可大可小,代碼侵入性也比較小,可操作性比較強(qiáng),如果需要獲取參數(shù)信息或者返回值信息,可以通過注解配置獲取到,可以集合fastjson中的jpath來獲取參數(shù)值下面有幾個偽代碼供參考
@Slf4j
@Aspect
public class SysLogAspect {
@Around("@annotation(sysLog)")
@SneakyThrows
public Object around(ProceedingJoinPoint point, SysLog sysLog) {
// 根據(jù)系統(tǒng)上下文獲取相關(guān)數(shù)據(jù)
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"));
// 發(fā)送異步日志事件
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']")
優(yōu)點(diǎn)
操作簡單
較靈活,粒度可大可小
缺點(diǎn)
有代碼侵入
個性化需求不滿足
方案四:針對復(fù)雜場景或者審計(jì)需求手動記錄,侵入性強(qiáng)
如果有些業(yè)務(wù)共用了方法,需要更小的粒度,或者需要記錄業(yè)務(wù)數(shù)據(jù)變更記錄,這時就只能選擇侵入式較強(qiáng)的方式來記錄日志了,直接在業(yè)務(wù)代碼中記錄日志,日志系統(tǒng)新貴 Loki,這個推薦看下。
logClient.logObject(LogObjectType.XXX,id,UserContext.getUserName(),"編輯xxx","xxx變更為xxxxx");
方案五:記錄sql日志
則可以使用mybatis攔截器來進(jìn)行,如果沒有使用mybatis,則可以做一個通用的preparestatement以及statement代理。
當(dāng)然現(xiàn)在已經(jīng)有很對監(jiān)控組件可以滿足這個需求,比如說jeager、javamelody、druid等。
總結(jié)
一般情況下我們會采用多種方式來記錄業(yè)務(wù)日志,這個都是根據(jù)具體需求來進(jìn)行評估用哪幾種方式可以更好的達(dá)到產(chǎn)品需求。
近期熱文推薦:
1.Java 15 正式發(fā)布, 14 個新特性,刷新你的認(rèn)知!!
2.終于靠開源項(xiàng)目弄到 IntelliJ IDEA 激活碼了,真香!
3.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看。。
4.吊打 Tomcat ,Undertow 性能很炸!!
5.《Java開發(fā)手冊(嵩山版)》最新發(fā)布,速速下載!
覺得不錯,別忘了隨手點(diǎn)贊+轉(zhuǎn)發(fā)哦!
總結(jié)
以上是生活随笔為你收集整理的微服务业务日志收集方案,写得非常好!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot中获取微信用户信息从
- 下一篇: php列目录设置密码,PHP输入密码并列