Fluentd 自定義字段解析
本文分享fluentd日志采集,把一些自定義字段(json)解析出來變成新字段。
PS: 不熟悉fluentd,建議先看:
解析思路
1. 約定日志格式
在打印日志可以約定一個分隔符如"@|@"(只做舉例),假設有以下日志:
[2020-06-06 12:00:00 +0900] INFO hello world @|@{"key1": "value1", "key2": "value2"}
2. 正則截取
Ruby正則(命名捕獲)匹配出"@|@"后面的json內容,把他復制到另一個新字段(temp)。
<parse>
@type regexp
expression /^\[(?<logtime>[^\]]*)\] (?<level>[^ ]*) (?<message>.+?(?=( @\|@.+)?$))(?: @\|@(?<temp>.*))?/
time_key logtime
time_format %Y-%m-%d %H:%M:%S %z
</parse>
假設輸入的日志(Event)為:
[2020-06-06 12:00:00 +0900] INFO hello world @|@{"key1": "value1", "key2": "value2"}
解析后的日志:
time:
1362120400 (2020-06-06 12:00:00 +0900)
record:
{
"level" : "INFO",
"message": "hello world",
"temp" : {"key1": "value1", "key2": "value2"}
}
3. 使用filter解析json
使用filter解析temp字段(json)的內容
<filter test.*>
@type parser
key_name temp
reserve_data true # 保留除temp外的其他字段
remove_key_name_field true # 解析成功刪除temp字段,如果要保留temp字段則關閉
<parse>
@type json
json_parser json # 重點,必須加這句才能把json解析成字段
</parse>
</filter>
使用過濾器后:
time:
1362120400 (2020-06-06 12:00:00 +0900)
record:
{
"level" : "INFO",
"message": "hello world @|@",
"key1": "value1",
"key2": "value2"
}
示例
<source>
@type tail
path /var/log/httpd-access.log
pos_file /var/log/td-agent/httpd-access.log.pos
tag test.*
<parse>
@type regexp # 亦可使用mutilline
expression /^\[(?<logtime>[^\]]*)\] (?<level>[^ ]*) (?<message>.+?(?=( @\|@.+)?$))(?: @\|@(?<temp>.*))?/
time_key logtime
time_format %Y-%m-%d %H:%M:%S %z
</parse>
</source>
<filter>
@type parser
key_name temp
reserve_data true # 保留除temp外的其他字段
remove_key_name_field true # 解析成功刪除temp字段
<parse>
@type json
json_parser json # 重點,必須加這句才能把json解析成字段
</parse>
</filter>
<match test.*>
@type stdout
<match>
在線ruby正則解析工具
在線正則解析
PS: 例子中用到的正則表達式^.+?(?=( @\|@.+)?$)
說明:
對於abc @|@{"xxx":123}字符串:
- 若存在分隔符" @|@",則截取分隔符前面的內容abc;
- 若不存在,則截取整個字符串如abc{"xxx":123}
優化
上面是最直接的思路。
可能通過fluentd的多分支處理應該也可以實現,有待研究。