How to Log INFO to separate file in Laravel
Asked Answered
A

6

82

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

Ash answered 13/9, 2015 at 17:21 Comment(2)
Possible duplicate of Laravel Monolog. Log INFO level to separate fileJohny
Could you please verify the right answer again? It's outdated. Please check my answer and may mark it as right since its the common way in Laravel.Diffusion
C
67

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.

Cesium answered 3/6, 2016 at 10:48 Comment(5)
This is still working in Laravel 5.4, I've just tested and used it.Fardel
For problems/caveats with this approach see https://mcmap.net/q/244427/-laravel-log-usefiles-method-is-making-log-write-in-multiple-filesIneradicable
Is there a way to remove second log handler after I wrote to log all I needed?Rosemarierosemary
useDailyFiles() existed in Laravel 5.5, but not any more since 5.8 laravel.com/api/5.5/search.html?search=useDailyFiles laravel.com/api/5.8/search.html?search=useDailyFilesHavre
I guess this has been removed in Laravel 7. How to do this in Laravel 7 ?Medium
C
62

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

Cromagnon answered 15/7, 2018 at 16:45 Comment(1)
I also used the same. everything is working fine. but this file also storing other debug and error logs. why this happening.Bimetallic
D
32

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!'); 
Diffusion answered 31/12, 2018 at 13:10 Comment(0)
C
16

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.

Chancellor answered 15/7, 2017 at 20:0 Comment(0)
H
13

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;
Heeltap answered 13/9, 2015 at 17:41 Comment(5)
getting this error PHP Fatal error: Class 'StreamHandler' not found in /var/www/html/project/bootstrap/app.php on line 56Drunk
@RohitJindal swap StreamHandler out for Monolog\Handler\StreamHandler. You may also find you need to swap Logger out for Monolog\Logger, too.Wassyngton
@alexrussell, so, according to it i have toinclude two namespaces in my bootstrap/app.php..Monolog\Handler\StreamHandler and Monolog\Logger ??Drunk
Yes, either use the namespaces, of reference the fully-qualified classes.Wassyngton
configureMonologUsing() existed in Laravel 5.5, but not any more since 5.8 laravel.com/api/5.5/search.html?search=configureMonologUsing laravel.com/api/5.8/search.html?search=configureMonologUsingHavre
L
2

If you want to separate only a set of logs you can do it using useFiles method, as follows:

\Log::useFiles(storage_path() . '/logs/your_custom_log_file.log');

❗❗❗ But keep in mind that useFiles() does not overwrite the default log handler, so the logs will be added to laravel.log too.

In Laravel 5.4 when I need to create a log in a separate file, I fall back to file_put_contents function:

$myLogInfo = "...";
file_put_contents(
   storage_path() . '/logs/your_custom_log_file.log', 
   $myLogInfo . PHP_EOL, 
   FILE_APPEND | LOCK_EX
);
Lorilee answered 29/7, 2022 at 6:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.