为通过 stdout 和 stderr 记录到日志的消息设置 INFO/ERROR 优先级?

mat*_*tpr 3 monitoring logging systemd journald centralized-logging

我们有许多生产应用程序(第一方和第三方),它们将日志记录留给运行应用程序的进程,而只记录stdoutforINFOstderrforERROR日志(即只有 2 个日志优先级:)INFO|ERROR

对于应用程序的 systemd 服务单元,可以这样设置:

StandardOutput=journal
StandardError=journal
Run Code Online (Sandbox Code Playgroud)

这使得 DevOps 可以通过 systemd 单元和日志来管理一切,以便于集中日志收集、监控任何内容……并且他们不需要担心为部署的每个应用程序定位和解析不同格式/位置的不同日志。

systemd 的日志具有与 syslog 的 7 级消息优先级系统兼容的消息优先级系统。 INFO是水平6ERROR是水平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 的内容)。

参考:

mfo*_*tti 5

如果必须使用stdout/ stderr,则可以使用sd-daemon 日志前缀

在前面添加stderr<3>发送ERROR优先级journald日志。

使用你的log-test.shlog-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-appsyslog 优先级errorinfo根据您的需要以及任何 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-ngrsyslog、 ...),因此可能检查您的系统日志过滤器,或者可能使用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)

两个日志记录驱动程序(syslogjournaldstdout )都支持和之间的分离stderr;即stdout消息将被INFO优先记录,stderr消息将被优先记录ERROR

抛开哲学和激烈的战争不谈,为什么不记录到真正的系统日志呢?它更容易,以文本格式存储,并且通常由日志管理软件支持(参见GraylogLogstashPapertrail)。