在FluentD中使用Ruby正则表达式解析多行日志文件
解决FluentD中多行日志(含JSON)的正则匹配问题
问题场景
你的日志分两种格式:
- 单行日志:
6/10/2022 10:06:16.908 | INFO | CLASS | BlankStart,15,1,2
- 多行JSON日志(消息跨多行):
6/10/2022 10:06:16.908 | INFO | CLASS | Obj: { "test": false,
"reso": true }
你之前用的正则:
(?<time>^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}.\d+)...(?<type>.[^| ]*)...(?<class>.[^| ]*)..(?<msg>.*)
因为默认是单行模式,.*只能匹配到当前行末尾,导致多行JSON的后续行被当作新日志截断,只保留了最后一行内容。
利用FluentD的\m修饰符解决问题
FluentD的\m修饰符用于开启多行模式,让正则能识别换行并正确匹配跨多行的内容。核心思路是让msg字段匹配到下一条日志的起始日期行之前的所有内容,或者日志末尾。
调整后的正则表达式
(?<time>^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}\.\d+)\s+\|\s+(?<type>[^|]+)\s+\|\s+(?<class>[^|]+)\s+\|\s+(?<msg>.*?(?=^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}\.\d+|\Z))\m
关键改动说明
\m修饰符:放在正则末尾,开启多行模式,让正则能处理跨行内容- 正向预查截断:
(?=^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}\.\d+|\Z)用来判断msg的结束位置——要么是下一条日志的日期开头,要么是整个日志的末尾(\Z) - 严谨的分隔符匹配:把原正则里的
...换成\s+\|\s+,匹配|前后的任意空白字符,避免因空格数量变化导致匹配失败 - 更灵活的字段匹配:将
.[^| ]*改为[^|]+,允许type或class字段包含空格(如果有这种场景)
FluentD配置示例(以in_tail插件为例)
<source> @type tail path /path/to/your/target.log tag custom.log.tag <parse> @type regexp expression /(?<time>^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}\.\d+)\s+\|\s+(?<type>[^|]+)\s+\|\s+(?<class>[^|]+)\s+\|\s+(?<msg>.*?(?=^\d{1,2}\/\d{1,2}\/\d{4}\s\d{2}:\d{2}:\d{2}\.\d+|\Z))\m/ time_format "%m/%d/%Y %H:%M:%S.%L" </parse> </source>
内容的提问来源于stack exchange,提问作者FreeSoftwareServers
相关产品推荐
相关产品推荐

