翻译进度
11
分块数量
2
参与人数

日志

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


日志

简介

为了帮助你更好地了解应用程序中的情况,Laravel 提供了强大的日志服务,它允许你将消息记录到文件、系统错误日志,甚至发送到 Slack 以通知整个团队。

Laravel 的日志是基于“通道(channels)”的。每个通道表示一种特定的日志写入方式。例如,single 通道会将日志写入单个日志文件,而 slack 通道会将日志消息发送到 Slack。根据日志的严重性,消息可以写入多个通道。

在底层,Laravel 使用了 Monolog 库,它提供了多种强大的日志处理器。Laravel 使得配置这些处理器非常简单,你可以自由组合它们,从而自定义应用程序的日志处理方式。

配置

所有控制应用程序日志行为的配置选项都位于 config/logging.php 配置文件中。该文件允许你配置应用程序的日志通道,所以务必查看每个可用通道及其选项。下面我们将介绍一些常见选项。

无与伦比 翻译于 2小时前

默认情况下,Laravel 在记录日志消息时会使用 stack 通道。stack 通道用于将多个日志通道聚合为单个通道。有关构建堆栈的更多信息,请查看下面的文档

可用通道驱动

每个日志通道都由一个“驱动(driver)”提供支持。驱动决定日志消息实际如何以及记录到哪里。每个 Laravel 应用程序都提供以下日志通道驱动。这些驱动的大多数条目已经存在于应用程序的 config/logging.php 配置文件中,因此务必查看该文件以熟悉其内容:

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

[!注意]
查看高级通道自定义文档,以了解更多关于 monologcustom 驱动的信息。

配置通道名称

默认情况下,Monolog 会使用与当前环境匹配的“通道名称”实例化,例如 productionlocal。要更改此值,可以在通道配置中添加 name 选项:

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

无与伦比 翻译于 2小时前

通道前置条件

配置 Single 和 Daily 通道

singledaily 通道有三个可选的配置项:bubblepermissionlocking

| 名称 | 描述 | 默认值 | | --- | --- | --- | | `bubble` | 指示消息在处理后是否应冒泡到其他通道。 | `true` | | `locking` | 在写入日志文件之前尝试锁定文件。 | `false` | | `permission` | 日志文件的权限。 | `0644` |

此外,daily 通道的保留策略可以通过环境变量 LOG_DAILY_DAYS 配置,或者通过设置配置项 days 来指定。

| 名称 | 描述 | 默认值 | | --- | --- | --- | | `days` | 每天日志文件应保留的天数。 | `14` |

配置 Papertrail 通道

papertrail 通道需要 hostport 配置项。可以通过环境变量 PAPERTRAIL_URLPAPERTRAIL_PORT 设置这些值。相关值可以从 Papertrail 官方文档 获取。

配置 Slack 通道

slack 通道需要一个 url 配置项。可以通过环境变量 LOG_SLACK_WEBHOOK_URL 设置该 URL。这个 URL 应该对应你为 Slack 团队配置的 Incoming Webhook

默认情况下,Slack 只会接收 critical 级别及以上的日志消息;你可以通过环境变量 LOG_LEVEL 或在 Slack 日志通道配置数组中修改 level 配置项来调整此级别。

无与伦比 翻译于 2小时前

记录弃用警告

PHP、Laravel 和其他库经常通知用户,它们的一些功能已被弃用,并将在将来的版本中移除。如果您希望记录这些弃用警告,可以使用 LOG_DEPRECATIONS_CHANNEL 环境变量或在应用程序的 config/logging.php 配置文件中指定您首选的 deprecations 日志通道:

'deprecations' => [
    'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
    'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],

'channels' => [
    // ...
]

或者,您可以定义一个名为 deprecations 的日志通道。如果存在具有此名称的日志通道,它将始终用于记录弃用警告:

'channels' => [
    'deprecations' => [
        'driver' => 'single',
        'path' => storage_path('logs/php-deprecation-warnings.log'),
    ],
],

构建日志堆栈

如前所述,stack 驱动程序允许您将多个通道组合成一个便利的单个日志通道。为了说明如何使用日志堆栈,让我们看一个您可能在生产应用程序中看到的示例配置:

'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['syslog', 'slack'], // [tl! add]
        'ignore_exceptions' => false,
    ],

    'syslog' => [
        'driver' => 'syslog',
        'level' => env('LOG_LEVEL', 'debug'),
        'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
        'replace_placeholders' => true,
    ],

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

