Configuring per-environment logging in Laravel 5


Laravel allows you to configure the default Monolog logger instance, but this largely allows you to add additional handlers or to put debug into another file for example.

The default logging implementation sets the log level to debug and doesn’t appear to provide a way to change this. This means that even if you specify a separate handler for debug logs, all log events with higher priority (info, notice, error, etc) will still be logged there.

You could use the setHandlers method to create an entirely new set of stream handlers and log each level — but this is still the minimum logging level. If you create a handler for the error level, you will still get all levels above this — critical, alert, and emergency.

I didn’t want to have to remove the debug level log messages — Log::debug() — from my code, but didn’t want to have them logged in production, as they are expected to get quite noisy.

Following the documentation

Your first thought might be to handle this within the bootstrap/app.php file per the documentatino:

$level = $app->environment('local') ? 'debug' : 'warning'; $app->configureMonologUsing(function ($monolog) { $monolog->pushHandler(new StreamHandler(storage_path('logs/laravel.log'), $level); });

Done, right? Wrong.

At this stage of the boot process, the environment has not yet been configured, so environment() triggers a fatal error:

Fatal error: Uncaught ReflectionException: Class env does not exist in /home/vagrant/Code/laravel.test/vendor/laravel/framework/src/Illuminate/Container/Container.php:741

There also doesn’t appear to be any way to set the $level parameter of Laravel’s underlying useFiles, useDailyFiles, useSyslog, or useErrorLog methods.

In order to get around this limitation, you need to override the functionality entirely.

A custom ConfigureLogging class

namespace App\Bootstrap; use Illuminate\Foundation\Bootstrap\ConfigureLogging as BaseConfigureLogging; use Illuminate\Contracts\Foundation\Application; use Illuminate\Log\Writer; class ConfigureLogging extends BaseConfigureLogging { protected function configureSingleHandler(Application $app, Writer $log) { $log->useFiles($app->storagePath().'/logs/laravel.log', $this->resolveLogLevel($app)); } protected function configureDailyHandler(Application $app, Writer $log) { $log->useDailyFiles( $app->storagePath().'/logs/laravel.log', $app->make('config')->get('app.log_max_files', 5), $this->resolveLogLevel($app) ); } protected function configureSyslogHandler(Application $app, Writer $log) { $log->useSyslog('laravel', $this->resolveLogLevel($app)); } protected function configureErrorlogHandler(Application $app, Writer $log) { $log->useErrorLog($this->resolveLogLevel($app)); } /** * Based on the current environment, return the desired log level. * * @param \Illuminate\Contracts\Foundation\Application $app * * @return string */ private function resolveLogLevel(Application $app) { return $app->isLocal() ? 'debug' : 'warning'; } }

In doing so, you overwrite the relevant methods in Laravel’s ConfigureLogging class, giving you the ability to set the log level based on the environment via the new resolveLogLevel method.

How you derive the appropriate log level is up to you; you might target a specific environment using $app->environment(‘staging’), for example.

Implementing the custom logging

Originally published at

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.