Ejemplo: "Aplicación elegante"

Ejemplo: "Aplicación elegante"

Tenemos muchas aplicaciones de producción (propias y de terceros) que dejan el registro en el proceso que ejecuta la aplicación y simplemente inician sesión en los registros stdoutfor INFOy stderrfor ERROR(es decir, solo 2 prioridades de registro INFO|ERROR:).

Con una unidad de servicio systemd para una aplicación, esto se puede configurar de esta manera:

StandardOutput=journal
StandardError=journal

Esto permite a los desarrolladores administrar todo a través de unidades systemd y el diario para facilitar la recopilación de registros centralizados, monitorear lo que sea... y no necesitan preocuparse por ubicar y analizar diferentes registros en diferentes formatos/ubicaciones para cada aplicación que implementan.

El diario de systemd tiene un sistema de prioridad de mensajes compatible con el sistema de prioridad de mensajes de 7 niveles de syslog. INFOestá nivelado 6y ERRORestá nivelado 3. Ver referencias para más detalles.

El problema es... systemd/journal aparentemente no distingue entre los mensajes escritos en el diario desde stdout y stderr. Tanto los mensajes stdout como stderr se escriben en el diario con una prioridad predeterminada de 6 ( INFO).

Ejemplo: "Aplicación elegante"

/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

ejecútelo y revise el diario

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

Puede ver que tanto los mensajes stderr como stdout tienen prioridad 6( INFO) cuando se escriben en el diario.

Esto es un problema porque no tenemos una manera fácil de diferenciar la salida en stdout vs stderr cuando se usa stdio->journalcomo función de registro principal.

Esto ha sidodiscutido antesysolucionesson posibles, perono se ha implementado. Espero que el equipo de systemd finalmente implemente esto, pero mientras tanto necesito una solución.

¿Alguien ha encontrado una solución razonable para que los mensajes escritos en stdout y stderr sean prioridades diferentes en el diario?sin modificar la forma en que una aplicación registra?

No quiero que todas las aplicaciones que implementamos (no todas escritas por nosotros) tengan que implementar integraciones de diario o syslog para obtener prioridad de registro cuando en realidad solo necesitamos dos niveles: INFO(stdout) y ERROR(stderr).

Gran parte de lo que implementamos no está en contenedores, por lo que depender de las instalaciones de registro del contenedor tampoco es una solución para nosotros.

Hacer que stderr y stdout vayan a diario/syslog con diferentes prioridades de forma predeterminada es bastante crítico para facilitar el monitoreo de errores de registros distribuidos (suponiendo una buena higiene del desarrollador acerca de escribir solo cosas que necesitan atención en stderr).

Referencias:

Respuesta1

Si tienes que usar stdout/ stderr, puedes usarsd-daemon prefijo de registro.

Anteponga su stderrcon <3>para enviar un registro ERRORde prioridad journald.

Usando tu log-test.shy log-test.service:

#!/bin/bash

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

exit 0

Y journalctlsalida:

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

Si fancy-apptiene alguna API para escribir syslog, puede usarla para escribir en un datagrama UNIX /dev/log(generalmente se puede escribir de forma predeterminada y se registra en journald) en lugar de stdout/ stderr. Utilice la etiqueta syslog para identificar su fancy-appprioridad syslog errorsegún infosus necesidades y cualquier instalación de syslog.

Por ejemplo, en Bash podemos usarlogger:

# 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

Tenga en cuenta que en la mayoría de las distribuciones journaldlas entradas generalmente se reenvían al demonio syslog local ( syslog-ng,, rsyslog...), por lo que probablemente verifique sus filtros syslog, o tal vez use local0... local7instalaciones.

Tenemos muchas aplicaciones de producción (propias y de terceros) que dejan el registro en el contenedor y simplemente inician sesión en stdout para INFORMACIÓN y stderr para registros de ERROR (es decir, solo 2 prioridades de registro: INFORMACIÓN|ERROR).

La mayoría de los motores de contenedores deberían poder iniciar sesión en syslog. Sin conocer su motor de contenedores, usaré Docker como ejemplo.

Docker tienecontrolador de registro syslogque se puede utilizar para enviar mensajes de registro utilizando el formato syslog a cualquier destino syslog. Deberías poder iniciar sesión journaldcon algo como:

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 también tienecontrolador de registro diariodisponible. Por ejemplo:

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

Ambos controladores de registro (registro del sistemaydiario) apoya la separación entre stdouty stderr; es decir, stdoutlos mensajes se registrarán con INFOprioridad y stderrlos mensajes se registrarán con ERRORprioridad.

Dejando a un lado las filosofías y las guerras incendiarias, ¿por qué no iniciar sesión en un syslog real? Es más fácil, se almacena en formato de texto y generalmente es compatible con software de gestión de registros (consultetronco gris,Logstash,Rastro de papel).

información relacionada