1. 程式人生 > >laravel5日誌設定篇(3/3) – 精確到微秒及日誌輸出位置記錄

laravel5日誌設定篇(3/3) – 精確到微秒及日誌輸出位置記錄

想要實現的功能

  • 記錄日誌輸出時的時間精度到微秒
  • 記錄日誌輸出時程式執行位置(方法/行數)
  • 記錄程序ID
例如:
  • app.log
[2017-10-22 10:13:57.833504] production.INFO: -- Startup {"method":"GET","uri":"/v1/stocks"} {"pid":7124,"line":"App\\Bootstrap\\ApplicationLog->startupLog:66"}
[2017-10-22 10:13:57.898702] production.INFO: get stocks info  {"pid":7124,"line":"App\\Http\\Controllers\\StocksController->index:66"}
[2017-10-22 10:13:57.903274] production.INFO: -- Shutdown {"time":"70.371[ms]","memory":"2048[kb]"} {"pid":7124,"line":"App\\Bootstrap\\ApplicationLog->handleShutdownLog:81"}
  • sql.log
[2017-10-22 10:11:19.750913] production.DEBUG: select count(*) as aggregate from `stocks_input` where `stocks_input`.`deleted_at` is null; {"time":0.63} {"pid":7124}
[2017-10-22 10:11:19.752787] production.DEBUG: select * from `stocks_input` where `stocks_input`.`deleted_at` is null order by `created_at` desc limit 10 offset 0; {"time":0.83} {"pid":7124}
[2017-10-22 10:11:19.756438] production.DEBUG: select * from `goods` where `goods`.`id` = 1 limit 1; {"time":0.9} {"pid":7124}

環境

  • php 7.0.22
  • laravel 5.2.*

具體實現

  1. 繼承Illuminate\Log\Writer類,複寫getDefaultFormatter方法
  2. 編寫Monolog用處理模組
  3. 1步驟建立的類替換老Writer及註冊Monolog用處理模組
ps. 依賴設定 laravel5日誌設定篇(1/3) – 記錄開始和結束日誌 laravel5日誌設定篇(2/3) – 記錄sql日誌
新Write類 (app/Utils/Writer.php)
<?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);
    }
}
Monolog輸出處理模組
  • 程式執行位置資訊 (app/Utils/Monolog/Processor/IntrospectionProcessor.php)
<?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 = 0;

        while (isset($trace[$i]['class'])) {
            foreach ($this->skipClassesPartials as $part) {
                if (strpos($trace[$i]['class'], $part) !== false) {
                    $i++;
                    continue 2;
                }
            }
            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 - 1]['file'])) {
            $line = $trace[$i - 1]['file'];
        }
        if (null !== $line && isset($trace[$i - 1]['line'])) {
            $line = $line . ':' . $trace[$i - 1]['line'];
        }

        $record['extra']['line'] = $line;

        return $record;
    }
}
  • 執行緒ID資訊 (app/Utils/Monolog/Processor/ProcessIdProcessor.php)
<?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;
    }
}
替換老Writer及註冊Monolog用處理模組 (app/Providers/LogServiceProvider.php)
<?php

namespace App\Providers;

// 引入新建立IntrospectionProcessor, ProcessIdProcessor, Writer類
use App\Utils\Monolog\Processor\IntrospectionProcessor;
use App\Utils\Monolog\Processor\ProcessIdProcessor;
use App\Utils\Monolog\Writer;
use Carbon\Carbon;
use Illuminate\Support\ServiceProvider;
use Monolog\Logger as Monolog;

/**
 * 日誌記錄器服務
 *
 * @package app.Providers
 */
class LogServiceProvider extends ServiceProvider
{

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('app-log', function () {
            return $this->createAppLogger();
        });
        $this->app->singleton('sql-log', function () {
            return $this->createSqlLogger();
        });
    }

    /**
     * Create the app logger.
     *
     * @return \Illuminate\Log\Writer
     */
    public function createAppLogger()
    {
        //新增
        $processors = [
            new ProcessIdProcessor(),
            new IntrospectionProcessor()
        ];
        $log = new Writer(
            new Monolog($this->channel(), [], $processors), $this->app['events']
        );
        $this->configureHandler($log, 'app');
        return $log;
    }

    /**
     * Create the sql logger.
     *
     * @return \Illuminate\Log\Writer
     */
    public function createSqlLogger()
    {
        //新增
        $processors = [
            new ProcessIdProcessor(),
        ];
        $log = new Writer(
            new Monolog($this->channel(), [], $processors), $this->app['events']
        );
        $this->configureHandler($log, 'sql');
        return $log;
    }
    ...


檢視原文:https://www.huuinn.com/archives/343
更多技術乾貨:風勻坊
關注公眾號:風勻坊