laravel5日志设置篇(3/3) – 精确到微秒及日志输出位置记录

本文详细介绍了在Laravel5中如何将日志记录精确到微秒,并且讲解了如何设置日志的输出位置,帮助开发者更好地管理和调试应用日志。
想要实现的功能
  • 记录日志输出时的时间精度到微秒
  • 记录日志输出时程序执行位置(方法/行数)
  • 记录进程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
更多技术干货:风匀坊
关注公众号:风匀坊
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值