Skip to content

fix(logging): emit the log level in JSON logs - #15

Merged
fey merged 1 commit into
mainfrom
fix/logback-loglevel-provider
Aug 4, 2026
Merged

fix(logging): emit the log level in JSON logs#15
fey merged 1 commit into
mainfrom
fix/logback-loglevel-provider

Conversation

@fey

@fey fey commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Проблема

В JSON-логах приложения нет уровня логирования. Замечено наставником при разборе проекта «Доска объявлений (Observability)» — там шаг про Promtail/Loki опирается на то, что логи уже в JSON и пригодны для фильтрации по уровню.

Симптом выглядел странно: поля app, environment и instance из того же самого appender'а пишутся, а level — нет.

Причина

В logback-spring.xml провайдер назывался <level/>. В logstash-logback-encoder такого провайдера нет: LoggingEventJsonProviders предоставляет addLogLevel и addLogLevelValue, но не addLevel. Logback молча выбрасывал неизвестный элемент, оставив лишь строку в своём startup-статусе:

|-WARN in ch.qos.logback.core.model.processor.ImplicitModelHandler -
Ignoring unknown property [level] in
[net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders]

app/environment/instance выживали потому, что приходят из отдельного, валидного провайдера <pattern>.

Поэтому баг и было легко не заметить: сборка не падала, логи оставались валидным JSON, просто одного поля тихо не было.

Фикс

<level/><logLevel/>, одна строка.

Проверка

./gradlew bootRun, профиль dev (h2, без внешних зависимостей):

JSON-строк из них с level warning в статусе
до 38 0 есть
после 46 46 нет

После фикса в логах присутствуют уровни DEBUG, INFO и WARN — то есть поле живое, а не константа. Пример строки:

{"@timestamp":"2026-08-04T17:50:49.842989867Z","app":"bulletins","environment":"dev",
 "instance":"linux-mint","logger_name":"io.hexlet.project_devops_deploy.DemoApplication",
 "thread_name":"restartedMain","level":"INFO",
 "message":"Started DemoApplication in 11.896 seconds (process running for 12.731)"}

Тикет: FEEDBACK-353.

The JSON encoder was configured with a <level/> provider, but
logstash-logback-encoder has no such provider — LoggingEventJsonProviders
exposes addLogLevel and addLogLevelValue, not addLevel. Logback silently
dropped the element and only hinted at it in its startup status output:

  |-WARN in ch.qos.logback.core.model.processor.ImplicitModelHandler -
  Ignoring unknown property [level] in
  [net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders]

So every log line went out without a level, while app/environment/instance
survived because they come from the separate, valid <pattern> provider. That
made the breakage easy to miss: nothing failed, the logs were still valid JSON,
and only one field was quietly absent.

Verified with ./gradlew bootRun on the dev profile. Before: 0 of 38 lines had
a level field and the warning above was present. After: all 46 lines carry
level, spanning DEBUG/INFO/WARN, and the warning is gone.
@fey
fey merged commit d5ca191 into main Aug 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant