laravel 5.2 custom log file for different tasks

后端 未结 10 1017
再見小時候
再見小時候 2021-01-30 00:36

Can we create a custom log file for different purposes in laravel 5.2 like for order related log entries that should be in order.log and for payment related stuff the entry shou

相关标签:
10条回答
  • 2021-01-30 00:47

    There is a simple way:

    use Monolog\Logger;
    use Monolog\Handler\StreamHandler;
    
    $log = ['orderId' => 10,
            'description' => 'Some description'];
    
    //first parameter passed to Monolog\Logger sets the logging channel name
    $orderLog = new Logger('order');
    $orderLog->pushHandler(new StreamHandler(storage_path('logs/order.log')), Logger::INFO);
    $orderLog->info('OrderLog', $log);
    

    Output in logs/order.log:

    [2017-04-30 00:00:00] order.INFO: OrderLog {"orderId":10, "description":"Some description"} []
    
    0 讨论(0)
  • 2021-01-30 00:52

    Quickest Way to output log to different files

    Log::useFiles('path/to/file.log');
    Log::info('Info');
    
    0 讨论(0)
  • 2021-01-30 00:53

    To expand on ShQ's answer:

    One issue I noticed is that the log will be appended with [] [], which are the empty array values for $context and $extra within LineFormatter.format();

    ie, vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php

    There are two ways around this, either provide a format which does not include extra or context to the constructor of LineFormatter, or provide the 4th argument $ignoreEmptyContextAndExtra = true.

    All files within ShQ's answer remain the same but ChannelStreamHandler must change.

    ChannelStreamHandler:

    <?php
    
    namespace App\Helpers;
    
    use Monolog\Formatter\LineFormatter;
    use Monolog\Handler\StreamHandler;
    use Monolog\Logger;
    
    /**
     * Use channels to log into separate files
     *
     */
    class ChannelStreamHandler extends StreamHandler
    {
        /**
         * Channel name
         *
         * @var String
         */
        protected $channel;
    
        /**
         * @param String $channel Channel name to write
         * @param bool|int $stream
         * @param bool|int $level
         * @param bool $bubble
         * @param null $filePermission
         * @param bool $useLocking
         * @see parent __construct for params
         */
        public function __construct(
            $channel,
            $stream,
            $level = Logger::DEBUG,
            $bubble = true,
            $filePermission = null,
            $useLocking = false
        ) {
            $this->channel = $channel;
    
            $formatter = new LineFormatter(null, null, false, true);
            $this->setFormatter($formatter);
    
            parent::__construct($stream, $level, $bubble);
        }
    
        /**
         * When to handle the log record.
         *
         * @param array $record
         * @return bool
         */
        public function isHandling(array $record)
        {
            //Handle if Level high enough to be handled (default mechanism)
            //AND CHANNELS MATCHING!
            if (isset($record['channel'])) {
                return ($record['level'] >= $this->level && $record['channel'] == $this->channel);
            } else {
                return ($record['level'] >= $this->level);
            }
        }
    
    }
    

    The important change is to provide 4th param of true, which is $ignoreEmptyContextAndExtra. This param, tells LineFormatter to ignore either context of extra arrays if empty:

    $formatter = new LineFormatter(null, null, false, true);
    $this->setFormatter($formatter);
    

    You must be sure to also ensure your running monolog 1.22 because it includes a bug fix regarding ignoreEmptyContextAndExtra.

    I also added an override for info() to the ChannelWritter class:

    public function info($channel, $message, array $context = [])
    {
        $level = array_flip($this->levels)[$this->channels[$channel]['level']];
        $this->writeLog($channel, $level, $message, $context);
    }
    

    Additionally, I wasn't happy with the "lazy load logger" in ShQ's solution so modified to use the service provider/IoC

    Replace ChannelWriter.writeLog():

    public function writeLog(string $channel, string $level, string $message, array $context = [])
    {
        if (!in_array($channel, array_keys($this->channels))) {
            throw new InvalidArgumentException('Invalid channel used.');
        }
    
        $logger = \App::make("{$channel}log");
        $channelHandler = new ChannelStreamHandler(
            $channel,
            storage_path() . '/' . $this->channels[$channel]['path'],
            $this->channels[$channel]['level']
        );
        $logger->pushHandler($channelHandler);
        $logger->{$level}($message);
    }
    

    and in your AppServiceProvider:

        $this->app->bind('eventlog', function () {
            return new Logger('event');
        });
    
        $this->app->bind('auditlog', function () {
            return new Logger('audit');
        });
    

    I'll try bundle this together into a package.

    0 讨论(0)
  • 2021-01-30 00:53

    For me in Laravel 5.3, I am not sure if it was my install previously but I found the bootstrap/app.php did not work for me.

    I needed to put this in app/Providers/AppServiceProvider.php.

    n.b. This is where I had the setting of the log level from config before, so I end up with 3 log handlers.

    public function register()
    {
       $monolog = Log::getMonolog();
       foreach ($monolog->getHandlers() as $handler) {
          $handler->setLevel(Config::get('app.log_level'));
       }
    
       $bubble = false;
       $infoStreamHandler = new \Monolog\Handler\StreamHandler( storage_path("logs/info.log"), \Monolog\Logger::INFO, $bubble);
       $monolog->pushHandler($infoStreamHandler);
    
       $warningStreamHandler = new \Monolog\Handler\StreamHandler( storage_path("logs/warning.log"), \Monolog\Logger::WARNING, $bubble);
       $monolog->pushHandler($warningStreamHandler);
    
    }
    
    0 讨论(0)
  • 2021-01-30 00:53
    Solution:
    
    step1: create a channel inside config/logging.php file
    
    example :
    
    'channels' => [
        'single' => [
        'driver' => 'single', 
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
    ],
    
    'web' => [
          'driver' => 'single',
          'path' => storage_path('logs/web/web.log'),
       ],
    
    ]
    
    Step2: Now set dynamic path from the controller  like this
    
    config(['logging.channels.web.path' => storage_path('logs/web/'.time().'.log')]);
    
    Step3 : now generate your log
    
      Log::channel('web')->info("your message goes here");
    
    Enjoy :)
    
    0 讨论(0)
  • 2021-01-30 00:55

    Based on the ShQ answer, a shorter and simpler logger helper that allows you to log to a custom file on the fly. You can also add your custom handler and set the file path.

    App\Helper

    <?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;
    
    /**
     * 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'
                );
    
                $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\AppServiceProvider.php (add to register function)

    //Facade to Object binding
    $this->app->bind('LogToChannels', 'App\Helpers\LogToChannels');
    

    config\app.php (add to aliases)

    // Custom Alias Class
    'Log' => App\Contracts\Facades\LogToChannels::class
    

    Then anywhere in your app you can call

    Log::info('logger_name', 'Log message');
    Log::error('other_logger_name', 'Log message', $someContext);
    

    You can even customize your logger output by calling

    Log::addChannel('channel_name', $customHandler);
    

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

    0 讨论(0)
提交回复
热议问题