Fluent-bit 可以解析一个文件中的多种类型的日志行吗?

cha*_*atz 7 fluentd fluent-bit

我在 k8s 中有一个相当简单的 Apache 部署,使用 Fluent-bit v1.5 作为日志转发器。我的设置与下面存储库中的设置几乎相同。我正在运行 AWS EKS 并将日志输出到 AWS ElasticSearch Service。

https://github.com/ Fluent/ Fluent-bit-kubernetes-logging

ConfigMap 位于: https: //github.com/ Fluent/ Fluent-bit-kubernetes-logging/blob/master/output/elasticsearch/ Fluent-bit-configmap.yaml

Apache 访问 (-> /dev/stdout) 和错误 (-> /dev/stderr) 日志行均位于节点上的同一容器日志文件中。我遇到的问题是 fluid-bit 似乎无法自动检测要使用哪个解析器,我不确定它是否应该这样做,而且我们只能在部署的注释部分指定一个解析器,我已经指定了 apache 。因此,最终,写入同一文件但来自 stderr 的错误日志行不会被解析。我应该将日志从 Fluent-bit 发送到 Fluentd 来处理错误文件(假设 Fluentd 可以处理这个问题),还是应该以某种方式仅将错误行抽回到 Fluent-Bit 中进行解析?

我错过了什么吗?

谢谢!

Dea*_*han 8

Fluentbit 能够对输入运行多个解析器。

如果您将多个解析器作为换行符添加到解析器过滤器中(对于非多行解析,因为多行支持逗号分隔),例如。

[Filter]
    Name Parser
    Match *
    Parser parse_common_fields
    Parser json
    Key_Name log
Run Code Online (Sandbox Code Playgroud)

第一个解析器parse_common_fields将尝试解析日志,只有失败时第二个解析器才会json尝试解析这些日志。

如果您想解析日志,然后再次解析它,例如日志中只有一部分是 JSON。然后你需要添加 2 个解析器,如下所示:

[Filter]
    Name Parser
    Match *
    Parser parse_common_fields
    Key_Name log

[Filter]
    Name Parser
    Match *
    Parser json
    # This is the key from the parse_common_fields regex that we expect there to be JSON
    Key_Name log
Run Code Online (Sandbox Code Playgroud)

您可以运行以下示例来测试这一点:

例子

尝试解析日志,但有些日志可能是 JSON,有时则不是。

日志行示例

2022-07-28T22:03:44.585+0000 [http-nio-8080-exec-3] [2a166faa-dbba-4210-a328-774861e3fdef][0ed32f19-47bb-4c1f-92c2-c9b7c43aa91f] INFO  SomeService:000 - Using decorator records threshold: 0
2022-07-29T11:36:59.236+0000 [http-nio-8080-exec-3] [][] INFO  CompleteOperationLogger:25 - {"action":"Complete","operation":"healthcheck","result":{"outcome":"Succeeded"},"metrics":{"delayBeforeExecution":0,"duration":0},"user":{},"tracking":{}}
Run Code Online (Sandbox Code Playgroud)

解析器配置文件

[PARSER]
    Name   parse_common_fields
    Format regex
    Regex ^(?<timestamp>[^ ]+)\..+ \[(?<log_type>[^ \[\]]+)\] \[(?<transaction_id>[^ \[\]]*)\]\[(?<transaction_id2>[^ \[\]]*)\] (?<level>[^ ]*)\s+(?<service_id>[^ ]+) - (?<log>.+)$
    Time_Format %Y-%m-%dT%H:%M:%S
    Time_Key    timestamp

[PARSER]
    Name   json
    Format json
Run Code Online (Sandbox Code Playgroud)

flutterbit.conf

[SERVICE]
    Flush     1
    Log_Level info
    Parsers_File parser.conf

