stdout
当社には、ログ記録をアプリを実行するプロセスに任せ、およびINFO
のログstderr
にのみログを記録するERROR
(つまり、ログの優先順位は 2 つだけである)運用アプリ (ファースト パーティおよびサードパーティ) が多数ありますINFO|ERROR
。
アプリ用の systemd サービス ユニットでは、次のように設定できます。
StandardOutput=journal
StandardError=journal
これにより、DevOps は systemd ユニットとジャーナルを通じてすべてを管理し、集中的なログ収集やあらゆる監視を容易にできるようになります。また、展開するアプリごとに異なる形式や場所にあるさまざまなログを見つけて解析する必要がなくなります。
systemd のジャーナルには、syslog の 7 レベルのメッセージ優先度システムと互換性のあるメッセージ優先度システムがあります。 INFO
はレベル6
で、ERROR
はレベル です3
。詳細については、参考資料を参照してください。
問題は... systemd/journal が、ジャーナルに書き込まれるメッセージを stdout と stderr から区別していないことです。stdout と stderr の両方のメッセージは、デフォルトの優先度 6 ( INFO
) でジャーナルに書き込まれます。
例: 「ファンシーアプリ」
/opt/log-test.sh
#!/bin/bash
echo "This is ERROR" 1>&2
echo "This is INFO"
exit 0
/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
実行してジャーナルをチェックする
$ 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 --
$
ジャーナルに書き込まれるときに、 stderr と stdout の両方のメッセージが優先度6
( )に設定されていることがわかります。INFO
stdio->journal
これは、主要なログ機能として使用するときに、stdout と stderr の出力を区別する簡単な方法がないため、問題になります。
これは前に議論したそしてソリューション可能ですが、実装されていないsystemd チームが最終的にこれを実装することを期待していますが、その間に解決策が必要です。
stdoutとstderrに書き込まれたメッセージをジャーナル内で異なる優先順位にするための合理的な解決策を見つけた人はいますか?アプリのログ記録方法を変更せずに?
INFO
実際に必要となるのは(stdout) と(stderr)の 2 つのレベルだけなのに、私たちが展開するすべてのアプリ (すべて私たちが作成したものではありません) で、ログの優先順位を取得するためにジャーナルまたは syslog の統合を実装しなければならない状況は避けたいと考えERROR
ています。
私たちが展開するものの多くはコンテナ化されていないため、コンテナのログ機能に頼るのも解決策にはなりません。
stderr と stdout がデフォルトで異なる優先順位で journal/syslog に送信されることは、分散ログ エラー監視を容易にするために非常に重要です (stderr に注意が必要な内容のみを記述するという開発者の健全な衛生状態を前提としています)。
参考文献:
答え1
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
出力は次のようになりjournalctl
ます:
$ journalctl -u log-test -p 3
May 02 01:22:58 host.example.com log-test.sh[29909]: This is ERROR
fancy-app
に書き込むための API がある場合は、それを使用して/の代わりにUNIX データグラム(通常はデフォルトで書き込み可能で、 にログが記録されます)syslog
に書き込むことができます。 、必要に応じてまたはへの syslog 優先度、および syslog 機能を識別するには syslog タグを使用します。/dev/log
journald
stdout
stderr
fancy-app
error
info
例えば、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
ほとんどのディストリビューjournald
ションでは、エントリは通常、ローカル syslog デーモン ( syslog-ng
、、rsyslog
...) に転送されるので、syslog フィルターを確認するか、local0
...local7
機能を使用する必要があることに注意してください。
当社には、ログ記録をコンテナに任せ、INFO ログについては stdout に、ERROR ログについては stderr にのみログを記録する (つまり、ログの優先順位は INFO|ERROR の 2 つのみ) 運用アプリ (ファースト パーティおよびサードパーティ) が多数あります。
ほとんどのコンテナ エンジンは syslog にログを記録できるはずです。コンテナ エンジンがわからないため、例として Docker を使用します。
Dockerはsyslog ロギング ドライバーjournald
syslog 形式を使用してログ メッセージを任意の syslog ターゲットに送信するために使用できます。次のようにログに記録できるはずです。
docker run \
--log-driver syslog \
--log-opt syslog-address=unix:///dev/log \
--log-opt syslog-facility=user \
--log-opt tag=fancy-app \
fancy-app:latest
Dockerにはjournald ログドライバー利用可能です。例:
docker run \
--log-driver journald \
--log-opt tag=fancy-app \
fancy-app:latest
両方のロギングドライバー(シスログそしてジャーナルstdout
) は、 との分離をサポートしますstderr
。つまり、stdout
メッセージは priority とともにログに記録されINFO
、メッセージはprioritystderr
とともにログに記録されます。ERROR
哲学や炎上はさておき、なぜ実際のsyslogにログを記録しないのでしょうか?それはより簡単で、テキスト形式で保存され、一般的にログ管理ソフトウェアでサポートされています(グレイログ、ログスタッシュ、ペーパートレイル)。