实际上,我解决这个问题的方法是将接收到的数据(从<source> 类型转发)写入文件(<match> 类型文件),然后读取文件(<source> 类型尾部) ,此时我可以使用多行解析器。来自原始源的元数据(例如主机名、环境名称等)必须存储在文件名中,然后使用标记部分提取出来。
例子:
Docker 守护程序使用以下选项运行:
--log-driver=fluentd --log-opt tag=ecs.{{.ImageName}}
Fluentd 配置如下:
<source>
@type forward
port 24224
</source>
<match ecs.**>
@type forest
subtype file
<template>
time_slice_format %Y-%m-%d
path /var/log/td-agent/ecs/${tag}.*.log
format single_value
message_key log
append true
</template>
</match>
<source>
type tail
format multiline
format_firstline /\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}/
format1 /(?<time>\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}([,.]\d{1,4})*\S*)\s+(?<level>\w+)\s+\[(?<thread>.*?)\s*\]\s+(?<message>.+)/
path /var/log/td-agent/ecs/ecs.*.java.*.log
multiline_flush_interval 2s
pos_file /var/log/td-agent/ecs/java-1.pos
tag java.log-1.*
refresh_interval 5
</source>
<match java.**>
type elasticsearch
host es-host
port 9200
index_name java
logstash_format true
logstash_prefix java
</match>
顺便说一句,您还可以在传递给 fluentd 的标记中包含来自 Docker 标签的值,使用 Docker 守护程序选项如下:
--log-opt tag='ecs.{{.ContainerLabels.ENVIRONMENT}}.{{.ContainerLabels.LOG_TYPE}}.{{.ContainerLabels.ARTIFACT_ID}}.{{.ContainerLabels.ARTIFACT_VERSION}}.{{index .ContainerLabels \\\"spinnaker.servergroup\\\"}}'
在上面的示例中,我为传递给 fluentd 的标签添加了 4 个标签,然后可以将其提取到字段中并传递给 Elasticsearch。