【问题标题】:Systemd service and structured logging系统服务和结构化日志记录
【发布时间】:2019-09-12 09:15:05
【问题描述】:

我有一个 simple 类型的 systemd 服务。

我希望我的服务记录键值对。

到目前为止,我的简单服务只是以自定义键值语法将其日志打印到标准输出。

我想避免我的自定义键值语法,它使用官方方式进行结构化日志记录。

有没有办法在 systemd 中使用结构化日志?

例如,我的服务将其写入标准输出:

{"key1": "value1", "key2": 1234}

如果 systemd 可以将字符串读取为 json,那就太好了。

【问题讨论】:

  • 请举例说明实际的应用程序日志记录和预期输出。

标签: logging systemd systemd-journald


【解决方案1】:

您可以将结构化数据记录到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

希望这会有所帮助。

【讨论】:

  • 我使用“简单”服务类型。有没有办法让流程的标准输出进入结构化的 journalctl?
  • 如果我正确理解了您的答案,那么 json 只是 systemd/journalctl 的字符串。
  • 是的,只是一个字符串。
【解决方案2】:

看看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 将标准输出发送到您有单独的服务侦听的套接字。

【讨论】:

  • 我也一直在考虑这样的包装器。但我不确定如果你包装了真正的服务,重新启动的信号处理是否仍然有效。
【解决方案3】:

好吧,systemd 并不容易从文本流中进行结构化日志记录。它希望您依赖其库并使用 sd_journal_send (例如参见 http://0pointer.de/blog/projects/journal-submit.html )。我还没有找到任何允许 systemd 理解您的行不应该在 MESSAGE 字段中混合在一起而是应该被解释为键值对的“文本表单”标准。我想一个解决方案是编写一个帮助程序来解析您的标准输出,然后调用 systemd 记录器。然后,您会将您的流程标准输出流程通过管道传输到

但是,我确实找到了 this answer 直接进入日志套接字的管道。通过巧妙地使用 jq,您可以编写一些利用它的东西。但这似乎很老套:我不知道 systemd 是否真的打算在该套接字上保持任何兼容性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多