将客户端唯一记录添加到日志事件,流利的一面。例如,使用过滤器

Adding client-unique record to a log event, fluentd side. E.g., using filter

我成功地将 docker 化的流利 TCP 日志记录到 运行!含义:有 远程 python 容器使用稍作修改 logging.handlers.SocketHandler 发送一些 JSON 到 fluentd - 和 它实际上到达那里,看起来像这样:

2020-08-31T09:06:31+00:00 paws.tcp {"service_uuid":"paws_log","loglvl":"INFO","file":"paws_log.paws_log","line":59,"msg":"Ping log line #2"}

我有多个这样的 python 容器,希望 fluentd 添加一些 每个日志事件的源 ID 类型。 Reading the docs 让我给了 filter -> record 机制一个机会。通过 新添加导致以下配置片段 filter:

<source>
  @type tcp
  @label stream_paws
  @id paws_tcp
  tag paws.tcp
  port 5170
  bind 0.0.0.0
  # https://docs.fluentd.org/parser/regexp
  <parse>
    @type regexp
    expression /^(?<service_uuid>[a-zA-Z0-9_-]+): (?<logtime>[^\s]+) (?<loglvl>[^\s]+) \[(?<file>[^\]:]+):(?<line>\d+)\]: (?<msg>.*)$/
    time_key logtime
    time_format %H:%M:%S
    types line:integer
  </parse>
</source>

# Add meta data fluentd side.
# https://docs.fluentd.org/deployment/logging
<filter **> # << Does NOT seem to work if kept outside the label-block! Inside is fine.
  @type record_transformer
  <record>
    host "#{Socket.gethostname}"
  </record>
</filter>

<label stream_paws>
  <match paws.tcp>
    @type file
    @id output_paws_tcp
    path /fluentd/log/paws/data/tcp.*.log
    symlink_path /fluentd/log/paws/tcp.log
  </match>
</label>

我这里有两个问题:

如果您使用的是 fluentd docker 日志记录驱动程序,它已经将容器元数据(包括 id)添加到每个日志记录中: https://docs.docker.com/config/containers/logging/fluentd/

Above config works if I put the filter-block inside the label-block. But this I do not want to do because I want the filter to act globally. @include directives might offer a work-around here. Anything better?

通常在服务器上实现的全局过滤器,例如:

<source>
...
</source>

<filter **> # filter globally
...
</filter>

<match tag.one>
...
</match>

<match tag.two>
...
</match>

<match **> # the rest
...
</match>

I suspect "#{Socket.gethostname}" yields information on the fluentd server.

正确,参见:https://docs.fluentd.org/filter/record_transformer#example-configurations。当您还想跟踪哪个服务器处理了日志记录时,这会很有用。

如果您使用的是 kubernetes,则使用 kubernetes 元数据,它将在每个日志条目中添加 pod 详细信息。

<filter kubernetes.**>
  @id filter_kubernetes_metadata
  @type kubernetes_metadata
</filter>

对于Docker

我以前并没有真正使用过 fluentd,所以对于这里稍微抽象的回答表示歉意。但是.. 检查 http://docs.fluentd.org/ 我猜你可能正在使用 in_tail 作为日志?从那里的示例来看,您可能希望将文件路径获取到输入消息中:

path /path/to/file
tag foo.*

显然用 foo.path.to.file

标记事件

您可能可以将 http://docs.fluentd.org/articles/filter_record_transformer 与 enable_ruby 一起使用。由此看来,您可能可以处理 foo.path.to.file 标记并使用一点 ruby 来提取容器 ID,然后解析出 JSON 文件。

例如,使用以下 ruby 文件进行测试,例如 foo.rb

tag = 'foo.var.lib.docker.containers.ID.ID-json.log'
require 'json'; id = tag.split('.')[5]; puts JSON.parse(IO.read("/var/lib/docker/containers/#{id}/config.v2.json"))['image']

其中 config.v2.json 类似于:

{"image":"foo"}

会打印你

foo

Fluentd 可能已经为您包含了 json,所以也许您可以省略 require 'json';少量。然后,用流利的术语来说,也许你可以使用像

这样的东西
<filter>
  enable_ruby
  <record>
    container ${tag.split('.')[5]}
    image ${id = tag.split('.')[5]; JSON.parse(IO.read("/var/lib/docker/containers/#{id}/config.v2.json"))['image']}
  </record>
 </filter>

在你的情况下,你可以像下面这样使用

<filter raw.**>
  @type record_transformer
  enable_ruby
 <record>
    container ${id = tag.split('.')[5]; JSON.parse(IO.read("/var/lib/docker/containers/#{id}/config.v2.json"))["Name"][1..-1]}
     hostname "#{Socket.gethostname}"
 </record>
</filter>