From 42fced29ff8d1d08a53ff436ba5d0a1a7a7a42c8 Mon Sep 17 00:00:00 2001 From: Neophytis <37024002+Neophytis@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:48:40 +0200 Subject: [PATCH] feat(logging): write warnings to stderr in prod as they happen (#524 follow-up) Since #558, prod writes only errors (with their buffered request context). Warnings from requests that don't fail were no longer written anywhere. On 3.8.0 that was about 28k a day, and they pointed at real problems: the avatar fallback (#556, which members have unreadable avatar files), header injection in the language switcher (#550), undecodable sessions (#532). - warnings: a filter handler that passes only the warning level, straight to php://stderr as JSON, no buffer. Errors stay with "main", so an error is never written twice. A warning in a request that later fails appears twice (alone and as context of the error), about 400 requests a day. - Deprecations, notices and debug stay off. Volume: about 28k lines a day, about 20k once ROX-502 (alias.cache.ini warning) is fixed. --- config/packages/prod/monolog.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/config/packages/prod/monolog.yaml b/config/packages/prod/monolog.yaml index 77f9f28fad..815440117c 100644 --- a/config/packages/prod/monolog.yaml +++ b/config/packages/prod/monolog.yaml @@ -3,7 +3,7 @@ # Production logs go to stderr, not to files in the container: Docker keeps them # (docker logs) and Vector ships them to VictoriaLogs. Records of a request are # buffered and only written when that request logs an error, so normal requests -# produce no log lines (#524). +# produce no log lines (#524). Warnings are written as they happen. # # Deprecations are off unless DEPRECATION_LOG is set, e.g. php://stderr on stage. # It is read at runtime: changing it needs a container restart, not a new image. @@ -26,6 +26,22 @@ monolog: level: debug formatter: monolog.formatter.json + # Warnings are written as they happen, without a buffer: they often point + # at a problem before it becomes an error. Only the warning level passes; + # errors stay with "main" so they are not written twice. + warnings: + type: filter + handler: warnings_stream + min_level: warning + max_level: warning + channels: ['!deprecation'] + + warnings_stream: + type: stream + path: php://stderr + formatter: monolog.formatter.json + nested: true + deprecation: type: stream channels: [deprecation]