Logging in Symfony and the Cloud
In the last few years, the way applications log messages has changed. Using
files was the common way to store logs but with the Cloud (read containers,
Docker, and the likes), using
stderr to stream logs is recommended.
Did you know that you don't need Monolog to capture application logs? Since
Symfony 3.4, the Symfony HttpKernel component comes with a default PSR3 logger that
logs everything in
stderr, without the help of any other packages. This
feature was added along side the introduction of Flex as new applications start
with no extra packages, and so no logger. Loggin via `stderr` was chosen with
containers in mind.
By default, new Symfony applications log in
stderr via this default
HttpKernel logger. It is probably enough for small applications; I'm using it
for fabbot and Twig's website for instance.
Using Monolog is still very useful as it comes with way more options and
configurability. But for historical reasons, and probably practicability on
dedicated servers, Monolog default recipe still uses a file to store logs
%kernel.logs_dir%/%kernel.environment%.log). The Symfony Kernel class even
getLogDir() method as defined in the Kernel interface.
It might make sense on a development server (more on that later), but in
stderr is a better option, especially when using Docker,
SymfonyCloud, lambdas, ... So, I now recommend to use
php://stderr as the
path for Monolog:
1 2 3 4 5 6 7 8 9 10 11
--- a/config/packages/prod/monolog.yaml +++ b/config/packages/prod/monolog.yaml @@ -11,7 +11,7 @@ monolog: members: [nested, buffer] nested: type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" + path: php://stderr level: debug buffer: type: buffer
On SymfonyCloud, using
stderr also has a few added benefits (the same
should apply to most containerized platforms). Even if in the end, the logs
stderr end up in a file as well:
app.log. You might wonder how
this could be better than using a dedicated file then. First, the
file is "managed" by SymfonyCloud: it is automatically rotated (no more log
files growing indefinitely until it fills up your disk), the
is stored in a local and fast disk instead of a network disk (which is used
when storing files under
var/log/). It might also be less expensive as you
don't "waste" network disk capacity with ephemeral logs.
stderr also means that there is one less write-able directory needed
by Symfony (don't forget to log deprecation notices in
stderr as well and
check that no third-party bundles write into the
What about development? Can you use
stderr as well? The answer is yes and I
recommend you to do so as well.
If you are using PHP-FPM, you need to configure it to "forward" logs to FPM
logs (which can be streamed on
stderr as well!):
1 2 3
; Ensure worker stdout and stderr are sent to the main error log catch_workers_output = yes decorate_workers_output = no (7.3+ only)
If you are using Symfony CLI, that's the default configuration for PHP-FPM and logs are automatically "un-decorated" for all PHP versions.
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
Why stderr all the time? Why not stdout by default and use stderr for error level and more?
I just tried it and I'm getting the following error:
"[error] 6#6: *1 upstream sent too big header while reading response header from upstream"
So is it still true that such logger logs everything in stderr?
Its not symfony fault though but a PHP short, as it seems.
Here is the bug report: https://bugs.php.net/bug.php?id=73886
Also from official docker lib: https://github.com/docker-library/php/issues/358#issuecomment-271033464
For example GCP log collector will label the log as error when coming from stderr and this will result in unwanted alerts by default in case you want to log some more bits then just errors from php. (Might happen even in production ;) )