Logtail 混合模式:使用插件处理文件日志
作為一個服務百萬機器的日志采集 agent,Logtail 目前已經提供了包括日志切分、日志解析(完整正則、JSON、分隔符)、日志過濾在內的常見處理功能,能夠應對絕大多數場景的處理需求。但有些時候,由于應用的歷史原因或是本身業務日志的復雜性,單一功能可能無法滿足所采集日志的處理需求,比如:
- 日志可能不再是單一格式,有可能同時由 JSON 或者分隔符日志組成。
- 日志格式可能也不固定,不同的業務邏輯所產生的日志具有不同的字段。
- ...
為此,Logtail 引入了?混合模式,一方面借助 Logtail 完善的事件機制來保證數據讀取階段的可靠性,另一方面,依賴于插件系統豐富的插件,來加強 Logtail 對復雜日志的處理能力。
Logtail 采集模式劃分
從整體來看,Logtail 的采集模式可以劃分為以下三種:
- 純 Logtail 模式:提供文本日志的采集能力,比如 Nginx 日志、JSON 日志、分隔符日志等。
- 純插件模式:作為文本日志采集的補充,提供對更豐富數據源的采集能力,包括 MySQL Binlog、JDBC Query、Syslog 等,同時還提供了一系列的插件來支撐采集后的數據處理。
- 混合模式:綜合上述兩者的能力,支持通過插件實現對文本日志的多樣處理。
混合模式工作原理
如上圖中間部分所示,純 Logtail 的核心處理部分由日志切分(Splitter)和日志解析(Parser)組成,根據選擇的日志采集模式,日志切分把讀取的文件內容切割成為一條條日志(比如單行基于換行符、多行基于行首正則),然后交由日志解析從單條日志中提取字段。由此可見,日志的采集模式固定了處理行為,比如完整正則模式要求日志必須完全符合設置的正則表達式,否則會報錯。這種基于采集模式的固定行為,擁有更好的性能,但犧牲了靈活性。
相比之下,混合模式則是犧牲一定的性能和計算資源來換取靈活性,以應對更為復雜的場景。如上圖所示,在混合模式下,Logtail 會將日志切分的結果直接提交給插件進行處理,在后者中,我們可以組合多種處理插件,來滿足我們的需求。
使用及限制說明
- 混合模式依舊依賴于 Logtail 完成日志切分,所以對于多行日志,依舊需要配置行首正則。
- 出于性能考慮,Logtail 提交給插件部分的數據并非是單條日志,而是日志的組合,因此插件處理配置的開始需要配置特定插件進行二次切分,具體下文將介紹。
- 性能開銷:視配置而定,混合模式下 Logtail 會消耗更多的資源(主要是 CPU)來完成處理任務,因此需要根據實際情況調整 Logtail 的資源限制。如果采集節點的資源有限,但確實有處理需求,可以仍舊使用純 Logtail 模式進行采集,之后使用數據加工來實現數據處理。
- Logtail 的版本需要在 0.16.28 及以上。
- 一些文本文件的功能在混合模式下無法使用,包括過濾器配置、上傳原始日志、機器時區、丟棄解析失敗日志、接受部分字段(分隔符模式)等,但其中部分功能可通過相關插件來實現。
插件處理配置語法
插件處理配置使用 JSON 對象進行表示,配置的 key 為?processors,value 是 JSON 對象的數組,數組內的每一個 JSON 對象表示一個處理插件的配置,處理時將按照數組內的定義順序依次執行。數組內的每個 JSON 對象包含兩個字段:type?和?detail,type?表示處理插件的類型(JSON string),detail?表示該插件的詳細參數(JSON 對象,key 為參數名,value 為參數值)。
{"processors": [{"type": "processor_regex","detail": {"SourceKey": "content","Regex": "...","Keys": ["time","short_msg","main_msg",]}},{"type": "processor_regex","detail": {"SourceKey": "main_msg","Regex": "...","Keys": [...]}}] }如上示例表示使用兩個?processor_regex?插件進行日志處理,第一個插件根據配置的?Regex?參數對日志中的?content?字段進行正則提取,結果為?Keys?參數指定的三個字段,而第二個插件對上一步提取得到的?main_msg?字段再次進行正則提取,得到更多的字段。
支持的插件列表
以下是當前所支持的處理插件,關于具體插件如何使用可參考文檔處理采集數據。
| processor_add_fields | 向日志中添加固定的一些字段 |
| processor_rename | 重命名指定字段名 |
| processor_drop | 根據字段名丟棄日志中的一些字段 |
| processor_drop_last_key | 當日志中存在指定的一些字段(名)時,丟棄特定字段,一般用于解析類型的處理插件后,當存在解析后的字段時,表示解析成功,可以丟棄原始字段 |
| processor_filter_key_regex | 判斷字段名是否符合設置的正則表達式,進而決定是否保留該字段 |
| processor_filter_regex | 判斷字段值是否符合設置的正則表達式,進而決定是否保留該字段 |
| processor_geoip | 對指定字段值(IP)進行地理位置分析,需要自行提供數據庫 |
| processor_gotime | 對指定字段值使用 Go 語言的時間格式進行解析,可將解析結果設置為日志時間 |
| processor_strptime | 對指定字段值使用 strptime 的時間格式進行解析,可將解析結果設置為日志時間 |
| processor_md5 | 對指定字段值進行 MD5 |
| processor_base64_decoding | 對指定字段值進行 base64 解碼 |
| processor_base64_encoding | 對指定字段值進行 base64 編碼 |
| processor_anchor | 可以配置 anchor 指定 start/stop 子串,然后對指定字段值進行處理,提取 start/stop 子串之間的內容作為新字段 |
| processor_regex | 對指定字段值進行正則提取 |
| processor_json | 對指定字段值進行 JSON 解析,可將結果展開為日志內容 |
| processor_packjson | 將指定的多個字段以 JSON 對象的格式打包至一個目標字段 |
| processor_split_char | 對指定字段值進行單字符分隔符(支持設置引用符)解析 |
| processor_split_string | 對指定的字段值進行多字符分隔符解析 |
| processor_split_key_value | 對指定的字段值進行鍵值對解析,如飛天日志 |
| processor_split_log_regex | 對指定字段值使用行首正則表達式進行切分,結果將分裂為多條日志,一般用于混合模式下對接 Logtail 多行日志 |
| processor_split_log_string | 對指定字段值使用多字符進行切分,結果將分裂為多條日志,一般用于混合模式下對接 Logtail 單行日志(使用換行符作為分隔) |
使用特定插件完成日志的二次切分
前文的說明中曾經提到,出于性能考慮,Logtail 提交給插件部分的數據并非是單條日志,而是日志的組合,需要在插件處理配置的開始增加特定插件進行二次切分。
總的來說,切分時所需要考慮的情況有單行日志和多行日志兩種,以下將分別介紹。
注意:此配置僅在混合模式下需要,如果使用的純自定義插件的采集配置,可以忽略。
單行日志
假設單行日志的內容是?2019-09-23 14:08:16.952 [INFO] hello world,則 Logtail 提交給插件部分的數據內容可能是:
"content": "2019-09-23 14:08:16.952 [INFO] hello world\n2019-09-23 14:08:16.952 [INFO] hello world1\n2019-09-23 14:08:16.952 [INFO] hello world2"可以看到,多條單行日志被一次性輸入到插件處理中,因此,我們需要配置一個針對單行日志的切分插件,即先前列表中最后的?processor_split_log_string。對于單行日志,可以直接復用如下配置:
{"type": "processor_split_log_string","detail": {"SplitKey": "content","SplitSep": "\n"} }多行日志
類似地,多行日志在提交給插件部分時也需要使用?processor_split_log_regex?進行基于行首正則的切分,配置如下(假設日志開頭為常見的 [] 包裹時間):
{"type": "processor_split_log_regex","detail": {"SplitKey": "content","SplitRegex": "\\[\\d+-\\d+\\d+\\s\\d+:\\d+:\\d+\\].*"} }參考此配置時需要根據實際情況調整行首正則表達式(SplitRegex)。
混合模式使用步驟
創建混合模式采集配置
從先前的介紹中可以看出,混合模式的采集配置實質上是文本模式的采集配置附加上額外的插件處理配置,因此,配置它的入口依舊是創建文本模式的采集配置:如果是單行日志,創建?極簡模式?的采集配置,如果是多行日志,創建?完整正則模式?的采集配置,并切換至多行模式,設置行首正則表達式。
API/SDK
在完成文本模式的采集配置創建后,我們可以通過 API/SDK 的方式添加構建好的插件處理配置。此處,我們借助?CLI?來實現這個過程,代碼如下:
# add_plugin_config.py # -*- coding:utf-8 -*-import commands import json import os import sysif len(sys.argv) != 4:print 'Usage: add_plugin_config.py <your_project_name> <your_config_name> <plugin_config_file>'sys.exit(1)your_project_name = sys.argv[1] your_config_name = sys.argv[2] your_plugin_config_file = sys.argv[3]status, output = commands.getstatusoutput('aliyunlog log get_logtail_config --project_name={} --config_name={}'.format(your_project_name, your_config_name)) if status != 0:print '[ERR] can not find specified config, please check your CLI configuration'print 'ErrMsg:', outputsys.exit(1) config = json.loads(output) print configplugin = json.load(open(your_plugin_config_file, 'r')) config["inputDetail"]["plugin"] = plugin with open('logtail_config.json', 'wb') as f:f.write(json.dumps(config))update_cmd = 'aliyunlog log update_logtail_config --project_name="{}" --config_detail="$(cat logtail_config.json)"'.format(your_project_name) print update_cmd print os.system(update_cmd)確定你需要修改的配置所屬的?project_name、config_name,把插件處理配置保存到任意文件(比如?plugin_config.json)后,調用腳本傳入這三個參數即可。
控制臺
在 SLS 控制臺上,我們可以通過?高級選項-啟用插件處理?來啟用混合模式。
在 API/SDK 的方式下,我們需要根據所選模式(JSON、分隔符等)來對二次切分的插件進行配置。而在控制臺上使用混合模式時,頁面將會根據所選的模式,自動地生成相應的默認配置,我們只需要配置針對單條日志的處理即可。通過?顯示/隱藏默認配置,我們可以查看插件配置的完整內容。
以下示例在極簡模式下使用?processor_add_fields?插件為每條日志增加兩個固定的字段。從兩張截圖的區別可以發現,頁面在默認配置中自動地填充了?processor_split_log_string?來實現按行二次切分。
示例
原始日志
假設我們所采集的是單行文本日志,原始日志內容如下:
"content": "2019-09-23 14:08:16.952 cip>->1.1.1.1_'_sip>->2.2.2.2_'_scheme>->http:POST_'_uri>->/v1/a/b/c_'_rt.all>->21_'_rt.p0>->19_'_\t{\"errcode\":10000,\"errmsg\":\"OK\",\"errdetail\":null,\"data\":{}}"該日志由?時間、多組鍵值對、JSON 對象?三部分組成,分別使用?空格?和?制表符?進行分隔,其中多組鍵值對部分使用?_'_?分隔鍵值對,>->?分隔鍵和值。
預期結果
為了方便分析,我們希望將日志的內容提取成如下的字段:
"time": "2019-09-23 14:08:16.952" "cip": "1.1.1.1" "sip": "2.2.2.2" "scheme": "http:POST" "uri": "/v1/a/b/c" "rt.all": "21" "rt.p0": "19" "errcode": "10000" "errmsg": "OK" "errdetail": "null"插件處理配置
{"processors": [{"type": "processor_split_log_string","detail": {"SplitKey": "content"}},{"type": "processor_regex","detail": {"SourceKey": "content","Regex": "(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+\\.\\d+)\\s(.*)_'_\t(.*)","Keys": ["time","main_msg","json_msg"],"NoKeyError": true,"NoMatchError": true,"KeepSource": true}},{"type": "processor_json","detail": {"SourceKey": "json_msg","KeepSource": true }},{"type": "processor_split_key_value","detail": {"SourceKey": "main_msg","Delimiter": "_'_","Separator": ">->","KeepSource": true}}] }如上是我們所創建的混合模式采集配置中的插件處理配置部分,由 4 個處理插件組成:
- processor_split_log_string:用于完成之前【使用特定插件完成日志的二次切分】提及的日志切分。
- processor_regex:將日志內容切分為三部分,三個字段分別為?time、main_msg、json_msg。
- processor_json:對上一步提取得到的?json_msg?進行解析,將其中的內容展開為日志字段。
- processor_split_key_value:對?main_msg?字段進行進一步的解析,將其中的各個鍵值對展開為日志字段。
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的Logtail 混合模式:使用插件处理文件日志的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 带领国产数据库走向世界,POLARDB底
- 下一篇: 前端内存优化的探索与实践