配置fluentd以正确解析并运送使用docker json-file日志记录驱动程序格式化的java stacktrace作为单个消息弹性

时间:2017-05-08 10:49:27

标签: docker fluentd

我们的服务作为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中轻松过滤它们。它会很高兴,但不那么重要。 重要的是准确地解析时间戳,缩短到毫秒,并将其作为实际的日志记录时间戳,并将其用于弹性。

3 个答案:

答案 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>