例: 「ファンシーアプリ」

例: 「ファンシーアプリ」

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/ を使用する必要がある場合はstderrsd-daemon ログ記録プレフィックス

優先ログを送信するには、stderr先頭に を付けます。<3>ERRORjournald

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/logjournaldstdoutstderrfancy-apperrorinfo

例えば、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 ロギング ドライバーjournaldsyslog 形式を使用してログ メッセージを任意の 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にログを記録しないのでしょうか?それはより簡単で、テキスト形式で保存され、一般的にログ管理ソフトウェアでサポートされています(グレイログログスタッシュペーパートレイル)。

関連情報