我有一个类型为simple
的systemd服务。
我希望我的服务记录键值对。
到目前为止,我的简单服务只是使用自定义键值语法将其日志打印到stdout。
我想避免使用自定义键值语法,而是使用一种正式的方式进行结构化日志记录。
是否可以在systemd中使用结构化日志?
例如,我的服务将此内容写入stdout:
{"key1": "value1", "key2": 1234}
systemd可以将字符串读取为json很棒。
答案 0 :(得分:3)
您可以将结构化数据记录到systemd
,然后按原样或json格式查看
假设我们以json格式记录键值对
systemd-cat -t "struct_logs" echo '{"key1": "value1", "key2": 1234}'
然后我们按原样阅读
sudo journalctl -t 'struct_logs' --lines 1 --no-pager
Apr 30 21:46:14 linux-ar struct_logs[17455]: {"key1": "value1", "key2": 1234}
或json格式
sudo journalctl -t 'struct_logs' --lines 1 --no-pager -o json-pretty
{
"__CURSOR" : "s=b6d07ffffffffff2787cea140a0db88a5;i=db8;b=c9b2132ffffffffe5807625fe;m=9fa5b3f81;t=58fffffff87eab;x=6402818ea7e32a5b",
"__REALTIME_TIMESTAMP" : "1556671574343339",
"__MONOTONIC_TIMESTAMP" : "42854989697",
"_BOOT_ID" : "fffffffffffff24ec7a237b5e5807625fe",
"PRIORITY" : "6",
"_MACHINE_ID" : "fffffffffff66c86aaaaaaaaaa",
"_HOSTNAME" : "linux-ar",
"_TRANSPORT" : "stdout",
"_UID" : "1000",
"_GID" : "100",
"SYSLOG_IDENTIFIER" : "struct_logs",
"MESSAGE" : "{\"key1\": \"value1\", \"key2\": 1234}",
"_PID" : "17455"
}
更进一步,您可以借助jq
sudo journalctl -t 'struct_logs' --lines 1 --no-pager -o json-pretty | jq -r '.MESSAGE'
{"key1": "value1", "key2": 1234}
如果用户具有适当的权限,也可以记录自定义密钥。服务应该能够做到这一点
sudo logger --journald <<end
MESSAGE_ID=67feb6ffbaf24c5cbec13c008dd72309
MESSAGE=The dogs bark, but the caravan goes on.
SYSLOG_IDENTIFIER=struct_logs
KEY=bark
VALUE=goes on
end
希望这会有所帮助。
答案 1 :(得分:1)
好吧,systemd使得从文本流进行结构化日志记录变得不容易。它希望您依赖其库并使用sd_journal_send
(例如,参见http://0pointer.de/blog/projects/journal-submit.html)。我还没有找到任何“文本格式”标准,该标准允许systemd理解您的行不应在MESSAGE
字段中混在一起,而应解释为键值对。我猜一个解决方案是编写一个帮助程序,解析您的标准输出,然后调用systemd记录器。然后,您可以将流程stdout流程通过管道传输到
但是,我确实发现this answer可以通过管道直接插入带日志的套接字。通过巧妙地使用jq,您可以编写可利用该功能的东西。但这似乎很hacky:我不知道systemd是否真的打算在该套接字上保持任何兼容性。
答案 2 :(得分:0)
看看Structured logging to journald from within a docker container;如果要指定自定义字段,则您的应用程序应使用sd_journal_send
方法。
如果您的应用程序无法执行此操作,则还可以输出json-最终将在MESSAGE
字段中进行输出,然后您可以自行分析。例如-我写了SystemdJournal2Gelf来将日记条目发送到Graylog,它还支持MESSAGE
中的json输出,并将其作为单独的字段发送到Graylog进行过滤
如果您不想修改应用程序,则可以使用单独的脚本-像这样:
[Service]
ExecStart=/bin/sh -c '/bin/my-app | while read l; do echo "$l" | logger --journald; done'
如果愿意,您甚至可以将json
转换为键/值对,或者使用StandardOutput
将标准输出发送到套接字,您可以在其中监听单独的服务。