Logtail 文件日志采集之完整正则模式
前言
為了簡化文件日志的采集過程,Logtail 提供了按行采集的極簡模式:通過換行符來切分日志,每行作為一條日志。極簡模式具有高效、配置簡單等優勢,但它將整條日志的內容作為整體,而不會對單條日志的內容進行額外解析,在有些場景下無法滿足需求。為此,我們還提供了其他解析方式,例如:分隔符模式、完整正則模式、JSON 模式等。
本文將介紹如何使用完整正則模式來實現對日志的解析,并且介紹一些使用此模式時的最佳實踐。
完整正則模式
簡介
完整正則模式是通過正則表達式實現的日志解析。正則表達式是用于匹配字符串中字符組合的模式,通俗來講,我們可以通過它來表達我們要什么樣的日志。正則表達式具有多個規范,包括 Posix、Perl 等,Logtail 的完整正則模式所支持的語法符合 Perl 正則(PCRE)規范(本文后續內容中所涉及的正則表達式都會采用該規范編寫)。
如上圖所示,相比極簡模式,完整正則模式增加了以下幾個功能:
-
采集多行日志
- 極簡模式僅通過換行符來切分日志,所以它無法采集多行日志(比如 Java 程序的異常堆棧)。
- 完整正則模式引入了行首正則,補足了采集多行日志的需求。
-
提取字段
- 極簡模式不對日志內容進行任何解析,每條日志都作為一個整體被發送到服務端。
- 完整正則模式通過為日志設置用于匹配的正則表達式,利用括號語法來提取日志的局部內容作為字段值。
-
指定日志時間
- 極簡模式只能使用采集時的系統時間作為每條日志所關聯的時間。
- 完整正則模式可以通過指定提取得到的某個字段以及一個關聯的時間格式,從字段值中解析得到時間戳,作為該條日志的時間。
接下來,我們將通過實際的操作去幫助您更好地理解如何使用完整正則模式的這三個功能。
準備工作
建議您可以先行到頁面開通日志服務,創建必要的 project 和 logstore,這樣您可以跟著本文的后續內容一起操作,加深您對完整正則模式的各個選項的理解。
我們為每個用戶都提供了每月的免費額度,簡單的試用不會給您帶來花費,不必擔心~
在您首次完成新的 project 和 logstore 的創建后,您將會進入到數據向導頁面,如下圖所示:
如果您不小心退出了這個頁面(或者非首次創建),也可以通過如下的步驟進入:
- 登錄日志服務控制臺,點擊您所創建的 project;
- 在進入的 logstore 列表,找到您所創建的 logstore,點擊對應的數據接入向導圖標,進入數據向導頁面。
進入數據向導頁面后,請滑動到頁面的最下端,在自定義數據中選擇文本文件,如下圖所示:
在點擊進入的頁面中,選擇完整正則模式,您會看到如下的界面:
至此,我們的準備工作已經完成,接下來我們將依次為您介紹完整正則模式的三個功能。
單行/多行日志
一般來說,日志文件都是單行日志,比如 Nginx 日志、Apache 日志等,示例如下:
127.0.0.1 - - [10/Sep/2018:12:36:49 +0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" 127.0.0.1 - - [10/Sep/2018:12:36:50 +0800] "GET /favicon.ico HTTP/1.1" 404 571 "http://127.0.0.1:8080/index.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"但同樣也存在著多行日志的情況,比如使用日志庫所打印的 Java 的異常堆棧日志等,示例如下:
[2018-10-01T10:30:01,000] [INFO] java.lang.Exception: exception happenedat TestPrintStackTrace.f(TestPrintStackTrace.java:3)at TestPrintStackTrace.g(TestPrintStackTrace.java:7)at TestPrintStackTrace.main(TestPrintStackTrace.java:16) [2018-10-01T10:30:31,000] [INFO] java.lang.Exception: another exception happenedat TestPrintStackTrace.f(TestPrintStackTrace.java:3)at TestPrintStackTrace.g(TestPrintStackTrace.java:7)at TestPrintStackTrace.main(TestPrintStackTrace.java:16)完整正則模式同時支持對以上兩種日志的解析,接下來我們來看看如何進行配置。
單行配置
當切換到完整正則模式時,默認使用的是單行配置,您只需要將您的實際日志粘貼到日志樣例文本框中即可,如下圖所示:
多行配置
對于多行日志的配置,首先您要關閉單行模式,然后設置行首正則表達式。Logtail 引入行首正則表達式來區分兩條多行日志之間該如何被切分,所以正確地設置行首正則表達式是切分您的多行日志的關鍵。
以先前提及的 Java 異常堆棧日志為例,每條日志的開頭都會有時間和日志等級,而日志的后續內容中一般沒有類似的內容,因此,我們可以根據這一點來設置我們的行首正則表達式(同樣地,您需要在日志樣例中粘貼您的實際日志,最好兩條以上)。
自動生成行首正則表達式
為了簡化您的操作,我們為您提供了自動生成正則表達式的功能,您可以在粘貼日志后,點擊自動生成,如下圖所示:
上圖示例中有幾點值得我們注意:
- 我們關閉了單行模式的選項,這樣界面上才會出現行首正則表達式的輸入框。
-
自動生成的行首正則表達式 (\[\d+-\d+-\w+:\d+:\d+,\d+]\s\[\w+]\s.*) 正確包含了時間和日志等級兩部分:
- \[\d+-\d+-\w+:\d+:\d+,\d+] 表示時間部分。
- [\w+]\s 表示日志等級部分以及其之后的空白符。
- 兩者中間的 \s 表示它們之間的空白符。
- 末尾的 .* 是固定內容,一定要填寫。
- 注意: 自動生成的行首正則并不一定完全可用,建議您進行一定的調整和優化。
手動調整行首正則表達式
自動生成行首正則表達式的功能很方便,但有時候它所生成的內容并不一定能夠滿足您的需求,您可以點擊手動輸入正則表達式,在自動生成的基礎上,進行修改。當您進入手動輸入正則表達式的狀態時,頁面上將出現一個驗證按鈕,通過它您可以驗證當前輸入的行首正則表達式能夠從日志樣例中匹配出多少行日志,方便您就地進行調試。
如下圖所示,我們對自動生成的行首正則的第二部分(日志等級)進行了錯誤修改(去掉了 + 號),然后再點擊驗證就會發現日志的匹配數目變為了 0。
提取字段
在設置了單行或者多行及其行首正則表達式后,我們能夠將原始文件中的內容切分為一條條的日志。如果每條日志都符合某個模式且能夠使用相同的正則表達式來進行匹配時,我們就可以將每條日志中的局部內容提取出來,將日志轉換為由鍵值對組成。
上述的這個過程我們稱之為提取字段,在默認情況下,完整正則模式也只會將每條日志作為一個整體發送到服務端。為了開啟此功能,您需要在頁面上打開提取字段選項,如下圖所示:
同樣地,為了方便您的使用,您也可以使用自動生成的方式來為各個字段生成對應的正則表達式。在您打開了提取字段的選項后,日志樣例文本框將變成一個可選擇的區域,您可以在上面選中要提取的內容,隨后點擊彈出的正則按鈕為選中的部分生成正則表達式。動圖示例如下:
接下來我們使用自動生成來為先前的單行和多行示例提取字段。
單行配置
如上圖所示:
- 我們從日志樣例文本框中提取了 6 個字段,分別將它們的 key 命名為 ip、time、query、status_code、length、user_agent,這樣該日志在采集到日志服務時,就會是一個具有 6 個字段(除特殊字段外)的日志。
- 在正則表達式的輸入框下,我們能看到 6 個使用 + 號連接的區域,它們分別包含了提取這 6 個字段所使用的正則表達式,其中使用 () 包裹的部分就是匹配對應字段的值時所使用的子模式。回想一下,我們之前也提到了提取字段是利用了正則表達式的括號語法實現的。
多行配置
如上圖所示,整個生成的過程基本類似,但需要注意一下最后一個字段(message)。在生成時,因為我們希望最后一個字段包含剩余的所有內容,我們跨越了多行去選擇日志內容。該字段對應的正則(僅括號內)為 ([^:]+:\s\w+\s\w+\s[^:]+:\S+\s[^:]+:\S+\s\S+)。事實上,這個正則是錯誤的(下文中我們會對此進行驗證):
- 它無法完整地包含日志的剩余部分,最后一個 at 后的內容都沒有被包含,這個從截圖中可以看到。
- 另外,該正則表達式中有三個冒號(:),因此,如果某個異常日志只有兩個冒號時,就無法匹配了。
這也體現了自動生成正則表達式的局限性,對此,您可以通過手動輸入正則表達式來進行一些修改,比如將最后一項直接修改為 ([\S\s]+) 這樣一個正則表達式即可將剩余的內容都包括到該字段中(包括換行)。
指定日志時間(可選項)
在日志服務中,每條日志都必須包括該日志發生的時間戳信息。默認情況下,Logtail 會使用該日志的采集時間作為它的日志時間(即啟用使用系統時間選項),但經過字段提取后,如果您的字段中有表示日志時間信息的字段,您可以將該字段的名字指定為 time,然后為其配置時間格式,進而 Logtail 會將該字段的值解析為時間戳,然后關聯給對應的日志。
Logtail 的時間格式解析使用的是 UNIX strptime,具體可參考文檔配置時間格式。
此功能于單行/多行日志沒有區別,這里我們就統一介紹下操作過程:
類似地,我們也提供了自動生成的功能來簡化您的使用,當然,您還是可以通過手動輸入來進行自定義的修改。我們示例中的單行和多行日志所生成的時間格式分別如下:
- 單行日志
- 多行日志
至此,我們已經對完整正則模式的三個功能(單行/多行日志采集、提取字段、指定日志時間)進行了依此的介紹,并給出了在控制臺操作它們的示例。
最佳實踐
1. 如何調試正則表達式?
如果您希望對您所在日志服務控制臺所設置的正則表達式進行調試,您可以直接在界面上使用驗證按鈕所提供的功能來進行檢查:
- 對于行首正則表達式,檢查一下當前設置能否正確匹配出您期望的日志數量。
- 對于提取字段,檢查一下各個字段中的值是否是您所希望的。
進一步地,如果您希望進行更多的驗證乃至調試正則表達式,您可以利用諸如 Regex101、RegexTester 之類的在線工具,將控制臺為您自動生成的正則表達式拷貝粘貼到這些工具上,然后填充您的實際日志來進行檢查、調試。
在之前的提取字段的示例中,我們有提到過自動生成功能為多行日志的 message 字段生成了不合適的正則。在此,我們以 Regex101 為例,對該正則進行一下檢查:
匹配,但是 at 之后的內容并沒有被包含到 message 字段中(注意顏色,橘色和藍色),這也就是我們之前所說的這個正則表達式是錯誤的原因之一。
匹配失敗。
at 后面的內容:
只有兩個冒號的日志:
類似地,您也可以按照如上的方法來對您的正則表達式進行調試、修改,最終應用于控制臺。
2. 日志里包含多種格式怎么辦?
完整正則模式要求日志必須采用統一的格式,但有些時候日志中可能會包含多種格式的日志,如何來處理這種情況呢?
[2018-10-01T10:30:31,000] [WARNING] java.lang.Exception: another exception happenedat TestPrintStackTrace.f(TestPrintStackTrace.java:3)at TestPrintStackTrace.g(TestPrintStackTrace.java:7)at TestPrintStackTrace.main(TestPrintStackTrace.java:16) [2018-10-01T10:30:32,000] [INFO] info something [2018-10-01T10:30:33,000] [DEBUG] key:value key2:value2以上面的 Java 日志為例,作為一個程序日志,它一般既包含正常信息,也會包含一些錯誤信息(比如異常棧等):
- WARNING 類型的多行日志
- INFO 類型的簡單文本日志
- DEBUG 類型的鍵值日志
對此,有兩種方案可以考慮:
- Schema-On-Write:為同樣的一份日志應用多個采集配置,每個采集配置具有不同的正則配置,從而能夠正確地實現字段提取。注:Logtail 不支持對同一個文件同時應用多個采集配置,您需要為該文件所在的目錄建立多個軟鏈接,每個配置作用于不同的軟鏈接目錄來間接實現多個配置同時采集一個文件。
- Schema-On-Read:使用它們共同的正則表達式來采集。比如說采用多行日志采集,將時間和日志等級作為行首正則,剩余的部分都作為 message。如果希望進一步分析 message 的話,您可以為該字段建立索引,然后利用日志服務的查詢分析功能,比如使用正則提取來從 message 字段提取需要的內容,基于該內容進行分析。此方案比較受限,僅推薦作用在同時分析的日志數量較小的場景下(比如千萬級)。
3. 正則表達式的性能優化
如果您非常地關注采集的性能,那您可以多花一些功夫在提高正則表達式的性能上。這里有一些建議可供您參考:
4. 時間格式配置技巧
日志服務的時間戳只支持到秒,所以時間格式只需配置到秒,無需配置毫秒、微秒等信息。
只需time字段中前面能解析出時間的部分即可,后面無需配置
常見日志格式配置示例如下:
更多閱讀
總結
以上是生活随笔為你收集整理的Logtail 文件日志采集之完整正则模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 增加关系型数据库驱动配置同步任务
- 下一篇: mongo数据库单节点搭建