開發與維運

【最佳實踐】簡單配置,實現Filebeat多行日誌傳送

在解決應用程序問題時,多行日誌為開發人員提供了寶貴的信息。 堆棧跟蹤就是一個例子。 堆棧跟蹤是引發異常時應用程序處於中間的一系列方法調用。 堆棧跟蹤包括遇到錯誤的相關行以及錯誤本身。 可以在此處查看 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)。 這些設置的行為取決於你為否定指定的內容:

image.png

我們還是以上面的 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 匹配了如下的情況:

1、這一行開始以一個 SPACE 為開頭,並接著一個詞 at
2、這一行以一個短語 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

聲明:本文由原文作者“Elastic 中國社區佈道師——劉曉國”授權轉載,對未經許可擅自使用者,保留追究其法律責任的權利。
出處鏈接:https://elasticstack.blog.csdn.net/.


image.png

阿里雲Elastic Stack】100%兼容開源ES,獨有9大能力,提供免費X-pack服務(單節點價值$6000)

相關活動


更多折扣活動,請訪問阿里雲 Elasticsearch 官網

阿里雲 Elasticsearch 商業通用版,1核2G ,SSD 20G首月免費
阿里雲 Logstash 2核4G首月免費


image.png

image.png

Leave a Reply

Your email address will not be published. Required fields are marked *