我们的服务作为docker实例运行。 给定限制是docker日志记录驱动程序不能更改为与默认json文件驱动程序不同的任何内容。 (scala micro)服务输出一个看起来像这样的日志
{"log":"10:30:12.375 [application-akka.actor.default-dispatcher-13] [WARN] [rulekeepr-615239361-v5mtn-7]- c.v.r.s.logic.RulekeeprLogicProvider(91) - decision making have failed unexpectedly\n","stream":"stdout","time":"2017-05-08T10:30:12.376485994Z"}
{"log":"java.lang.RuntimeException: Error extracting fields to make a lookup for a rule at P2: [failed calculating amount/amountEUR/directive: [failed getting accountInfo of companyId:3303 from deadcart: unexpected status returned: 500]]\n","stream":"stdout","time":"2017-05-08T10:30:12.376528449Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.BasicRuleService$$anonfun$lookupRule$2.apply(BasicRuleService.scala:53)\n","stream":"stdout","time":"2017-05-08T10:30:12.376537277Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.BasicRuleService$$anonfun$lookupRule$2.apply(BasicRuleService.scala:53)\n","stream":"stdout","time":"2017-05-08T10:30:12.376542826Z"}
{"log":"\u0009at scala.concurrent.Future$$anonfun$transform$1$$anonfun$apply$2.apply(Future.scala:224)\n","stream":"stdout","time":"2017-05-08T10:30:12.376548224Z"}
{"log":"Caused by: java.lang.RuntimeException: failed calculating amount/amountEUR/directive: [failed getting accountInfo of companyId:3303 from deadcart: unexpected status returned: 500]\n","stream":"stdout","time":"2017-05-08T10:30:12.376674554Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.logic.TlrComputedFields$$anonfun$calculatedFields$1.applyOrElse(AbstractComputedFields.scala:39)\n","stream":"stdout","time":"2017-05-08T10:30:12.376680922Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.logic.TlrComputedFields$$anonfun$calculatedFields$1.applyOrElse(AbstractComputedFields.scala:36)\n","stream":"stdout","time":"2017-05-08T10:30:12.376686377Z"}
{"log":"\u0009at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)\n","stream":"stdout","time":"2017-05-08T10:30:12.376691228Z"}
{"log":"\u0009... 19 common frames omitted\n","stream":"stdout","time":"2017-05-08T10:30:12.376720255Z"}
{"log":"Caused by: java.lang.RuntimeException: failed getting accountInfo of companyId:3303 from deadcart: unexpected status returned: 500\n","stream":"stdout","time":"2017-05-08T10:30:12.376724303Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.mixins.DCartHelper$$anonfun$accountInfo$1.apply(DCartHelper.scala:31)\n","stream":"stdout","time":"2017-05-08T10:30:12.376729945Z"}
{"log":"\u0009at org.assbox.rulekeepr.services.mixins.DCartHelper$$anonfun$accountInfo$1.apply(DCartHelper.scala:24)\n","stream":"stdout","time":"2017-05-08T10:30:12.376734254Z"}
{"log":"\u0009... 19 common frames omitted\n","stream":"stdout","time":"2017-05-08T10:30:12.37676087Z"}
如何利用流畅的指令正确组合包含堆栈跟踪的以下日志事件,以便将它们作为单个消息发送到弹性文件中?
我可以完全控制所使用的logback appender模式,因此我可以将日志值的出现顺序更改为其他内容,甚至可以更改appender类。
我们正在使用k8s,事实证明它不是直接更改docker日志记录驱动程序,所以我们正在寻找一个能够处理给定示例的解决方案。
我不太关心将loglevel,thread,logger提取到特定键中,以便稍后我可以在kibana中轻松过滤它们。它会很高兴,但不那么重要。 重要的是准确地解析时间戳,缩短到毫秒,并将其作为实际的日志记录时间戳,并将其用于弹性。
答案 0 :(得分:1)
您可以使用fluent-plugin-concat。
例如使用Fluentd v0.14.x,
<source>
@type tail
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
<parse>
@type json
</parse>
@label @INPUT
</source>
<label @INPUT>
<filter kubernetes.**>
@type concat
key log
multiline_start_regexp ^\d{2}:\d{2}:\d{2}\.\d+
continuous_line_regexp ^(\s+|java.lang|Caused by:)
separator ""
flush_interval 3s
timeout_label @PARSE
</filter>
<match kubernetes.**>
@type relabel
@label @PARSE
</match>
</label>
<label @PARSE>
<filter kubernetes.**>
@type parser
key_name log
inject_key_prefix log.
<parse>
@type multiline_grok
grok_failure_key grokfailure
<grok>
pattern YOUR_GROK_PATTERN
</grok>
</parse>
</filter>
<match kubernetes.**>
@type relabel
@label @OUTPUT
</match>
</label>
<label @OUTPUT>
<match kubernetes.**>
@type stdout
</match>
</label>
类似问题:
答案 1 :(得分:0)
您可以尝试使用fluentd-plugin-grok-parser - 但我遇到了同样的问题 - 似乎没有识别\ u0009制表符,因此使用fluentd-plugin-detect-exceptions将无法检测到多行例外 - 至少在我的尝试中还没有......
答案 2 :(得分:0)
在fluentd 1.0中,我能够使用fluent-plugin-concat实现此目的。 concat插件将启动并继续串联,直到再次看到multiline_start_regexp模式。这捕获了JAVA异常和多行slf4j日志语句。调整您的multiline_start_regexp模式以匹配slf4j日志输出行。
任何行,包括从时间戳匹配模式开始的异常 2020-10-05 18:01:52.871 将被串联 例如:
2020-10-05 18:01:52.871 ERROR 1 --- [nio-8088-exec-3] c.i.printforever.DemoApplication multiline statement
我正在使用container_id作为身份密钥,
<system>
log_level debug
</system>
# Receive events from 24224/tcp
# This is used by log forwarding and the fluent-cat command
<source>
@type forward
@id input1
@label @mainstream
port 24224
</source>
# All plugin errors
<label @ERROR>
<match **>
@type file
@id error
path /fluentd/log/docker/error/error.%Y-%m-%d.%H%M
compress gzip
append true
<buffer>
@type file
path /fluentd/log/docker/error
timekey 60s
timekey_wait 10s
timekey_use_utc true
total_limit_size 200mb
</buffer>
</match>
</label>
<label @mainstream>
<filter docker.**>
@type concat
key log
stream_identity_key container_id
multiline_start_regexp /^\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}\.\d{1,3}/
</filter>
# Match events with docker tag
# Send them to S3
<match docker.**>
@type copy
<store>
@type s3
@id output_docker_s3
aws_key_id "#{ENV['AWS_KEY_ID']}"
aws_sec_key "#{ENV['AWS_SECRET_KEY']}"
s3_bucket "#{ENV['S3_BUCKET']}"
path "#{ENV['S3_OBJECT_PATH']}"
store_as gzip
<buffer tag,time>
@type file
path /fluentd/log/docker/s3
timekey 300s
timekey_wait 1m
timekey_use_utc true
total_limit_size 200mb
</buffer>
time_slice_format %Y%m%d%H
</store>
<store>
@type stdout
</store>
<store>
@type file
@id output_docker_file
path /fluentd/log/docker/file/${tag}.%Y-%m-%d.%H%M
compress gzip
append true
<buffer tag,time>
@type file
timekey_wait 1m
timekey 1m
timekey_use_utc true
total_limit_size 200mb
path /fluentd/log/docker/file/
</buffer>
</store>
</match>
<match **>
@type file
@id output_file
path /fluentd/log/docker/catch-all/data.*.log
</match>
</label>