天天看點

larave 日志自定義配置格式記錄調用檔案路徑與行号

larave Monolog日志自定義配置

1、原有的日志記錄檔案隻記錄了時間和日志内容沒有記錄是在哪個檔案記錄的,給新來的人員檢視日志增加了額外的負擔。類似下面這樣

[-- ::] local.INFO: 我是來測試日志的 {"content":} 
[-- ::] local.DEBUG: 我是來測試日志的  
[-- ::] local.ERROR: 我是來測試日志的  
[-- ::] local.WARNING: 我是來測試日志的  
           

2、基于公司需求對MonoLog子產品的源碼進行了分析,釋出Laravel是對MonoLog之上做了一層封裝,達到了如下效果

[-- ::] local.INFO: 我是來測試日志的 {"content":} {"pid":,"file":"App\\Http\\Controllers\\TestController->log:20","line":,"ip":"127.0.0.1"}
[-- ::] local.DEBUG: 我是來測試日志的  {"pid":,"file":"App\\Http\\Controllers\\TestController->log:21","line":,"ip":"127.0.0.1"}
[-- ::] local.ERROR: 我是來測試日志的  {"pid":,"file":"App\\Http\\Controllers\\TestController->log:22","line":,"ip":"127.0.0.1"}
[-- ::] local.WARNING: 我是來測試日志的  {"pid":,"file":"App\\Http\\Controllers\\TestController->log:23","line":,"ip":"127.0.0.1"}
           

接下來告訴大家怎麼來實作它

1、重建立立一個

Writer.php

類 暫定目錄存

app\Utils\Monolog

<?php

namespace App\Utils\Monolog;

use Illuminate\Log\Writer as BaseWriter;
use Monolog\Formatter\LineFormatter;

/**
 * 時間精确到微秒
 *
 * @package app.Utils.Monolog
 */
class Writer extends BaseWriter
{

    /**
     * Get a default Monolog formatter instance.
     *
     * @return \Monolog\Formatter\LineFormatter
     */
    protected function getDefaultFormatter()
    {
        return new LineFormatter(null, 'Y-m-d H:i:s.u', true, true);
    }
           

2、建立處理程式

IntrospectionProcessor.php

目錄

app\Utils\Monolog\Processor

<?php

namespace App\Utils\Monolog\Processor;

use Monolog\Logger;

/**
 * Monolog用處理子產品
 * 标準IntrospectionProcessor的簡化版
 *
 * @package app.Utils.Monolog.Processor
 */
class IntrospectionProcessor
{
    private $level;

    private $skipClassesPartials;

    public function __construct($level = Logger::DEBUG, array $skipClassesPartials = ['Monolog\\', 'Illuminate\\'])
    {
        $this->level = Logger::toMonologLevel($level);
        $this->skipClassesPartials = $skipClassesPartials;
    }

    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }

        $trace = debug_backtrace();

        // skip first since it's always the current method
        array_shift($trace);
        // the call_user_func call is also skipped
        array_shift($trace);

        $i = ;

        while (isset($trace[$i]['class'])) {
            foreach ($this->skipClassesPartials as $part) {
                if (strpos($trace[$i]['class'], $part) !== false) {
                    $i++;
                    continue ;
                }
            }
            break;
        }

        $line = null;
        if (isset($trace[$i]['class'])) {
            $line = $trace[$i]['class'];
            if (isset($trace[$i]['class'])) {
                $line = $line . '->' . $trace[$i]['function'];
            }
        } else if (isset($trace[$i - ]['file'])) {
            $line = $trace[$i - ]['file'];
        }
        if (null !== $line && isset($trace[$i - ]['line'])) {
            $line = $line . ':' . $trace[$i - ]['line'];
        }

        $record['extra']['file'] = $line;
        $record['extra']['line'] = $trace[$i - ]['line'];
        $record['extra']['ip'] = $_SERVER["REMOTE_ADDR"];
        return $record;
    }
}
           

3、建立 處理子產品

ProcessIdProcessor.php

目錄

app\Utils\Monolog\Processor

<?php

namespace App\Utils\Monolog\Processor;

/**
 * Monolog用處理子產品
 * 标準IntrospectionProcessor的簡化版, 原輸出鍵值文字長度過長
 *
 * @package app.Utils.Monolog.Processor
 */
