Menu

日志

日志

简介

为了帮助你更多的了解应用程序中到底发生了什么,Laravel 提供了强大的日志服务,允许你将日志消息、系统错误日志记录到文件,甚至使用 Slack 通知到你的整个团队。

在 Laravel 框架中,Laravel 使用 Monolog 库,它为各种强大的日志处理提供支持。Laravel 使配置这些处理程序变得简单,允许你混合并匹配它们自定义的应用程序日志处理。

配置

所有的应用程序日志系统配置都位于 config/logging.php 配置文件中。这个文件允许你配置你的应用程序日志通道,所以务必查看每个可用的通道及它们的选项。当然,我们将在下面回顾一些常用的选项。

默认情况下,Laravel 将使用 stack 去记录日志消息。stack 通道被用来将多个日志通道聚合到一个单一的通道中。关于堆栈的更多信息,查看 以下文档

配置通道名称

默认情况下,Monolog 使用与当前环境匹配的『通道名称』进行实例化,比如 production 或者 local。要改变这个值,需添加一个 name 选项到你的通道配置中:

'stack' => [
        'driver' => 'stack',
        'name' => 'channel-name',
        'channels' => ['single', 'slack'],
],

可用的通道驱动

名称 描述
single 一个便于创建『多通道』通道的包装器
daily 单个文件或者基于日志通道的路径 (StreamHandler)
slack 一个每天轮换的基于 Monolog 驱动的 RotatingFileHandler
syslog 一个基于 Monolog 驱动的 SyslogHandler
errorlog 一个基于 Monolog 驱动的 ErrorLogHandler
monolog 一个可以使用任何支持 Monolog 处理程序的 Monolog 工厂驱动程序
custom 一个调用指定工厂创建通道的驱动程序

{tip} 有关 monologcustom 驱动,查看 高级通道自定义

配置 Slack 通道

slack 通道需要 url 配置选项。这个 URL 应当与你为 Slack 团队配置的一个 incoming webhook 相匹配。

构建日志栈

如前所述,stack 驱动允许你将多个通道合并到一个单一日志通道中。为了说明如何使用日志栈,让我们看一个你可能在生产应用配置中看到的实例配置:

'channels' => [
        'stack' => [
                'driver' => 'stack',
                'channels' => ['syslog', 'slack'],
        ],

        'syslog' => [
                'driver' => 'syslog',
                'level' => 'debug',
        ],

        'slack' => [
                'driver' => 'slack',
                'url' => env('LOG_SLACK_WEBHOOK_URL'),
                'username' => 'Laravel Log',
                'emoji' => ':boom:',
                'level' => 'critical',
        ],
],

让我们剖析这个配置。首先,注意我们的 stack 通道通过它的 channels 选项聚合其它两个通道:syslogslack。因此,当记录日志消息时,这两个通道都有机会去记录日志消息。

日志级别

注意上面实例中在 syslogslack 通道配置中存在的 level 配置选项。这个选项决定了一个消息必须被通道记录的最小『level』。Monolog 为 Laravel 的日志服务提供了 RFC 5424 规范 中定义的所有日志级别:emergencyalertcriticalerrorwarningnoticeinfodebug

因此,假设我们记录一个日志消息使用 debug 方法:

Log::debug('An informational message.');

根据我们的配置,syslog 通道将写消息到系统日志;然而,由于错误消息不是 critical 或者这个级别之上,它将不被发送到 Slack。但是,如果我们记录一个 emergency 的日志消息,它将被同时发送到系统日志和 Slack,因为 emergency 级别高于我们对两个通道最低级别的阈值:

Log::emergency('The system is down!');

记录日志消息

你可以通过 Log 外观类将信息写入到日志。如前所述,日志器提供在 RFC 5424 规范 中定义的八个日志级别:emergency, alert, critical, error, warning, notice, infodebug

Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);

