简体   繁体   English

Systemd 服务和结构化日志记录

[英]Systemd service and structured logging

I have a systemd service which is of type simple .我有一个 systemd 服务,它的类型是simple

I want my service to log key-value pairs.我希望我的服务记录键值对。

Up to now my simple service just prints it log to stdout in a custom key-value syntax.到目前为止,我的简单服务只是以自定义键值语法将它的日志打印到标准输出。

I would like to avoid my custom key-value syntax it use an official way to do structured logging.我想避免我的自定义键值语法,它使用官方方式进行结构化日志记录。

Is there a way to use structured logs with systemd?有没有办法在 systemd 中使用结构化日志?

For example my service writes this to stdout:例如,我的服务将其写入标准输出:

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

It would be great of systemd could read the string as json. systemd 可以将字符串读取为 json 会很棒。

You can log structured data to systemd and then view it as is or in json format您可以将结构化数据记录到systemd ,然后按原样或以 json 格式查看

Let's say we log key-value pairs in json format假设我们以 json 格式记录键值对

systemd-cat -t "struct_logs" echo '{"key1": "value1", "key2": 1234}'

Then we read them as is然后我们按原样阅读它们

sudo journalctl -t 'struct_logs' --lines 1 --no-pager

Apr 30 21:46:14 linux-ar struct_logs[17455]: {"key1": "value1", "key2": 1234}

Or in json format或者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"
}

Going further you can recover your exact log messages with the help of jq更进一步,您可以在jq的帮助下恢复准确的日志消息

sudo journalctl -t 'struct_logs' --lines 1 --no-pager -o json-pretty | jq -r '.MESSAGE'
{"key1": "value1", "key2": 1234}

It could be possible also to log custom keys provided that the user has the proper rights to do that.如果用户有适当的权限,也可以记录自定义密钥。 A service should be able to do that服务应该能够做到这一点

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

Hope this helps.希望这可以帮助。

Have a look at Structured logging to journald from within a docker container ;查看从 docker 容器内记录到日志的结构化日志记录 your application should use the sd_journal_send method if you want to specify custom fields.如果您想指定自定义字段,您的应用程序应该使用sd_journal_send方法。

If your application is unable to do that you can also output json - which will end up in the MESSAGE field you can then parse yourself.如果您的应用程序无法执行此操作,您还可以输出 json - 它将最终出现在MESSAGE字段中,然后您可以自己解析。 For example - I wrote SystemdJournal2Gelf to send the journal entries to Graylog and it also supports json output in the MESSAGE , sending it to Graylog as separate fields for filtering例如 - 我编写了SystemdJournal2Gelf来将日志条目发送到 Graylog,它还支持MESSAGE json 输出,将其作为单独的字段发送到 Graylog 进行过滤

If you don't want to modify the application you could use a separate script - something like this:如果您不想修改应用程序,您可以使用单独的脚本 - 如下所示:

[Service]
ExecStart=/bin/sh -c '/bin/my-app | while read l; do echo "$l" | logger --journald; done'

You could even convert json to key/value pairs if you want, or use StandardOutput to send your standard-output to a socket where you have a separate service listening.如果需要,您甚至可以将json转换为键/值对,或者使用StandardOutput将您的标准输出发送到您有单独服务侦听的套接字。

Well, systemd does not make it easy to do structured logging from text stream.好吧,systemd 并没有让从文本流中进行结构化日志记录变得容易。 It want your to take a dependencies on its library and use sd_journal_send (see for example http://0pointer.de/blog/projects/journal-submit.html ).它希望您依赖其库并使用sd_journal_send (例如参见http://0pointer.de/blog/projects/journal-submit.html )。 I have not found any "text form" standard that allow systemd to understand that your line should not be smushed together in the MESSAGE fields but rather should be interpreted as a key-value pair.我还没有找到任何允许 systemd 理解您的行不应该在MESSAGE字段中混在一起的“文本形式”标准,而应该被解释为键值对。 I guess a solution would be to write a helper process that parse your stdout and then call the systemd logger.我想一个解决方案是编写一个帮助程序来解析您的标准输出,然后调用 systemd 记录器。 You would then pipe your process stdout process into然后,您将通过管道将您的流程标准输出流程导入

However, I did found this answer that pipe directly into the journald socket.但是,我确实找到了这个答案该答案将管道直接插入到日志套接字中。 With clever use of jq, you could write something that exploit that.通过巧妙地使用 jq,您可以编写一些利用它的东西。 But that seems hacky: I do not know if systemd really intend to keep any compatibility on that socket.但这似乎很棘手:我不知道 systemd 是否真的打算在该套接字上保持任何兼容性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM