How to Log INFO to separate file in Laravel

PhpLaravelLaravel 5Monolog

Php Problem Overview


How to specify a separate file for logging INFO in Laravel 5.1?

Php Solutions


Solution 1 - Php

Do you want to specifically log info to one log file and another log type to another location? My solution might not help in that case, but could still be useful.

To write a log file to another location, use the method useDailyFiles or useFiles, and then info to log to the log file at the path you just specified. Like so:

    Log::useDailyFiles(storage_path().'/logs/name-of-log.log');
	Log::info([info to log]);

The first parameter for both methods is the path of the log file (which is created if it doesn't already exist) and for useDailyFiles the second argument is the number of days Laravel will log for before erasing old logs. The default value is unlimited, so in my example I haven't entered a value.

Solution 2 - Php

Since Laravel 5.6 you can create your own channel in config\logging.php. If you have upgraded from an older Laravel version you need to create this file (https://laravel.com/docs/5.6/upgrade).

Add this to you channel array in config\logging.php

'your_channel_name' => [
            'driver' => 'single',
            'path' => storage_path('logs/your_file_name.log'),
        ],

You can then call any of the 8 logging levels like that:

Illuminate\Support\Facades\Log::channel('your_channel_name')->info('your_message');

The logs will be stored in logs/your_file_name.log

Solution 3 - Php

Since Laravel >= 5.6 we can use Log Channels to make it work in a easy way. This allows you to create log channels which can be handled as own log files with own drivers, paths or levels. You just need this few lines to make it work.

Simple add a new channel (choose your channel name, e.g. "command")

config/logging.php:

return [
    'channels' => [ 
        'command' => [
            'driver' => 'single',
            'path' => storage_path('logs/command.log'),
            'level' => 'debug',
        ],
    ],
];

Log where ever you want by parse the channel name:

Log::channel('command')->info('Something happened!'); 

Solution 4 - Php

If you would like add another monolog handler, you may use the application's configureMonologUsing method.

Place a call to this method in bootstrap/app.php file right before the $app variable is returned:

$app->configureMonologUsing(function($monolog) {
    $monolog->pushHandler(new StreamHandler('path/to/info.log', Logger::INFO, false)); // false value as third argument to disable bubbling up the stack
});

return $app;

Solution 5 - Php

A simple logger helper that allows you to log to multiple custom files on the fly. You can also add your custom handler and set the file path.

App\Helper\LogToChannels.php

<?php
/**
 * Logger helper to log into different files
 *
 * @package    App\Helpers
 * @author     Romain Laneuville <romain.laneuville@hotmail.fr>
 */

namespace App\Helpers;

use Monolog\Logger;
use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;

/**
 * Class LogToChannels
 *
 * @package App\Helpers
 */
class LogToChannels
{
    /**
     * The LogToChannels channels.
     *
     * @var Logger[]
     */
    protected $channels = [];

    /**
     * LogToChannels constructor.
     */
    public function __construct()
    {
    }

    /**
     * @param string $channel The channel to log the record in
     * @param int    $level   The error level
     * @param string $message The error message
     * @param array  $context Optional context arguments
     *
     * @return bool Whether the record has been processed
     */
    public function log(string $channel, int $level, string $message, array $context = []): bool
    {
        // Add the logger if it doesn't exist
        if (!isset($this->channels[$channel])) {
            $handler = new StreamHandler(
                storage_path() . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . $channel . '.log'
            );

            $handler->setFormatter(new LineFormatter(null, null, true, true));

            $this->addChannel($channel, $handler);
        }

        // LogToChannels the record
        return $this->channels[$channel]->{Logger::getLevelName($level)}($message, $context);
    }

    /**
     * Add a channel to log in
     *
     * @param string           $channelName The channel name
     * @param HandlerInterface $handler     The channel handler
     * @param string|null      $path        The path of the channel file, DEFAULT storage_path()/logs
     *
     * @throws \Exception When the channel already exists
     */
    public function addChannel(string $channelName, HandlerInterface $handler, string $path = null)
    {
        if (isset($this->channels[$channelName])) {
            throw new \Exception('This channel already exists');
        }

        $this->channels[$channelName] = new Logger($channelName);
        $this->channels[$channelName]->pushHandler(
            new $handler(
                $path === null ?
                    storage_path() . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . $channelName . '.log' :
                    $path . DIRECTORY_SEPARATOR . $channelName . '.log'
            )
        );
    }

    /**
     * Adds a log record at the DEBUG level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function debug(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::DEBUG, $message, $context);
    }

    /**
     * Adds a log record at the INFO level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function info(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::INFO, $message, $context);
    }

    /**
     * Adds a log record at the NOTICE level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function notice(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::NOTICE, $message, $context);
    }

    /**
     * Adds a log record at the WARNING level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function warn(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::WARNING, $message, $context);
    }

    /**
     * Adds a log record at the WARNING level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function warning(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::WARNING, $message, $context);
    }

    /**
     * Adds a log record at the ERROR level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function err(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::ERROR, $message, $context);
    }

    /**
     * Adds a log record at the ERROR level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function error(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::ERROR, $message, $context);
    }

    /**
     * Adds a log record at the CRITICAL level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function crit(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::CRITICAL, $message, $context);
    }

    /**
     * Adds a log record at the CRITICAL level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return Boolean Whether the record has been processed
     */
    public function critical(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::CRITICAL, $message, $context);
    }

    /**
     * Adds a log record at the ALERT level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function alert(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::ALERT, $message, $context);
    }

    /**
     * Adds a log record at the EMERGENCY level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function emerg(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::EMERGENCY, $message, $context);
    }

    /**
     * Adds a log record at the EMERGENCY level.
     *
     * @param  string $channel The channel name
     * @param  string $message The log message
     * @param  array  $context The log context
     *
     * @return bool Whether the record has been processed
     */
    public function emergency(string $channel, string $message, array $context = []): bool
    {
        return $this->log($channel, Logger::EMERGENCY, $message, $context);
    }
}

App\Providers\LogToChannelsServiceProvider.php

<?php
/**
 * Logger service provider to be abled to log in different files
 *
 * @package    App\Providers
 * @author     Romain Laneuville <romain.laneuville@hotmail.fr>
 */

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Helpers\LogToChannels;

/**
 * Class LogToChannelsServiceProvider
 *
 * @package App\Providers
 */
class LogToChannelsServiceProvider extends ServiceProvider
{
    /**
     * Initialize the logger
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('App\Helpers\LogToChannels', function () {
            return new LogToChannels();
        });
    }
}

config\app.php (add the service provider)

// Register Service Providers
$app->register(App\Providers\LogToChannelsServiceProvider::class);

Then anywhere in your app you can call using dependency injection (add the class in your constructor and bind it to a log class attribute)

$this->log->info('logger_name', 'Log message');
$this->log->error('other_logger_name', 'Log message', $someContext);

You can even customize your logger output by calling

$this->log->addChannel('channel_name', $customHandler);

And it will be accessible when you will call its name anywhere in your app.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoh&#236;t J&#237;ndalView Question on Stackoverflow
Solution 1 - PhpTimothyBuktuView Answer on Stackoverflow
Solution 2 - PhpAdamView Answer on Stackoverflow
Solution 3 - PhplinView Answer on Stackoverflow
Solution 4 - PhpJosip IvicView Answer on Stackoverflow
Solution 5 - PhpRomain LaneuvilleView Answer on Stackoverflow