前言:
上文http://www.itdecent.cn/p/8b68ac58b191通過logstash grok進(jìn)行數(shù)據(jù)處理,提取出日志類型及message,并可以生成到不同的索引文件;
隨后的使用中發(fā)現(xiàn)針對錯誤日志,由于日志信息換行導(dǎo)致message會分散到多條日志中,如下圖所示:
日志內(nèi)容(部分)如下
[2020-04-06 15:55:14.521] |http-nio-8020-exec-10|ERROR| com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)

1.多行處理
目前針對多行合并處理通常采用的logstash的multiline插件完成。
筆者采用如下方式處理時,發(fā)現(xiàn)無法啟動logstash,提示multiline不被beats支持,進(jìn)入docker查看 codec的multiline插件是安裝過的。
input {
beats {
port => 5044
codec => multiline {
pattern => "^\[\d*-\d*"
negate => true
what => "previous"
}
}
}
查閱官方資料的確有顯示該功能不被支持,如果要合并則需要我們從源頭配置Filebeat去處理,只能姑且理解為ES期望這種多行文本合并的操作最好在源頭解決掉。
https://www.elastic.co/guide/en/beats/filebeat/6.8/multiline-examples.html

解決方案
采集日志我們采用了log-pilot,其內(nèi)部使用了filebeat,我們修改其filebeat模式后重新部署log-pilot。
**master節(jié)點**
[root@k8s-master es]# kubectl get pods -n kube-system | grep log-pilot
log-pilot-9pt27 1/1 Running 0 3d17h
log-pilot-qq9w5 1/1 Running 1 3d17h
log-pilot-vc7qs 1/1 Running 0 3d17h
kubectl cp kube-system/log-pilot-9pt27:/pilot/filebeat.tpl filebeat.tpl #復(fù)制容器中filebeat.tpl文件到master節(jié)點
如上文提及,我們的日志格式如下:
***********.Net日志**************
[2020-04-05 12:59:04.7338]|netCore07.LogHelper|INFO|請求Healthy:04/05/2020 12:59:04
[2020-04-05 12:59:16.3861]|netCore07.LogHelper|INFO|請求DefaultIndex:04/05/2020 12:59:16
[2020-04-05 12:59:17.5992]|netCore07.LogHelper|INFO|請求DefaultIndex:04/05/2020 12:59:17
[2020-04-05 12:59:18.1920]|netCore07.LogHelper|INFO|請求DefaultIndex:04/05/2020 12:59:18
[2020-04-05 12:59:21.6663]|netCore07.LogHelper|INFO|請求Healthy:04/05/2020 12:59:21
***********Java日志**************
[2020-04-05 13:16:58.351] |http-nio-8020-exec-1|INFO| o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
[2020-04-05 13:16:58.351] |http-nio-8020-exec-1|INFO| org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet'
[2020-04-05 13:16:58.375] |http-nio-8020-exec-1|INFO| org.springframework.web.servlet.DispatcherServlet - Completed initialization in 22 ms
[2020-04-05 13:16:58.434] |http-nio-8020-exec-1|INFO| com.xxx.controller.StudentController - File-springboot-say:xx
針對日志我們編寫一個正則匹配每條日志的開頭格式
^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}
vim filebeat.tpl #修改該文件
{{range .configList}}
{{range .configList}}
{{range .configList}}
{{range .configList}}
scan_frequency: 10s
fields_under_root: true
{{if .Stdout}}
docker-json: true
{{end}}
{{if eq .Format "json"}}
json.keys_under_root: true
{{end}}
fields:
{{range $key, $value := .Tags}}
{{ $key }}: {{ $value }}
{{end}}
{{range $key, $value := $.container}}
{{ $key }}: {{ $value }}
{{end}}
tail_files: false
close_inactive: 2h
close_eof: false
close_removed: true
clean_removed: true
close_renamed: false
#以下4行是我們手動添加的
multiline.pattern: '^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}'
multiline.negate: true
multiline.match: after
multiline.max_lines: 1000
multiline.timeout: 20s
{{end}}
參數(shù)說明:
multiline.negate: 多行匹配模式是否取反,默認(rèn)false
multiline.match: 定義多行內(nèi)容被添加到模式匹配行之后還是之前,默認(rèn)無,可以被設(shè)置為after或者before
multiline.max_lines: 單一聚合最大的行數(shù),超過會被丟棄
multiline.timeout:多行匹配超時時間,超過超時時間后的當(dāng)前多行匹配事件將停止并發(fā)送,然后開始一個新的多行匹配事件,默認(rèn)5秒,這個很有用,以往我們用logstash的multiline時就會遇到最后一條日志無法采集,需要新日志插入才能采集的情況。
文件編寫完畢后我們重新制作一個定制版log-pilot鏡像:
vim Dockerfile
FROM registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.6-filebeat
COPY filebeat.tpl /pilot/filebeat.tpl
####wq保存dockerFile
####然后執(zhí)行docker build制作鏡像
[root@k8s-master log-pilot]# docker build -t 192.168.0.230:8083/es/log-pilot .
Sending build context to Docker daemon 3.584kB
Step 1/2 : FROM registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.7-filebeat
---> 10a688e1229a
Step 2/2 : COPY filebeat.tpl /pilot/filebeat.tpl
---> 433f59cc094e
Successfully built 433f59cc094e
Successfully tagged 192.168.0.230:8083/es/log-pilot:latest
####上傳鏡像到倉庫
[root@k8s-master log-pilot]# docker push 192.168.0.230:8083/es/log-pilot
The push refers to repository [192.168.0.230:8083/es/log-pilot]
5d508534be62: Pushed
385d5e9ef470: Pushed
60121972171a: Pushed
f48d07bb0c66: Pushed
93d544c0cc28: Pushed
b204552c6406: Pushed
721384ec99e5: Pushed
latest: digest: sha256:e8cba23fec45b221df0fc6e7b640c0475085dce4e39e14c0eb77cfd6571115c4 size: 1788
重新部署log-pilot
kubectl delete -f log-pilot.yaml 刪除當(dāng)前的log-pilot
接下來修改log-pilot.yaml中鏡像地址為我們剛才制作的鏡像完整名稱
kubectl apply -f log-pilot.yaml 再重新部署log-pilot
2.驗證
重新訪問下報錯的URL路徑,系統(tǒng)記錄下報錯日志,然后我們到kibana中查看
從容器日志文件中查看,出現(xiàn)2條錯誤日志,內(nèi)容很長,文中就不再粘貼。
kibana中查看,和預(yù)期一樣,記錄了兩條完整的日志

說明:列表中是摘要,點擊列表行可以查看單個文檔,查看完整日志信息。
總結(jié)
這種從源頭解決多行的問題并不是筆者所期望的,配置方式的靈活度并不如logstash的腳本模式,您也可能嘗試通過logstash的filter中使用multiline模式達(dá)到同樣的效果,示例:
filter {
multiline {
pattern => "^.{0,3}\[[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}\]|^[0-9]{4}-[0-9]{2}-[0-9]{2}.{0,20}"
negate => true
what => "previous"
}
grok {
match => {"message" => ".{0,3}%{TIMESTAMP_ISO8601:logTime}.{0,10}\|.*\|%{LOGLEVEL:logLevel}\|%{GREEDYDATA:message}"}
#用上面提取的message覆蓋原message字段
overwrite => ["message"]
}
}