让我们分解这个配置。首先,注意到我们的 stack 通道通过其 channels 选项聚合了另外两个通道:syslogslack。因此,在记录消息时,这两个通道都有机会记录消息。然而,正如我们将在下文中看到的,这些通道是否实际记录消息可能取决于消息的严重性 /“级别”。

dkp 翻译于 1个月前

Log Levels

Take note of the level configuration option present on the syslog and slack channel configurations in the example above. This option determines the minimum "level" a message must be in order to be logged by the channel. Monolog, which powers Laravel's logging services, offers all of the log levels defined in the RFC 5424 specification. In descending order of severity, these log levels are: emergency, alert, critical, error, warning, notice, info, and debug.

So, imagine we log a message using the debug method:

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

Given our configuration, the syslog channel will write the message to the system log; however, since the error message is not critical or above, it will not be sent to Slack. However, if we log an emergency message, it will be sent to both the system log and Slack since the emergency level is above our minimum level threshold for both channels:

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

Writing Log Messages

You may write information to the logs using the Log facade. As previously mentioned, the logger provides the eight logging levels defined in the RFC 5424 specification: emergency, alert, critical, error, warning, notice, info and debug:

use Illuminate\Support\Facades\Log;

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

You may call any of these methods to log a message for the corresponding level. By default, the message will be written to the default log channel as configured by your logging configuration file:

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     */
    public function show(string $id): View
    {
        Log::info('Showing the user profile for user: {id}', ['id' => $id]);

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

Contextual Information

An array of contextual data may be passed to the log methods. This contextual data will be formatted and displayed with the log message:

use Illuminate\Support\Facades\Log;

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

Occasionally, you may wish to specify some contextual information that should be included with all subsequent log entries in a particular channel. For example, you may wish to log a request ID that is associated with each incoming request to your application. To accomplish this, you may call the Log facade's withContext method:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class AssignRequestId
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $requestId = (string) Str::uuid();

        Log::withContext([
            'request-id' => $requestId
        ]);

        $response = $next($request);

        $response->headers->set('Request-Id', $requestId);

        return $response;
    }
}

If you would like to share contextual information across all logging channels, you may invoke the Log::shareContext() method. This method will provide the contextual information to all created channels and any channels that are created subsequently:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class AssignRequestId
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $requestId = (string) Str::uuid();

        Log::shareContext([
            'request-id' => $requestId
        ]);

        // ...
    }
}

[!NOTE]
If you need to share log context while processing queued jobs, you may utilize job middleware.

Writing to Specific Channels

Sometimes you may wish to log a message to a channel other than your application's default channel. You may use the channel method on the Log facade to retrieve and log to any channel defined in your configuration file:

use Illuminate\Support\Facades\Log;

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

If you would like to create an on-demand logging stack consisting of multiple channels, you may use the stack method:

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

On-Demand Channels

It is also possible to create an on-demand channel by providing the configuration at runtime without that configuration being present in your application's logging configuration file. To accomplish this, you may pass a configuration array to the Log facade's build method:

use Illuminate\Support\Facades\Log;

Log::build([
  'driver' => 'single',
  'path' => storage_path('logs/custom.log'),
])->info('Something happened!');

You may also wish to include an on-demand channel in an on-demand logging stack. This can be achieved by including your on-demand channel instance in the array passed to the stack method:

use Illuminate\Support\Facades\Log;

$channel = Log::build([
  'driver' => 'single',
  'path' => storage_path('logs/custom.log'),
]);

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

Monolog Channel Customization

Customizing Monolog for Channels

Sometimes you may need complete control over how Monolog is configured for an existing channel. For example, you may want to configure a custom Monolog FormatterInterface implementation for Laravel's built-in single channel.

