laravel 5.2 针对不同任务的自定义日志文件

2022-08-30 12:31:42

我们是否可以在laravel 5.2中为不同的目的创建自定义日志文件,例如用于应该按顺序排列的订单相关日志条目.log以及用于与付款相关的东西,该条目应该登录付款.log

我想找到最好的Laravel方式。

目前,我们只能更改日志文件频率(如每日,单个),或者我们可以更改日志文件的名称,而不是默认值,即laravel.log


答案 1

有一个简单的方法:

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);

日志/订单中的输出.log:

[2017-04-30 00:00:00] order.INFO: OrderLog {"orderId":10, "description":"Some description"} []

答案 2

给你。。。我花了很多时间向Monolog添加自定义功能,这些功能能够以正确的方式做到这一点。我尝试了很多不同的方法,但一切都有点笨拙。最后,我找到了一个好方法来让这个功能工作....

由于应用程序很大,我需要单独的日志文件,并尽可能地维护现有的Laravel的日志界面。我需要这样的东西:

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

解决方案:

App\Providers\AppServiceProvider.php(添加到注册函数)

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

config\app.php(添加到别名)

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

应用程序\合同\外观\通道日志.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
            );
        }
    }

}

在此之后,您可以在任何文件中执行以下操作:

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])
}

推荐