Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel 5.2 custom log file for different tasks

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 should get logged in payments.log

I want to find the best possible Laravel way.

Currently we can only change the log file frequency (like daily, single) or we can change the name of the log file other than default i.e laravel.log

like image 454
Gaurav Bakshi Avatar asked Jun 14 '16 10:06

Gaurav Bakshi


People also ask

How do I put logs in Laravel?

By default, Laravel is configured to create daily log files for your application which are stored in the storage/logs directory. You may write information to the log like so: Log::info('This is some useful information. ');

Where are Laravel logs stored?

By default, Laravel is configured to create a single log file for your application, and this file is stored in app/storage/logs/laravel. log .

What are the Laravel log levels?

The logger provides the eight logging levels defined in RFC 5424: emergency, alert, critical, error, warning, notice, info and debug.

What is Laravel log channel?

Laravel logging is based on "channels". Each channel represents a specific way of writing log information. For example, the single channel writes log files to a single log file, while the slack channel sends log messages to Slack. Log messages may be written to multiple channels based on their severity.


2 Answers

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"} [] 
like image 156
massreuy Avatar answered Oct 07 '22 19:10

massreuy


Here you go... I've spent so much time to add custom functionality to Monolog which able to do THAT in a proper way. I tried sooooo many different ways, but all was a bit hacky. Finally I found a good way to get this functionality working....

As the application is big, I needed separate log files, and maintain the existing Laravel's Log interface as much as possible. I needed something like:

Log::write('audit', 'User logged in to the app.');
Log::info('event', 'User sent out 2 emails.');

The Solution:

App\Providers\AppServiceProvider.php (add to register function)

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

config\app.php (add to aliases)

//Custom Alias Class 'ChannelLog' => App\Contracts\Facades\ChannelLog::class, 

App\Contracts\Facades\ChannelLog.php

<?php  namespace App\Contracts\Facades;  use Illuminate\Support\Facades\Facade;  /**  * @see \Illuminate\Log\Writer  */ class ChannelLog extends Facade {     /**      * Get the registered name of the component.      *      * @return string      */     protected static function getFacadeAccessor()     {         return 'chanellog';     } } 

App\Helpers\ChannelWriter.php

<?php  namespace App\Helpers;  use Monolog\Logger;  use App\Helpers\ChannelStreamHandler;  class ChannelWriter {     /**      * The Log channels.      *      * @var array      */     protected $channels = [         'event' => [              'path' => 'logs/audit.log',              'level' => Logger::INFO          ],         'audit' => [              'path' => 'logs/audit.log',              'level' => Logger::INFO          ]     ];      /**      * The Log levels.      *      * @var array      */     protected $levels = [         'debug'     => Logger::DEBUG,         'info'      => Logger::INFO,         'notice'    => Logger::NOTICE,         'warning'   => Logger::WARNING,         'error'     => Logger::ERROR,         'critical'  => Logger::CRITICAL,         'alert'     => Logger::ALERT,         'emergency' => Logger::EMERGENCY,     ];      public function __construct() {}      /**      * Write to log based on the given channel and log level set      *       * @param type $channel      * @param type $message      * @param array $context      * @throws InvalidArgumentException      */     public function writeLog($channel, $level, $message, array $context = [])     {         //check channel exist         if( !in_array($channel, array_keys($this->channels)) ){             throw new InvalidArgumentException('Invalid channel used.');         }          //lazy load logger         if( !isset($this->channels[$channel]['_instance']) ){             //create instance             $this->channels[$channel]['_instance'] = new Logger($channel);             //add custom handler             $this->channels[$channel]['_instance']->pushHandler(                  new ChannelStreamHandler(                      $channel,                      storage_path() .'/'. $this->channels[$channel]['path'],                      $this->channels[$channel]['level']                 )             );         }          //write out record         $this->channels[$channel]['_instance']->{$level}($message, $context);     }      public function write($channel, $message, array $context = []){         //get method name for the associated level         $level = array_flip( $this->levels )[$this->channels[$channel]['level']];         //write to log         $this->writeLog($channel, $level, $message, $context);     }      //alert('event','Message');     function __call($func, $params){         if(in_array($func, array_keys($this->levels))){             return $this->writeLog($params[0], $func, $params[1]);         }     }  } 

App\Helpers\ChannelStreamHandler.php

<?php  namespace App\Helpers;  use Monolog\Handler\StreamHandler;  /**  * Use channels to log into separate files  *  * @author Peter Feher  */ class ChannelStreamHandler extends StreamHandler {     /**      * Channel name      *       * @var String       */     protected $channel;      /**      * @param String $channel Channel name to write      * @see parent __construct for params      */     public function __construct($channel, $stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)     {         $this->channel = $channel;          parent::__construct($stream, $level, $bubble);     }      /**      * When to handle the log record.       *       * @param array $record      * @return type      */     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             );         }     }  } 

After this, you can do in any file:

use ChannelLog as Log; ... function myFunction(){     //Recommended (writes INFO to logs/event.log)     Log::write('event', 'User sent out 3 voucher.')     //Possible to use (writes ALERT to logs/audit.log)     Log::alert('audit', 'User modified xyz entry.')     //Or even:      Log::write('audit', 'User modified xyz entry.', ['user'=>1]) } 
like image 35
ShQ Avatar answered Oct 07 '22 20:10

ShQ