To get started, define a tap array on the channel's configuration. The tap array should contain a list of classes that should have an opportunity to customize (or "tap" into) the Monolog instance after it is created. There is no conventional location where these classes should be placed, so you are free to create a directory within your application to contain these classes:

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

Once you have configured the tap option on your channel, you're ready to define the class that will customize your Monolog instance. This class only needs a single method: __invoke, which receives an Illuminate\Log\Logger instance. The Illuminate\Log\Logger instance proxies all method calls to the underlying Monolog instance:

<?php

namespace App\Logging;

use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;

class CustomizeFormatter
{
    /**
     * Customize the given logger instance.
     */
    public function __invoke(Logger $logger): void
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(new LineFormatter(
                '[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
            ));
        }
    }
}

[!NOTE]
All of your "tap" classes are resolved by the service container, so any constructor dependencies they require will automatically be injected.

Creating Monolog Handler Channels

Monolog has a variety of available handlers and Laravel does not include a built-in channel for each one. In some cases, you may wish to create a custom channel that is merely an instance of a specific Monolog handler that does not have a corresponding Laravel log driver. These channels can be easily created using the monolog driver.

When using the monolog driver, the handler configuration option is used to specify which handler will be instantiated. Optionally, any constructor parameters the handler needs may be specified using the handler_with configuration option:

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

Monolog Formatters

When using the monolog driver, the Monolog LineFormatter will be used as the default formatter. However, you may customize the type of formatter passed to the handler using the formatter and formatter_with configuration options:

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

If you are using a Monolog handler that is capable of providing its own formatter, you may set the value of the formatter configuration option to default:

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

Monolog Processors

Monolog can also process messages before logging them. You can create your own processors or use the existing processors offered by Monolog.

If you would like to customize the processors for a monolog driver, add a processors configuration value to your channel's configuration:

'memory' => [
    'driver' => 'monolog',
    'handler' => Monolog\Handler\StreamHandler::class,
    'handler_with' => [
        'stream' => 'php://stderr',
    ],
    'processors' => [
        // Simple syntax...
        Monolog\Processor\MemoryUsageProcessor::class,

        // With options...
        [
            'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
            'with' => ['removeUsedContextFields' => true],
        ],
    ],
],

Creating Custom Channels via Factories

If you would like to define an entirely custom channel in which you have full control over Monolog's instantiation and configuration, you may specify a custom driver type in your config/logging.php configuration file. Your configuration should include a via option that contains the name of the factory class which will be invoked to create the Monolog instance:

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

Once you have configured the custom driver channel, you're ready to define the class that will create your Monolog instance. This class only needs a single __invoke method which should return the Monolog logger instance. The method will receive the channels configuration array as its only argument:

<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * Create a custom Monolog instance.
     */
    public function __invoke(array $config): Logger
    {
        return new Logger(/* ... */);
    }
}

Tailing Log Messages Using Pail

Often you may need to tail your application's logs in real time. For example, when debugging an issue or when monitoring your application's logs for specific types of errors.

Laravel Pail is a package that allows you to easily dive into your Laravel application's log files directly from the command line. Unlike the standard tail command, Pail is designed to work with any log driver, including Sentry or Flare. In addition, Pail provides a set of useful filters to help you quickly find what you're looking for.

pail-example.png

Installation

[!WARNING]
Laravel Pail requires PHP 8.2+ and the PCNTL extension.

To get started, install Pail into your project using the Composer package manager:

composer require laravel/pail

Usage

To start tailing logs, run the pail command:

php artisan pail

To increase the verbosity of the output and avoid truncation (…), use the -v option:

php artisan pail -v

For maximum verbosity and to display exception stack traces, use the -vv option:

php artisan pail -vv

To stop tailing logs, press Ctrl+C at any time.

Filtering Logs

--filter

You may use the --filter option to filter logs by their type, file, message, and stack trace content:

php artisan pail --filter="QueryException"

--message

To filter logs by only their message, you may use the --message option:

php artisan pail --message="User created"

--level

The --level option may be used to filter logs by their log level:

php artisan pail --level=error

--user

To only display logs that were written while a given user was authenticated, you may provide the user's ID to the --user option:

php artisan pail --user=1

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~