Home » Php » Laravel : How to Log INFO to separate file

Laravel : How to Log INFO to separate file

Posted by: admin November 30, 2017 Leave a comment

Questions:

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

Any immediate help will be highly appreciable. Thanks

Answers:

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.

Questions:
Answers:

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;

Questions:
Answers:

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 <[email protected]>
 */

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 <[email protected]>
 */

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.

Questions:
Answers:

Laravel uses monolog for logging, but it uses an older version that does not support multiple channels in a single log level.

Here is a suggestion that may help: laravel 5.2 custom log file for different tasks