淺談java日志格式化
1.日志的重要性
不管我們使用何種語言開發(fā),一旦程序發(fā)生異常,日志是一個很重要的數(shù)據(jù)。但是并不是意味著打印的日志越多越好,我們需要的是有用的日志。
曾經(jīng)參與一個很重要的項目優(yōu)化,他們的日志沒有進行規(guī)范,開發(fā)、運維也沒有把這個事情放在心上。等到壓測的時候TPS和響應時間一直上不去。通過jstack分析發(fā)現(xiàn),大部分的log數(shù)據(jù)在阻塞!
今天我們不討論具體的日志規(guī)范,我從日志中心的角度來聊下LOG的規(guī)范
2.日志采集分析 -ELK
目前主流的ELK系統(tǒng)應該都是通過agent端(filebeat/flume)采集具體.log文件,對于日志沒有多大處理的話,我們可能把整條日志采集過來后,通過logstash后把message存儲到elasticsearch中。
1.當我們需要從每條日志中提取日志時間、日志級別等等信息的時候,我們需要在logstash配置相應的 grok語法解析其中的message信息。
2.當我們的日志中有異常信息,我們需要提取異常信息的時候,你會發(fā)現(xiàn)用grok來清洗message很困難!其實也有解決的方法,需要你去慢慢寫正則匹配
不錯,logstash強大的grok及mutate可以滿足需求,但是當日志量很大的時候,logstash的grok和mutate會消耗大量的資源。那我們有沒有更有的方案呢?
下面我們用java日志來舉例吧
在想要得到答案之前,我們需要知道存儲到es的最終數(shù)據(jù)是JSON,logstash清洗數(shù)據(jù)最終的結果是轉換成JSON。一般的agent采集端僅僅只是做日志的采集,即使kafka做緩沖,kafka也不做處理。因此我們需要從日志的根源來解決這個問題。
3.為什么使用logstash處理Java的異常信息不好做呢?
這就涉及到日志框架輸出的異常信息通常是多行的,這就意味著我們需要在filebeat(flume)或者logstash來處理多行的問題。當我們在日志的配置文件沒有很好的區(qū)分日志的message和stack時,日志是糅雜一塊的。提前其中的信息很難很難
4. 日志json化
既然原生的日志數(shù)據(jù)不好處理,那么我們需要對日志框架做些美容手術。
在日志中,我們一般都會打印,時間/日志級別/線程/日志內容/當前文件名/loggerName/異常信息等等。
其中 日志內容和異常信息可能會出現(xiàn)多行。這個需要處理下,下面我們使用fastjson來處理這兩個字段,見代碼
public class MsgConverter extends ClassicConverter {
@Override
public String convert(ILoggingEvent event) {
return JsonUtils.serialize(event.getFormattedMessage());
}
}
public class StackTraceConverter extends ThrowableProxyConverter {
@Override
public String convert(ILoggingEvent event) {
IThrowableProxy throwableProxy = event.getThrowableProxy();
// 如果沒有異信息
if (throwableProxy == null) {
//返回字符串 : "\"\""
return JsonUtils.serialize("");
}
String ex = super.convert(event);
return JsonUtils.serialize(ex);
}
}
其中JsonUtils可以選擇合適的json框架來處理
之后在logback.xml中配置
<configuration> <conversionRule conversionWord="exdiy" converterClass="xxx.logback.converter.StackTraceConverter" /> <conversionRule conversionWord="msgdiy" converterClass="xxx.logback.converter.MsgConverter" /> </configuration>
修改layout -> Pattern
<layout>
<!--<Pattern>{"date":"%date{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","tid":"%tid","className":"%logger","fileLine":"%file:%line","msg":%message, "stack_trace":%ex }%n</Pattern>-->
<Pattern>{"date":"%date{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","className":"%logger","fileName":"%file","thread":"%thread","msg":%msgdiy, "stack_trace":%exdiy}%n</Pattern>
</Pattern>
{
"date":"2019-01-02 16:16:33.817",
"level":"INFO",
"className":"org.springframework.web.servlet.DispatcherServlet","fileName":"FrameworkServlet.java","thread":"http-nio-8762-exec-1","msg":"FrameworkServlet 'dispatcherServlet': initialization completed in 38 ms", "stack_trace":""
}
logstash將json字符串轉換成json即可
json {
source => "message"
#target => "doc"
remove_field => ["message"]
}
date {
match => ["date","yyyy-MM-dd HH:mm:ss.SSS"]
target => "@timestamp"
locale => "cn"
timezone => "Asia/Shanghai"
}
最終效果

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
java web監(jiān)聽器統(tǒng)計在線用戶及人數(shù)
本文主要介紹了java web監(jiān)聽器統(tǒng)計在線用戶及人數(shù)的方法解析。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04
Spring?Cloud集成Nacos?Config動態(tài)刷新源碼剖析
這篇文章主要為大家介紹了Spring?Cloud集成Nacos?Config動態(tài)刷新源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08
springboot實現(xiàn)將自定義日志格式存儲到mongodb中
這篇文章主要介紹了springboot實現(xiàn)將自定義日志格式存儲到mongodb中的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot使用MyBatis-Flex實現(xiàn)靈活的數(shù)據(jù)庫訪問
MyBatisFlex是一款優(yōu)秀的持久層框架,本文主要介紹了SpringBoot使用MyBatis-Flex實現(xiàn)靈活的數(shù)據(jù)庫訪問,具有一定的參考價值,感興趣的可以了解一下2024-06-06
SpringCloud Eureka服務的基本配置和操作方法
Eureka是Netflix開源的一個基于REST的服務治理框架,主要用于實現(xiàn)微服務架構中的服務注冊與發(fā)現(xiàn),Eureka是Netflix開源的服務發(fā)現(xiàn)框架,用于在分布式系統(tǒng)中實現(xiàn)服務的自動注冊與發(fā)現(xiàn),本文介紹SpringCloud Eureka服務的基本配置和操作方法,感興趣的朋友一起看看吧2023-12-12
在Spring?MVC中使用@ControllerAdvice創(chuàng)建全局異常處理器的方法
在Spring?MVC中,可以使用@ControllerAdvice或@RestControllerAdvice注解來定義全局異常處理器類,并使用?@ExceptionHandler注解來定義處理特定異常的方法,本文就給大家介紹了Spring?MVC?@ControllerAdvice創(chuàng)建處理器的方法,需要的朋友可以參考下2023-08-08
SpringCloud超詳細講解微服務網(wǎng)關Zuul
這篇文章主要介紹了SpringCloud Zuul微服務網(wǎng)關,負載均衡,熔斷和限流,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07

