文章轉載自:https://blog.csdn.net/UbuntuTouch/article/details/106272704
在解決應用程序問題時,多行日志為開發人員提供了寶貴的信息。 堆棧跟蹤就是一個例子。 堆棧跟蹤是引發異常時應用程序處於中間的一系列方法調用。 堆棧跟蹤包括遇到錯誤的相關行以及錯誤本身。 可以在此處查看Java堆棧跟蹤的示例:
Exception in thread "main" java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
當使用類似Elastic Stack的日志記錄工具時,如果沒有正確的配置,可能很難識別和搜索堆棧跟蹤。 使用像Filebeat這樣的開源輕型日志攝入器發送應用程序日志時,堆棧跟蹤的每一行在Kibana中都將被視為單個文檔。
因此,上面的堆棧跟蹤將在Kibana中視為四個單獨的文檔。 這使得在堆棧跟蹤中搜索和理解錯誤和異常變得很困難,因為它們與它們的上下文脫離了共同的事件。 使用Filebeat記錄應用程序日志時,用戶可以通過在filebeat.yml文件中添加配置選項來避免此問題。
你可以配置filebeat.yml輸入節filebeat.inputs以添加一些多行配置選項,以確保將多行日志(如堆棧跟蹤)作為一個完整文檔發送。 將以下配置選項添加到filebeat.yml輸入部分,將確保上面引用的Java堆棧跟蹤將作為單個文檔發送。
multiline.pattern: '^[[:space:]]'
multiline.negate: false
multiline.match: after
根據 Elastic 的官方文檔介紹:
multiline.pattern
指定要匹配的正則表達式模式。 請注意,Filebeat支持的正則表達式模式與Logstash支持的模式有些不同。 有關受支持的正則表達式模式的列表,請參見正則表達式支持。 根據你配置其他多行選項的方式,與指定正則表達式匹配的行將被視為上一行的延續或新多行事件的開始。 你可以設置 negate 選項以否定模式。
multiline.negate
定義是否為否定模式,也就是和上面定義的模式相反。 默認為false。
multiline.match
指定Filebeat如何將匹配的行組合到事件中。 設置在之后 (after) 或之前 (before)。 這些設置的行為取決於你為否定指定的內容:
我們還是以上面的log例子為例。我們來創建一個叫做mulitline.log的文件:
mulitline.log
Exception in thread "main" java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
我們創建一個 filebeat 的配置文件:
mulitiline.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /Users/liuxg/data/multiline/multiline.log
multiline.pattern: '^[[:space:]]'
multiline.negate: false
multiline.match: after
output.elasticsearch:
hosts: ["localhost:9200"]
index: "multiline"
setup.ilm.enabled: false
setup.template.name: multiline
setup.template.pattern: multiline
運行 filebeat,我們看一下被導入的文檔的內容:
GET multiline/_search
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "multiline",
"_type" : "_doc",
"_id" : "9FI7OnIBmMpX8h3C4Cx8",
"_score" : 1.0,
"_source" : {
"@timestamp" : "2020-05-22T02:34:55.533Z",
"ecs" : {
"version" : "1.5.0"
},
"host" : {
"name" : "liuxg"
},
"agent" : {
"ephemeral_id" : "53a2f64e-c587-4f82-90bc-870274227c54",
"hostname" : "liuxg",
"id" : "be15712c-94be-41f4-9974-0b049dc95750",
"version" : "7.7.0",
"type" : "filebeat"
},
"log" : {
"offset" : 0,
"file" : {
"path" : "/Users/liuxg/data/multiline/multiline.log"
},
"flags" : [
"multiline"
]
},
"message" : """Exception in thread "main" java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)""",
"input" : {
"type" : "log"
}
}
}
]
}
}
從上面,我們可以看到在 message 字段,它含有 stack trace 的總三行信息。
另外一個例子是在 Elastic 的官方文檔中:
multiline.pattern: '^\['
multiline.negate: true
multiline.match: after
上面將匹配所有以 [ 為開頭的行,並且后面非以 [ 為開頭的行將被追加到匹配的那一行。那么它很好地匹配了像如下的日志:
[beat-logstash-some-name-832-2015.11.28] IndexNotFoundException[no such index]
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver$WildcardExpressionResolver.resolve(IndexNameExpressionResolver.java:566)
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:133)
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:77)
at org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction.checkBlock(TransportDeleteIndexAction.java:75)
針對如下的信息:
Exception in thread "main" java.lang.IllegalStateException: A book has a null property
at com.example.myproject.Author.getBookIds(Author.java:38)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Caused by: java.lang.NullPointerException
at com.example.myproject.Book.getId(Book.java:22)
at com.example.myproject.Author.getBookIds(Author.java:35)
... 1 more
我們可以采用如下的配置:
multiline.pattern: '^[[:space:]]+(at|\.{3})[[:space:]]+\b|^Caused by:'
multiline.negate: false
multiline.match: after
在上面的例子中,它的 pattern 匹配了如下的情況:
這一行開始以一個 SPACE 為開頭,並接着一個詞 at
這一行以一個短語 Caused by 為開始的
更多參考,請參閱官方文檔 https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html
除了上面提到的多行配置選項外,您還可以設置選項來刷新多行消息的內存,設置單個事件中可以包含的最大行數 multiline.max_lines,並且可以將超時時間設置為5秒(默認值)multiline.timeout。在指定的超時后,即使未找到新的模式來啟動新事件,Filebeat也會發送多行事件。
讓我們看一下使用multiline.flush_pattern的示例。 Filebeat的此配置選項對於包含事件以特定標記開始和結束的多行應用程序日志很有用。
[2015-08-24 11:49:14,389] Start new event
[2015-08-24 11:49:14,395] Content of processing something
[2015-08-24 11:49:14,399] End event
如果我們希望這些行在Kibana中顯示為單個文檔,我們將在filebeat.yml中使用以下多行配置選項:
multiline.pattern: ‘Start new event’
multiline.negate: true
multiline.match: after
multiline.flush_pattern: ‘End event’
從上面的配置選項中,當看到“Start new event”模式並且以下幾行與該模式不匹配時,它們將被追加到與該模式匹配的前一行。 當看到以“End event”開頭的一行時,flush_pattern選項將指示多行事件結束。
結論
將應用程序日志集中到一個位置是重要的第一步,可以幫助解決應用程序出現的任何問題。 確保在該工具中正確提取並顯示了日志,可以幫助公司減少平均解決時間。
參考:
【1】https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html