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>
我在 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>