Beispiel: „Fancy App“

Beispiel: „Fancy App“

Wir haben viele Produktions-Apps (Erst- und Drittanbieter-Apps), die die Protokollierung dem Prozess überlassen, der die App ausführt, und nur stdoutfür INFOund stderrfür ERRORProtokolle protokollieren (d. h. nur 2 Protokollprioritäten: INFO|ERROR).

Mit einer Systemd-Serviceeinheit für eine App kann dies wie folgt eingerichtet werden:

StandardOutput=journal
StandardError=journal

Auf diese Weise können Entwickler alles über Systemd-Einheiten und das Journal verwalten, um eine zentralisierte Protokollerfassung und -überwachung zu ermöglichen. Außerdem müssen sie sich nicht darum kümmern, für jede bereitgestellte App unterschiedliche Protokolle in unterschiedlichen Formaten/an unterschiedlichen Standorten zu suchen und zu analysieren.

Das Journal von systemd verfügt über ein Nachrichtenprioritätssystem, das mit dem 7-stufigen Nachrichtenprioritätssystem von syslog kompatibel ist. INFOist Stufe 6und ERRORist Stufe 3. Weitere Einzelheiten finden Sie in den Referenzen.

Das Problem ist, dass systemd/journal anscheinend nicht zwischen Nachrichten unterscheidet, die von stdout oder stderr ins Journal geschrieben werden. Sowohl stdout- als auch stderr-Nachrichten werden alle mit der Standardpriorität 6 ( INFO) ins Journal geschrieben.

Beispiel: „Fancy App“

/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

Führen Sie es aus und überprüfen Sie das Journal

$ 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 --
$

Sie können sehen, dass sowohl stderr- als auch stdout-Nachrichten beim Schreiben in das Journal auf Priorität 6( ) gesetzt werden.INFO

stdio->journalDies ist ein Problem, da wir bei Verwendung als primäre Protokollierungseinrichtung keine einfache Möglichkeit haben, zwischen der Ausgabe auf stdout und stderr zu unterscheiden .

Dies warbereits besprochenUndLösungensind möglich, abernicht implementiert. Ich hoffe, dass das systemd-Team dies irgendwann implementiert, aber in der Zwischenzeit brauche ich eine Lösung.

Hat jemand eine vernünftige Lösung gefunden, um Nachrichten, die an stdout und stderr geschrieben werden, mit unterschiedlichen Prioritäten im Journal zu versehen?ohne die Protokollierung einer App zu ändern?

Ich möchte nicht, dass alle von uns bereitgestellten Apps (die nicht alle von uns geschrieben wurden) Journal- oder Syslog-Integrationen implementieren müssen, um Protokollpriorität zu erhalten, wenn wir wirklich nur zwei Ebenen benötigen: INFO(stdout) und ERROR(stderr).

Viele unserer Bereitstellungen sind nicht in Containern untergebracht. Daher ist es für uns auch keine Lösung, uns auf die Protokollierungsfunktionen des Containers zu verlassen.

Dass stderr und stdout standardmäßig mit unterschiedlichen Prioritäten ins Journal/Syslog gehen, ist ziemlich wichtig, um die verteilte Überwachung von Protokollfehlern zu vereinfachen (vorausgesetzt, die Entwickler sind gewissenhaft und schreiben nur Dinge in stderr, die ihre Aufmerksamkeit erfordern).

Verweise:

Antwort1

stdoutWenn Sie / verwenden müssen stderr, können Sie verwendensd-daemon Protokollierungspräfix.

Stellen Sie Ihrem „ stderrmit“ voran <3>, um ein ERRORPrioritätsprotokoll zu senden journald.

Verwenden Sie Ihre log-test.shund log-test.service:

#!/bin/bash

>&2 echo "<3>This is ERROR"
echo "This is INFO"

exit 0

Und journalctlAusgabe:

$ journalctl -u log-test -p 3
May 02 01:22:58 host.example.com log-test.sh[29909]: This is ERROR

Wenn Ihr fancy-appüber eine API zum Schreiben verfügt syslog, können Sie diese zum Schreiben in ein UNIX-Datagramm verwenden /dev/log(normalerweise standardmäßig beschreibbar und protokolliert in journald) statt in stdout/ stderr. Verwenden Sie den Syslog-Tag, um Ihr zu identifizieren fancy-app, die Syslog-Priorität auf erroroder infoje nach Bedarf und jede Syslog-Funktion.

Beispielsweise können wir in Bash verwendenlogger:

# 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

Beachten Sie, dass in den meisten Distributionen journaldEinträge normalerweise an den lokalen Syslog-Daemon ( syslog-ng, rsyslog, …) weitergeleitet werden. Überprüfen Sie daher am besten Ihre Syslog-Filter oder verwenden Sie local0local7-Funktionen.

Wir haben viele Produktions-Apps (Erst- und Drittanbieter-Apps), die die Protokollierung dem Container überlassen und für INFO-Protokolle nur in stdout und für ERROR-Protokolle nur in stderr protokollieren (d. h. nur 2 Protokollprioritäten: INFO|ERROR).

Die meisten Container-Engines sollten in der Lage sein, in Syslog zu protokollieren. Ohne Ihre Container-Engine zu kennen, verwende ich Docker als Beispiel.

Docker hatSyslog-ProtokollierungstreiberDamit können Protokollnachrichten im Syslog-Format an jedes Syslog-Ziel gesendet werden. Sie sollten sich journaldmit etwas wie Folgendem anmelden können:

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 hat auchJournald-Protokollierungstreiberverfügbar. Zum Beispiel:

docker run \
    --log-driver journald \
    --log-opt tag=fancy-app \
    fancy-app:latest

Beide Protokollierungstreiber (SyslogUndTagebuch) unterstützt die Trennung zwischen stdoutund stderr; d. h. stdoutNachrichten werden mit INFOPriorität protokolliert und stderrNachrichten werden mit ERRORPriorität protokolliert.

Philosophien und Flame Wars beiseite, warum loggen Sie nicht in ein echtes Syslog? Es ist einfacher, wird im Textformat gespeichert und wird im Allgemeinen von Protokollverwaltungssoftware unterstützt (sieheGraylog,Logstash,Papier Spur).

verwandte Informationen