mat*_*tpr 3 monitoring logging systemd journald centralized-logging
我们有许多生产应用程序(第一方和第三方),它们将日志记录留给运行应用程序的进程,而只记录stdout
forINFO
和stderr
forERROR
日志(即只有 2 个日志优先级:)INFO|ERROR
。
对于应用程序的 systemd 服务单元,可以这样设置:
StandardOutput=journal
StandardError=journal
Run Code Online (Sandbox Code Playgroud)
这使得 DevOps 可以通过 systemd 单元和日志来管理一切,以便于集中日志收集、监控任何内容……并且他们不需要担心为部署的每个应用程序定位和解析不同格式/位置的不同日志。
systemd 的日志具有与 syslog 的 7 级消息优先级系统兼容的消息优先级系统。 INFO
是水平6
,ERROR
是水平3
。有关更多详细信息,请参阅参考资料。
问题是... systemd/journal 显然不区分从 stdout 与 stderr 写入日志的消息。stdout 和 stderr 消息都以默认优先级 6 ( ) 写入日志INFO
。
/opt/log-test.sh
StandardOutput=journal
StandardError=journal
Run Code Online (Sandbox Code Playgroud)
/etc/systemd/system/log-test.service
[Unit]
Description=log test for journal
[Service]
Type=simple
ExecStart=/opt/log-test.sh
StandardOutput=journal
StandardError=journal
SyslogIdentifier=log-test
Run Code Online (Sandbox Code Playgroud)
$ systemctl start log-test
$ journalctl -u log-test
-- Logs begin at Thu 2022-04-07 08:17:16 UTC, end at Thu 2022-04-07 16:35:02 UTC. --
Apr 07 16:34:58 host.example.com systemd[1]: Started log test for journal.
Apr 07 16:34:58 host.example.com log-test.sh[29909]: This is ERROR
Apr 07 16:34:58 host.example.com log-test.sh[29909]: This is INFO
$ journalctl -u log-test -p 6 # syslog info priority
-- Logs begin at Thu 2022-04-07 08:17:16 UTC, end at Thu 2022-04-07 16:35:08 UTC. --
Apr 07 16:34:58 host.example.com systemd[1]: Started log test for journal.
Apr 07 16:34:58 host.example.com log-test.sh[29909]: This is ERROR
Apr 07 16:34:58 host.example.com log-test.sh[29909]: This is INFO
$ journalctl -u log-test -p 3 # syslog error priority
-- No entries --
$
Run Code Online (Sandbox Code Playgroud)
您可以看到,当写入日志时,stderr 和 stdout 消息都设置为优先级6
( )。INFO
stdio->journal
这是一个问题,因为当用作主要日志记录工具时,我们没有一种简单的方法来区分 stdout 和 stderr 上的输出。
之前已经讨论过这个问题,并且解决方案是可能的,但尚未实施。我希望 systemd 团队最终能够实现这一点,但同时我需要一个解决方案。
有没有人找到一个合理的解决方案,让写入 stdout 和 stderr 的消息在日志中具有不同的优先级,而无需修改应用程序的日志记录方式?
我不希望我们部署的所有应用程序(并非全部由我们编写)都必须实现日志或系统日志集成,以便在我们实际上只需要两个级别:INFO
(stdout)和ERROR
(stderr)时获得日志优先级。
我们部署的大部分内容都不是容器化的,因此依赖容器的日志记录设施也不是我们的解决方案。
默认情况下,让 stderr 和 stdout 以不同的优先级进入日志/系统日志对于使分布式日志错误监控变得更容易非常关键(假设开发人员良好的卫生习惯,只编写需要注意 stderr 的内容)。
如果必须使用stdout
/ stderr
,则可以使用sd-daemon
日志前缀。
在前面添加stderr
来<3>
发送ERROR
优先级journald
日志。
使用你的log-test.sh
和log-test.service
:
#!/bin/bash
>&2 echo "<3>This is ERROR"
echo "This is INFO"
exit 0
Run Code Online (Sandbox Code Playgroud)
并journalctl
输出:
$ journalctl -u log-test -p 3
May 02 01:22:58 host.example.com log-test.sh[29909]: This is ERROR
Run Code Online (Sandbox Code Playgroud)
如果您fancy-app
有任何可写入的 API syslog
,则可以使用它来写入 UNIX 数据报/dev/log
(通常默认情况下可写,并记录到journald
)而不是stdout
/ stderr
。使用 syslog 标签来识别您的fancy-app
syslog 优先级error
或info
根据您的需要以及任何 syslog 工具。
例如,在 Bash 中我们可以使用logger
:
# emit INFO message to journalctl
$ logger -t fancy-app -u /dev/log -p user.info "This is INFO"
# emit ERROR message to journalctl
$ logger -t fancy-app -u /dev/log -p user.error "This is ERROR"
# show journald messages for fancy-app
$ journalctl -t fancy-app
May 02 01:23:38 host.example.com fancy-app[27302]: This is INFO
May 02 01:23:39 host.example.com fancy-app[27303]: This is ERROR
# show journald ERROR messages for fancy-app
$ journalctl -t fancy-app -p 3
May 02 01:23:39 host.example.com fancy-app[27303]: This is ERROR
Run Code Online (Sandbox Code Playgroud)
请注意,在大多数发行版中journald
,条目通常转发到本地系统日志守护程序(syslog-ng
、rsyslog
、 ...),因此可能检查您的系统日志过滤器,或者可能使用local0
...local7
设施。
我们有许多生产应用程序(第一方和第三方)将日志记录保留到容器中,仅将信息记录到 stdout,将错误日志记录到 stderr(即只有 2 个日志优先级:INFO|ERROR)。
大多数容器引擎应该能够记录到系统日志。在不了解容器引擎的情况下,我将使用 Docker 作为示例。
Docker 具有syslog 日志记录驱动程序,可用于使用 syslog 格式将日志消息发送到任何 syslog 目标。您应该能够使用journald
以下内容登录:
$ journalctl -u log-test -p 3
May 02 01:22:58 host.example.com log-test.sh[29909]: This is ERROR
Run Code Online (Sandbox Code Playgroud)
Docker 还提供可用的日志记录驱动程序。例如:
# emit INFO message to journalctl
$ logger -t fancy-app -u /dev/log -p user.info "This is INFO"
# emit ERROR message to journalctl
$ logger -t fancy-app -u /dev/log -p user.error "This is ERROR"
# show journald messages for fancy-app
$ journalctl -t fancy-app
May 02 01:23:38 host.example.com fancy-app[27302]: This is INFO
May 02 01:23:39 host.example.com fancy-app[27303]: This is ERROR
# show journald ERROR messages for fancy-app
$ journalctl -t fancy-app -p 3
May 02 01:23:39 host.example.com fancy-app[27303]: This is ERROR
Run Code Online (Sandbox Code Playgroud)
两个日志记录驱动程序(syslog和journaldstdout
)都支持和之间的分离stderr
;即stdout
消息将被INFO
优先记录,stderr
消息将被优先记录ERROR
。
抛开哲学和激烈的战争不谈,为什么不记录到真正的系统日志呢?它更容易,以文本格式存储,并且通常由日志管理软件支持(参见Graylog、Logstash、Papertrail)。