class ProcessIdProcessor
{
    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        $record['extra']['pid'] = getmypid();

        return $record;
    }
}
           

4、建立

ServiceProvider

檔案

LogServiceProvider.php

目錄

app\Providers

<?php
namespace App\Providers;

use Monolog\Logger as Monolog;
use Illuminate\Support\ServiceProvider;
use App\Utils\Monolog\Writer;

class LogServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('log', function () {
            return $this->createLogger();
        });
    }

    /**
     * Create the logger.
     *
     * @return \Illuminate\Log\Writer
     */
    public function createLogger()
    {
        $processors = [
            new \App\Utils\Monolog\Processor\ProcessIdProcessor(),
            new \App\Utils\Monolog\Processor\IntrospectionProcessor()
        ];

        $log = new \App\Utils\Monolog\Writer(
            new Monolog($this->channel(), [], $processors), $this->app['events']
        );

        if ($this->app->hasMonologConfigurator()) {
            call_user_func($this->app->getMonologConfigurator(), $log->getMonolog());
        } else {
            $this->configureHandler($log);
        }
        return $log;
    }

    /**
     * Get the name of the log "channel".
     *
     * @return string
     */
    protected function channel()
    {
        return $this->app->bound('env') ? $this->app->environment() : 'production';
    }

    /**
     * Configure the Monolog handlers for the application.
     *
     * @param  \Illuminate\Log\Writer  $log
     * @return void
     */
    protected function configureHandler(Writer $log)
    {
        $this->{'configure'.ucfirst($this->handler()).'Handler'}($log);
    }

    /**
     * Configure the Monolog handlers for the application.
     *
     * @param  \Illuminate\Log\Writer  $log
     * @return void
     */
    protected function configureSingleHandler(Writer $log)
    {
        $log->useFiles(
            $this->app->storagePath().'/logs/laravel.log',
            $this->logLevel()
        );
    }

    /**
     * Configure the Monolog handlers for the application.
     *
     * @param  \Illuminate\Log\Writer  $log
     * @return void
     */
    protected function configureDailyHandler(Writer $log)
    {
        $log->useDailyFiles(
            $this->app->storagePath().'/logs/laravel.log', $this->maxFiles(),
            $this->logLevel()
        );
    }

    /**
     * Configure the Monolog handlers for the application.
     *
     * @param  \Illuminate\Log\Writer  $log
     * @return void
     */
    protected function configureSyslogHandler(Writer $log)
    {
        $log->useSyslog('laravel', $this->logLevel());
    }

    /**
     * Configure the Monolog handlers for the application.
     *
     * @param  \Illuminate\Log\Writer  $log
     * @return void
     */
    protected function configureErrorlogHandler(Writer $log)
    {
        $log->useErrorLog($this->logLevel());
    }

    /**
     * Get the default log handler.
     *
     * @return string
     */
    protected function handler()
    {
        if ($this->app->bound('config')) {
            return $this->app->make('config')->get('app.log', 'single');
        }

        return 'single';
    }

    /**
     * Get the log level for the application.
     *
     * @return string
     */
    protected function logLevel()
    {
        if ($this->app->bound('config')) {
            return $this->app->make('config')->get('app.log_level', 'debug');
        }

        return 'debug';
    }

    /**
     * Get the maximum number of log files for the application.
     *
     * @return int
     */
    protected function maxFiles()
    {
        if ($this->app->bound('config')) {
            return $this->app->make('config')->get('app.log_max_files', );
        }

        return ;
    }
}
           

5、最後注冊建立的

LogServiceProvider.php

服務到容器裡面覆寫掉底層的

LogServiceProvider

#打開 config/app.php在 providers數組裡面添加上
App\Providers\LogServiceProvider::class,
           
到此大功完成,可以建立一個控制器來看看實作的效果
<?php
namespace App\Http\Controllers;
/**
 * 資料
 */
class TestController extends Controller{
    public function log()
    {
        echo "我是來測試的";
        \Log::info('我是來測試日志的', ['content' => ]);
        \Log::debug('我是來測試日志的');
        \Log::error('我是來測試日志的');
        \Log::warning('我是來測試日志的');
    }
}