fluent bit能从一个文件中解析多种类型的日志行吗



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

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(日志行都在节点上的同一容器日志文件中。我遇到的问题是fluent bit似乎无法自动检测要使用哪个解析器,我不确定它是否应该使用,而且我们只能在部署的注释部分指定一个解析器,我已经指定了apache。因此,最终不会解析写入同一文件但来自stderr的错误日志行。我应该将日志从fluent bit发送到fluentd来处理错误文件,假设fluentd可以处理这个问题,还是应该以某种方式将错误行泵回fluent bit进行解析?

我是不是错过了什么?

谢谢!

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

此处记录: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

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

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

[Filter]
Name Parser
Match *
Parser parse_common_fields
Parser json
Key_Name log

第一个解析器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

下面是一个可以运行来测试的示例:

示例

试图解析日志,但某些日志可能是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":{}}

parser.conf

[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

fluentbit.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 *

结果

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":{}}"}]

一旦Filterjson解析了日志,我们就成功地使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"=>{}}]

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

Pass1

[1659094619.000000000, {"log"=>"{"action": {"Complete", ...

Pass2

[1659094619.000000000, {"action"=>"Complete", ...

FluentBit没有看到这一点,但Fluentd:

  • https://github.com/fluent/fluentd-kubernetes-daemonset
  • https://github.com/repeatedly/fluent-plugin-multi-format-parser#configuration

注意,format none作为最后一个选项意味着如果其他选项都不起作用,则保持日志行原样,例如明文。

您还可以使用FluentBit作为纯日志收集器,然后使用Fluentd进行单独的部署,该部署从FluentBit接收流、解析并执行所有输出。在FluentBit输出中使用type forward,在Fluentd中使用源@type forward。文档:https://docs.fluentbit.io/manual/pipeline/outputs/forward

最新更新