[INPUT]
    NAME   dummy
    Dummy  {"log": "2022-07-28T22:03:44.585+0000 [http-nio-8080-exec-3] [2a166faa-dbba-4210-a328-774861e3fdef][0ed32f19-47bb-4c1f-92c2-c9b7c43aa91f] INFO  AnonymityService:245 - Using decorator records threshold: 0"}
    Tag    testing.deanm.non-json

[INPUT]
    NAME   dummy
    Dummy  {"log": "2022-07-29T11:36:59.236+0000 [http-nio-8080-exec-3] [][] INFO  CompleteOperationLogger:25 - {\"action\":\"Complete\",\"operation\":\"healthcheck\",\"result\":{\"outcome\":\"Succeeded\"},\"metrics\":{\"delayBeforeExecution\":0,\"duration\":0},\"user\":{},\"tracking\":{}}"}
    Tag    testing.deanm.json

[Filter]
    Name Parser
    Match *
    Parser parse_common_fields
    Key_Name log

[Filter]
    Name Parser
    Match *
    Parser json
    Key_Name log

[OUTPUT]
    Name  stdout
    Match *
Run Code Online (Sandbox Code Playgroud)

结果

parse_common_fields过滤器在日志行上运行后,它成功解析公共字段,并且要么log是字符串,要么是转义的 json 字符串

第一关

[0] testing.deanm.non-json: [1659045824.000000000, {"log_type"=>"http-nio-8080-exec-3", "transaction_id"=>"2a166faa-dbba-4210-a328-774861e3fdef", "transaction_id2"=>"0ed32f19-47bb-4c1f-92c2-c9b7c43aa91f", "level"=>"INFO", "service_id"=>"AnonymityService:245", "log"=>"Using decorator records threshold: 0"}]
[0] testing.deanm.json: [1659094619.000000000, {"log_type"=>"http-nio-8080-exec-3", "level"=>"INFO", "service_id"=>"CompleteOperationLogger:25", "log"=>"{"action":"Complete","operation":"healthcheck","result":{"outcome":"Succeeded"},"metrics":{"delayBeforeExecution":0,"duration":0},"user":{},"tracking":{}}"}]
Run Code Online (Sandbox Code Playgroud)

一旦过滤器json解析日志,我们就成功地正确解析了 JSON

第二遍

[0] testing.deanm.non-json: [1659045824.000000000, {"log_type"=>"http-nio-8080-exec-3", "transaction_id"=>"2a166faa-dbba-4210-a328-774861e3fdef", "transaction_id2"=>"0ed32f19-47bb-4c1f-92c2-c9b7c43aa91f", "level"=>"INFO", "service_id"=>"AnonymityService:245", "log"=>"Using decorator records threshold: 0"}]
[0] testing.deanm.json: [1659094619.000000000, {"action"=>"Complete", "operation"=>"healthcheck", "result"=>{"outcome"=>"Succeeded"}, "metrics"=>{"delayBeforeExecution"=>0, "duration"=>0}, "user"=>{}, "tracking"=>{}}]
Run Code Online (Sandbox Code Playgroud)

注意:上面 result1 和 result2 之间的区别在于,第一次传递后,json 字符串仍在日志对象内,而第二次传递将 json 解析为它自己的键,例如:

通过1

[1659094619.000000000, {"log"=>"{"action": {"Complete", ...
Run Code Online (Sandbox Code Playgroud)

通过2

[1659094619.000000000, {"action"=>"Complete", ...
Run Code Online (Sandbox Code Playgroud)


cha*_*atz 7

我能够通过使用带有“解析器”插件(名称)的 FluentBit FILTER 将第二个(和第三个)解析器应用于日志,如下所示。

记录于此处:https://docs. Fluentbit.io/manual/pipeline/filters/parser

[FILTER]
    Name            parser
    Match           kube.*
    Parser          apache_error_custom
    Parser          apache_error
    Preserve_Key    On
    Reserve_Data    On
    Key_Name        log
Run Code Online (Sandbox Code Playgroud)