Fluentd 不解析嵌套的 json 数组

Fluentd does not parse nested json array

我在 Fluentd 输入中收到以下 json 消息

{"foo":{"bar":{"abc":"[\n {\n \"ip\":\"192.168.1.1\",\n \"hostname\":\"pc\",\n \"mac\":\"01:02:03:04:05:06\"\n} \n]"}}}

并且想要得到输出消息

{"foo":{"bar":{"abc":[{"ip":"192.168.1.1", "hostname":"pc", "mac":"01:02:03:04:05:06}]"}}}

我正在尝试使用过滤器解析它

<filter **>
  @type parser
  key_name foo
  reserve_data true
  remove_key_name_field false
  <parse>
    @type multi_format
    <pattern>
      format json
    </pattern>
    <pattern>
      format none
    </pattern>
  </parse>
</filter>  

但是没有任何效果。输出与输入相同。

当我尝试时

<filter **>
  @type parser
  key_name $['foo']['bar']['abc']
  <parse>
    @type none
  </parse>
</filter>

<filter **>
  @type parser
  key_name message
  <parse>
    @type json
  </parse>
</filter>

它“有效”,但当然我只得到

[{"ip":"192.168.1.1","hostname":"ps","mac":"01:02:03:04:05:06}]

感谢您的建议。

您可以这样使用 record_transformer by enabling Ruby

<filter **>
  @type record_transformer
  enable_ruby true
  <record>
    message ${ record['message'].gsub(/(\n)|(\)|(\s+)/, '') }
  </record>
</filter>

输出:

2021-05-17 16:22:14.568177376 +0500 test.*: {"message":"{\"foo\":{\"bar\":{\"abc\":\"[{\"ip\":\"192.168.1.1\",\"hostname\":\"pc\",\"mac\":\"01:02:03:04:05:06\"}]\"}}}"}

输出 puts:

{"foo":{"bar":{"abc":"[{"ip":"192.168.1.1","hostname":"pc","mac":"01:02:03:04:05:06"}]"}}}

引号中的数组是一个 JSON 值。要使其成为有效的 JSON 数组,还应删除其引号。

因此,为此,您将使用如下内容:

s.gsub(/(\n)|(\)|(\s+)/, '').gsub(/\"\[/, '[').gsub(/\]\"/, ']')

这是完整的测试:

fluent.conf

<source>
  @type forward
  bind 0.0.0.0
  port 8080
  tag test.*
</source>

<filter **>
  @type record_transformer
  enable_ruby true
  <record>
    # message ${ record['message'].gsub(/(\n)|(\)|(\s+)/, '') }
    message ${ m = record['message'].gsub(/(\n)|(\)|(\s+)/, ''); puts m; m; }
  </record>
</filter>

<match **.*>
  @type stdout
</match>

运行 fluentd:

fluentd -c fluent.conf

fluent-cat 发送消息给 fluentd:

echo '{"foo":{"bar":{"abc":"[\n  {\n  \"ip\":\"192.168.1.1\",\n  \"hostname\":\"pc\",\n  \"mac\":\"01:02:03:04:05:06\"\n}  \n]"}}}' | fluent-cat -p 8080 -f none test

fluentd 日志中的输出:

{"foo":{"bar":{"abc":"[{"ip":"192.168.1.1","hostname":"pc","mac":"01:02:03:04:05:06"}]"}}}
2021-05-17 16:22:14.568177376 +0500 test.*: {"message":"{\"foo\":{\"bar\":{\"abc\":\"[{\"ip\":\"192.168.1.1\",\"hostname\":\"pc\",\"mac\":\"01:02:03:04:05:06\"}]\"}}}"}

这会解析未解析的嵌套 json

<filter **>
  @type parser
  key_name $['foo']['bar']['abc']
  hash_value_field parsed_abc
  reserve_data true
  remove_key_name_field true
  <parse>
    @type json
  </parse>
</filter>

<filter **>
  @type record_transformer
  enable_ruby true
  <record>
    parsed_abc ${record['foo']['bar']['abc'] = record['parsed_abc']}
  </record>
  remove_keys parsed_abc
</filter>