因此,你可以调用这些方法中的任何一个去记录相应级别的一个日志消息。默认情况下,消息将写入到你的 config/logging.php 配置文件配置的默认日志通道中:

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
        /**
         * Show the profile for the given user.
         *
         * @param  int  $id
         * @return Response
         */
        public function showProfile($id)
        {
                Log::info('Showing user profile for user: '.$id);

                return view('user.profile', ['user' => User::findOrFail($id)]);
        }
}

上下文信息

还可以将一组上下文数组数据传递给日志方法。这个上下文数据将被格式化并用日志消息显示:

Log::info('User failed to login.', ['id' => $user->id]);

记录日志到指定通道

有时候你可能希望将日志记录到非默认通道。你可以使用 Log Facade 中的 channel 方法,将日志记录到应用配置中存在的任何渠道:

Log::channel('slack')->info('Something happened!');

如果你想按需创建多个渠道的日志堆栈,你可以使用 stack 方法:

Log::stack(['single', 'slack'])->info('Something happened!');

先进的 Monolog 日志通道定制

自定义 Monolog 日志通道

有时你可能需要完全配置 Monolog 现有的通道。例如:你想要为现有通道自定义一个 Monolog FormatterInterface 实现。

首先,在频道配置文件中定义一个 tap 数组。tap 数组应该包含所需的类列表,这些类就是 Monolog 实例创建后需要自定义(或开发)的类:

'single' => [
    'driver' => 'single',
    'tap' => [App\Logging\CustomizeFormatter::class],
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
],

当你完成了通道中 tap 选项的配置,你就可以开始写 Monolog 实例自定义类了。这个类只需要一个方法: __invoke,这个方法可以接收一个 Illuminate\Log\Logger 实例。 Illuminate\Log\Logger 实例代理了所有 Monolog 实例底层方法调用:

<?php

namespace App\Logging;

class CustomizeFormatter
{
    /**
     * 自定义日志实例
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(...);
        }
    }
}

{tip} 所有的「tap」类可以通过 服务容器 解析,所以它们所需的任何构造函数依赖项都会被自动注入。

创建自定义通道

Monolog 有各种可用的处理程序。 在某些情况下,你希望创建的记录器类型仅仅是具有特定处理程序实例的 Monolog 驱动程序。 可以使用 monolog 驱动程序创建这些通道。

当使用 monolog 驱动程序时,handler 配置选项用于指定将实例化哪个处理程序。 可选地,可以使用 handler_with 配置选项指定处理程序所需的任何构造函数参数:

'logentries' => [
    'driver'  => 'monolog',
    'handler' => Monolog\Handler\SyslogUdpHandler::class,
    'handler_with' => [
        'host' => 'my.logentries.internal.datahubhost.company.com',
        'port' => '10000',
    ],
],

Monolog 格式化

当使用 monolog 驱动程序时,Monolog LineFormatter 将用作默认格式化程序。 但是,你可以使用 formatterformatter_with 配置选项自定义传递给处理程序的格式化程序的类型:

'browser' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\BrowserConsoleHandler::class,
    'formatter' => Monolog\Formatter\HtmlFormatter::class,
    'formatter_with' => [
        'dateFormat' => 'Y-m-d',
    ],
],

如果你使用能够提供自我格式化程序的 Monolog 处理程序,你可以将 formatter 配置选项的值设置为 default

'newrelic' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\NewRelicHandler::class,
    'formatter' => 'default',
],

通过工厂创建渠道

如果你想定义一个完全自定义的通道,你可以完全控制 Monolog 的实例化和配置,你可以在 config / logging.php 配置文件中指定 custom 驱动程序类型。 你的配置应该包含一个 via 选项,指向将被调用以创建 Monolog 实例的工厂类:

'channels' => [
    'custom' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],

一旦配置了 custom 通道,就可以定义创建 Monolog 实例的类。 这个类只需要一个方法:__ invoke,它就可以返回 Monolog 实例:

<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * 创建一个 Monolog 实例
     *
     * @param  array  $config
     * @return \Monolog\Logger
     */
    public function __invoke(array $config)
    {
        return new Logger(...);
    }
}

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 1
发起讨论


Benny
队列中无法使用 log 记录日志
0 个点赞 | 1 个回复 | 分享