guice
guice

Reputation: 1094

Laravel: multiple log providers using `configureMonologUsing()`?

I'm using configureMonologUsing() to add in two custom loggers. Doing the standard SOLID principal, I have two providers: ConsoleLoggerProvider and MailLogProvider.

Both of these have a register similar to:

public function register()
{
    app()->configureMonologUsing(function(\Monolog\Logger $monolog) {
        $monolog->pushHandler(new HandlerClass());
    });
}

However, I have noticed over logger will overwrite another logger... How do I stack these?

I've tried to use boot() as well, and that didn't work. I couldn't find any other way to add to the Monolog stack.

Preferable, I want to stack onto Laravel's built-in logger as well.

Upvotes: 4

Views: 6384

Answers (4)

Nuryagdy Mustapayev
Nuryagdy Mustapayev

Reputation: 785

Here is how I able to configure on Laravel Lumen v5.4 in app.php:

$publisher = new \Gelf\Publisher(new \Gelf\Transport\HttpTransport(env('GRAYLOG_HOST'), env('GRAYLOG_PORT'), env('GRAYLOG_PATH')));

//WhatFailureGroupHandler does not break app execution 
//if some exceptions happen  happens while logging
$failureHandler = new \Monolog\Handler\WhatFailureGroupHandler([
 new \Monolog\Handler\GelfHandler($publisher)
]);

\Log::pushHandler($failureHandler);

\Log::getMonolog() as on accepted answer threw error.

Also tried to configure using $app->configureMonologUsing() which threw A facade root has not been set. error. But at the end, I found out that was because we need to return logger:

$app->configureMonologUsing(function ($monolog) {

    $publisher = new \Gelf\Publisher(new \Gelf\Transport\HttpTransport(env('GRAYLOG_HOST'), env('GRAYLOG_PORT'), env('GRAYLOG_PATH')));
    
    $failureHandler = new \Monolog\Handler\WhatFailureGroupHandler([new \Monolog\Handler\GelfHandler($publisher)]);

    $monolog->pushHandler($failureHandler);

    //fixes error: A facade root has not been set
    return $monolog;
});

All the examples of $app->configureMonologUsing() usage I have seen do not have a return statement, even in the other answers, which did not work for me.

Upvotes: 0

Ryan
Ryan

Reputation: 24093

Following Laravel 5.2 docs, in bootstrap/app.php, I added the following code right before return $app;:

$app->configureMonologUsing(function($monolog) {//IMPORTANT: I think the order of pushHandler matters, and the ones defined last here will be the first to be called, which affects anything where bubble=false
    if (config('services.slack.send_errors_to_slack')) {
        $bubble = false; //I think that if I set the 'bubble' argument to false and handle the most severe logging levels first (which counterintuitively means lower in this function), less severe logging levels don't bother reporting the same message.
        $useShortAttachment = false;
        $includeContextAndExtra = true; //This is important because otherwise 404 errors wouldn't report the URL, give how 'report' function is coded within App\Exceptions\Handler.php.
        $handlerForWarningsToNotifyPhone = new \Monolog\Handler\SlackHandler(config('services.slack.token'), config('services.slack.channel_warnings'), 'Monolog', true, null, \Monolog\Logger::WARNING, $bubble, $useShortAttachment, $includeContextAndExtra);
        $monolog->pushHandler($handlerForWarningsToNotifyPhone);
        $handlerForErrorsToNotifyPhone = new \Monolog\Handler\SlackHandler(config('services.slack.token'), config('services.slack.channel_errors'), 'Monolog', true, null, \Monolog\Logger::ERROR, $bubble, $useShortAttachment, $includeContextAndExtra);
        $monolog->pushHandler($handlerForErrorsToNotifyPhone);
    }
    if (config('app.send_logs_to_loggy')) {
        $logglyHandler = new \Monolog\Handler\LogglyHandler(config('services.loggly.token'), config('app.send_logs_to_loggy')); //See \Monolog\Logger::INFO. Log level 200 is "info".
        $logglyHandler->setTag(config('services.loggly.tag'));
        $monolog->pushHandler($logglyHandler);
    }
    if (config('app.log_to_local_disk')) {
        $localHandler = new \Monolog\Handler\StreamHandler(storage_path("/logs/laravel.log"));
        $monolog->pushHandler($localHandler);
    }
});

It's just an example that may help you.

Be sure to edit your config files accordingly (e.g. so that app.log_to_local_disk, services.slack.send_errors_to_slack, etc are available).

http://stackoverflow.com/a/36259944/470749 was helpful.

Upvotes: 0

guice
guice

Reputation: 1094

I (finally) found the answer my question:

Within my providers, instead of using configureMonologUsing(), I used Log::getMonolog()->pushHandler([..])

That works! All loggers, including built-in Laravel file logger, are firing. Finally!

(I've honestly been looking for days for a way to add onto the Monolog stack; I apparently wasn't searching by the right terms)

Upvotes: 11

shalvah
shalvah

Reputation: 895

According to the Laravel documentation:

You should place a call to the configureMonologUsing method in your bootstrap/app.php file right before the $app variable is returned by the file.

In that case, thus should work for you: create two handler classes and add them to monolog this way (in your bootstrap/app.php):

$app->configureMonologUsing(function ($monolog) {
  $monolog->pushHandler(new EmailLogHandler);
  $monolog->pushHandler(new ConsoleLogHandler); 
}); 
return $app;

Upvotes: 1

Related Questions