У нас есть много производственных приложений (собственных и сторонних), которые оставляют ведение журнала на усмотрение процесса, запускающего приложение, и просто ведут журналы stdout
в INFO
и stderr
для ERROR
журналов (т. е. всего 2 приоритета журналов: INFO|ERROR
).
С помощью служебного модуля systemd для приложения это можно настроить следующим образом:
StandardOutput=journal
StandardError=journal
Это позволяет разработчикам управлять всем через модули systemd и журнал, чтобы обеспечить централизованный сбор журналов, мониторинг всего остального... и им не нужно беспокоиться о поиске и анализе различных журналов в разных форматах/местоположениях для каждого развертываемого ими приложения.
Журнал systemd имеет систему приоритетов сообщений, совместимую с 7-уровневой системой приоритетов сообщений syslog. INFO
is level 6
и ERROR
is level 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
) при записи в журнал.
Это проблема, поскольку у нас нет простого способа дифференцировать вывод на stdout и stderr при использовании stdio->journal
в качестве основного средства ведения журнала.
Это былообсуждалось ранееирешениявозможны, ноне реализована. Я надеюсь, что команда systemd в конечном итоге реализует это, но пока мне нужно решение.
Нашел ли кто-нибудь разумное решение, чтобы сообщения, записанные в stdout и stderr, имели разные приоритеты в журнале?без изменения того, как приложение ведет журнал?
Я не хочу, чтобы все приложения, которые мы развертываем (не все написаны нами), были вынуждены реализовывать интеграцию журналов или системных журналов для получения приоритета журнала, когда нам на самом деле нужны только два уровня: INFO
(stdout) и ERROR
(stderr).
Большая часть того, что мы развертываем, не контейнеризирована, поэтому полагаться на возможности контейнеризации также не является для нас решением.
Наличие по умолчанию разных приоритетов для stderr и stdout, направляемых в журнал/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 для записи syslog
, вы можете использовать его для записи в UNIX-датаграмму /dev/log
(обычно доступную для записи по умолчанию и регистрируемую в journald
) вместо stdout
/ stderr
. Используйте тег syslog для идентификации вашего fancy-app
, приоритета syslog error
или info
в зависимости от ваших потребностей, а также любого средства 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
Обратите внимание, что в большинстве дистрибутивов journald
записи обычно перенаправляются локальному демону syslog ( syslog-ng
, rsyslog
, ...), поэтому, вероятно, проверьте фильтры syslog или, возможно, используйте local0
... local7
средства.
У нас есть много производственных приложений (собственных и сторонних), которые оставляют ведение журнала на усмотрение контейнера и просто выводят журналы INFO на stdout и ERROR на stderr (т. е. всего 2 приоритета журнала: INFO|ERROR).
Большинство контейнерных движков должны уметь логировать в syslog. Не зная вашего контейнерного движка, я буду использовать Docker в качестве примера.
У Докера естьдрайвер ведения журнала syslogкоторый может быть использован для отправки сообщений журнала с использованием формата syslog на любую цель syslog. Вы должны иметь возможность войти в систему journald
с помощью чего-то вроде:
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
У Докера также естьдрайвер журналирования journaldдоступно. Например:
docker run \
--log-driver journald \
--log-opt tag=fancy-app \
fancy-app:latest
Оба драйвера регистрации (системный журналижурналd) поддерживает разделение между stdout
и stderr
; т. е. stdout
сообщения будут регистрироваться с INFO
приоритетом, а stderr
сообщения будут регистрироваться с ERROR
приоритетом.
Оставив в стороне философию и флеймовые войны, почему бы не вести журнал в реальном syslog? Это проще, хранится в текстовом формате и, как правило, поддерживается программным обеспечением для управления журналами (см.Грейлог,Logstash,Papertrail).