Ethan22
Ethan22

Reputation: 757

Heroku not showing log messages created during scheduled tasks

I'm using Heroku to host a Lumen app. I've setup the logging to send messages to stdout:

// bootstrap/app.php
$app->configureMonologUsing(function ($monolog) {
    /** @var Monolog\Logger $monolog */
    $monolog->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', \Monolog\Logger::DEBUG));
});

I've tested this works by adding a log message to the schedule function

protected function schedule(Schedule $schedule)
{
    \Log::info('Running cronjobs.');

    $schedule
        ->command('update:daily')
        ->timezone('America/Los_Angeles')
        ->everyMinute();
}

The Heroku logs show:

Jan 19 09:42:15 service app/scheduler.4140: [2018-01-19 17:42:14] lumen.INFO: Running cronjobs. [] [] 
Jan 19 09:42:15 service app/scheduler.4140: Running scheduled command: '/app/.heroku/php/bin/php' artisan update:daily > '/dev/null' 2>&1

However the update:daily command has a number of log messages inside it and none of them are showing up.

I thought this might be because of the > '/dev/null' so I tried adding ->sendOutputTo('php://stdout') and ->sendOutputTo(base_path('storage/logs/cronjobs.log')) to the scheduled task but neither works.

Here's my Procfile:

web: vendor/bin/heroku-php-nginx -C heroku-nginx.conf -l storage/logs/cronjobs.log public/

Upvotes: 0

Views: 756

Answers (2)

Lulu
Lulu

Reputation: 470

Ethan is right with his observation regarding > '/dev/null'. As Heroku collects logs from stdout and stderr - scheduled tasks are not being logged correctly.

Luckily there's a simple workaround: log to a file, and output it's content into stdout. Heroku will then be able to log everything, whether using its native logging or using an add-on like LogDNA, Papertrail, etc.

Given that you're logging to a single channel in logging.php, into the file storage/logs/laravel.log, replace your scheduler command php artisan schedule:run with the following:

touch ./storage/logs/laravel.log; tail -f ./storage/logs/laravel.log & php artisan schedule:run

What it does?

  1. Makes sure a log file exists. If it didn't - the following command will fail
  2. Tails the log file, so its content is outputted to stdout
  3. Starting the Laravel scheduler

The advantage of using this method is that you don't need to change your code, rather the configuration and the environment, so if you're running the app on other platforms - it won't change the way they work/log.

Upvotes: 1

Ethan22
Ethan22

Reputation: 757

Laravel uses the > '/dev/null' when you do not call ->sendOutputTo(). I couldn't figure out an appropriate way to use the ->sendOutputTo() function to send to stdout.

What I did to fix this issue was change the ->command() function to a ->call(function(){}) function and executed the same single line of code the terminal command could have called. When laravel calls a Closure, it does not dump the output to > '/dev/null'.

Upvotes: 0

Related Questions