1.日志的重要性
站在用戶的角度思考問題,與客戶深入溝通,找到靖宇網(wǎng)站設(shè)計(jì)與靖宇網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、申請域名、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋靖宇地區(qū)。
不管我們使用何種語言開發(fā),一旦程序發(fā)生異常,日志是一個(gè)很重要的數(shù)據(jù)。但是并不是意味著打印的日志越多越好,我們需要的是有用的日志。
曾經(jīng)參與一個(gè)很重要的項(xiàng)目優(yōu)化,他們的日志沒有進(jìn)行規(guī)范,開發(fā)、運(yùn)維也沒有把這個(gè)事情放在心上。等到壓測的時(shí)候TPS和響應(yīng)時(shí)間一直上不去。通過jstack分析發(fā)現(xiàn),大部分的log數(shù)據(jù)在阻塞!
今天我們不討論具體的日志規(guī)范,我從日志中心的角度來聊下LOG的規(guī)范
2.日志采集分析 -ELK
目前主流的ELK系統(tǒng)應(yīng)該都是通過agent端(filebeat/flume)采集具體.log文件,對于日志沒有多大處理的話,我們可能把整條日志采集過來后,通過logstash后把message存儲到elasticsearch中。
1.當(dāng)我們需要從每條日志中提取日志時(shí)間、日志級別等等信息的時(shí)候,我們需要在logstash配置相應(yīng)的 grok語法解析其中的message信息。
2.當(dāng)我們的日志中有異常信息,我們需要提取異常信息的時(shí)候,你會發(fā)現(xiàn)用grok來清洗message很困難!其實(shí)也有解決的方法,需要你去慢慢寫正則匹配
不錯,logstash強(qiáng)大的grok及mutate可以滿足需求,但是當(dāng)日志量很大的時(shí)候,logstash的grok和mutate會消耗大量的資源。那我們有沒有更有的方案呢?
下面我們用java日志來舉例吧
在想要得到答案之前,我們需要知道存儲到es的最終數(shù)據(jù)是JSON,logstash清洗數(shù)據(jù)最終的結(jié)果是轉(zhuǎn)換成JSON。一般的agent采集端僅僅只是做日志的采集,即使kafka做緩沖,kafka也不做處理。因此我們需要從日志的根源來解決這個(gè)問題。
3.為什么使用logstash處理Java的異常信息不好做呢?
這就涉及到日志框架輸出的異常信息通常是多行的,這就意味著我們需要在filebeat(flume)或者logstash來處理多行的問題。當(dāng)我們在日志的配置文件沒有很好的區(qū)分日志的message和stack時(shí),日志是糅雜一塊的。提前其中的信息很難很難
4. 日志json化
既然原生的日志數(shù)據(jù)不好處理,那么我們需要對日志框架做些美容手術(shù)。
在日志中,我們一般都會打印,時(shí)間/日志級別/線程/日志內(nèi)容/當(dāng)前文件名/loggerName/異常信息等等。
其中 日志內(nèi)容和異常信息可能會出現(xiàn)多行。這個(gè)需要處理下,下面我們使用fastjson來處理這兩個(gè)字段,見代碼
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中配置
修改layout -> Pattern
{"date":"%date{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","className":"%logger","fileName":"%file","thread":"%thread","msg":%msgdiy, "stack_trace":%exdiy}%n
{ "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字符串轉(zhuǎn)換成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" }
最終效果
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。