【问题标题】:In Laravel can I set a default context for the Log facade在 Laravel 中,我可以为 Log 门面设置默认上下文吗
【发布时间】:2021-07-21 18:08:28
【问题描述】:

我经常使用Log:: 外观,并且有一个名为LogHelper 的帮助程序类,它为我提供了一个静态方法LogHelper::context(),其中包括我需要跟踪请求的许多关键值。但是每次使用都必须每次都输入,这会导致错误修剪和填充效率不高。

我正在寻找一种默认注入值的方法,并允许我在需要时覆盖它们。

目前我就是这样使用它的,

Log::debug('Request Started', LogHelper::context());

我正在寻找的是默认注入上下文

Log::debug('Request Started');

如果需要,可以选择覆盖它:

Log::debug('Request Started', ['more' => 'context'] + LogHelper::context());

PS,LogHelper::context() 返回一个简单的key => value 数组,其中包括一些我需要调试请求的人员,它不直接在消息中使用这些值的原因是因为我作为结构化数据记录到 graylog,并且这样我就可以按任意键过滤了。

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    我已经通过使用tap 功能和$logger->withContext() 解决了这个问题(注意:后者是在 Laravel 8.49 中添加的)。

    您想创建一个包含上下文逻辑的新类。我在 app/ 中创建了一个额外的 Logging 文件夹,我的日志自定义设置位于其中。

    app/Logging/WithAuthContext.php:

    <?php
    
    namespace App\Logging;
    
    use Illuminate\Log\Logger;
    
    class WithAuthContext
    {
        public function __invoke(Logger $logger)
        {
            $logger->withContext([
                'ip' => request()?->ip(),
                'ua' => request()?->userAgent(),
            ]);
        }
    }
    

    根据您使用的日志记录通道,您必须将类添加到每个要添加上下文的通道。所以在app/config/logging.php:

    <?php
    
    use App\Logging\WithAuthContext;
    use Monolog\Handler\NullHandler;
    use Monolog\Handler\StreamHandler;
    use Monolog\Handler\SyslogUdpHandler;
    
    return [
    // ...
        'channels' => [
            // ...
            'single' => [
                'driver' => 'single',
                'path' => storage_path('logs/laravel.log'),
                'level' => env('LOG_LEVEL', 'debug'),
                'tap' => [WithAuthContext::class],
            ],
            // ...
        ],
    ];
    

    【讨论】:

      【解决方案2】:

      有一种方法,但它并不漂亮。您可以创建自定义独白记录器驱动程序。该过程在https://laravel.com/docs/8.x/logging#creating-monolog-handler-channels 进行了描述。

      这是一个可能的实现:

      class ContextEnrichingLogger extends \Monolog\Handler\AbstractHandler {
       
          
          private $logger;
      
          public function __construct($level = Monolog\Logger::DEBUG, bool $bubble = true, $underlyingLogger = 'single') {
             $this->logger = Log::driver($underlyingLogger);
          }
      
          public function handle(array $record) {
              $record['context'] += LogHelper::context();
              return $this->logger->handle($record);
          }  
      
      }
      
      

      然后在您的config/logging.php 中将其注册为自定义记录器:

      return [ 
          'default' => 'enriched',
          //...
          'channels' => [
             // ...
             'enriched' => [
                  'driver' => 'monolog',
                  'handler' => ContextEnrichingLogger::class,
                  'level' => env('APP_LOG_LEVEL', 'debug'),
                  "with" => [
                      "underlyingLogger" => env('LOG_CHANNEL', 'single')
                  ]
              ]
      
         ]
      ];
           
      

      我还没有测试过这个特定的记录器,但这就是我定义其他自定义记录器的方式。

      注意,这可能也可以通过自定义格式化程序实现,尽管我认为这可能是同样的麻烦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-22
        • 2015-09-08
        • 1970-01-01
        • 2015-12-19
        • 2011-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多