> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 日志

> 学习如何使用 Laravel 日志系统，把应用运行情况记录到文件、Slack 或外部服务。

## 什么是日志

Laravel 日志系统以\*\*通道（Channel）\*\*为核心概念。
通道指的是一组定义了日志写入目标与方式的配置单元，可以组合文件、Slack、syslog 等各种输出目的地。

底层使用 [Monolog](https://github.com/Seldaek/monolog) 库，可以充分利用其丰富的 handler 与 formatter。

<Info>
  默认使用 `stack` 通道。`stack` 是把多个通道组合在一起的父通道。
</Info>

## 配置

日志配置集中在 `config/logging.php` 中。可通过环境变量 `LOG_CHANNEL` 切换默认通道。

```php theme={null}
// config/logging.php
'default' => env('LOG_CHANNEL', 'stack'),
```

### 可用的通道驱动

| 驱动         | 说明                             |
| ---------- | ------------------------------ |
| `single`   | 把所有日志写入单一文件                    |
| `daily`    | 按日期拆分文件写入（自动轮转）                |
| `slack`    | 通过 Slack Incoming Webhook 发送消息 |
| `stack`    | 组合多个通道的父通道                     |
| `syslog`   | 写入系统 syslog                    |
| `errorlog` | 写入 PHP 错误日志                    |
| `monolog`  | 直接指定 Monolog 的 handler         |
| `custom`   | 通过工厂类完全自定义通道                   |

### 日志级别

Laravel 支持 [RFC 5424](https://tools.ietf.org/html/rfc5424) 定义的 8 个日志级别，按严重性从高到低排列：

| 级别          | 用途示例                    |
| ----------- | ----------------------- |
| `emergency` | 系统整体不可用，需立即处理           |
| `alert`     | 必须由人立即介入的状态（如数据库断连）     |
| `critical`  | 主要功能停摆的重大故障             |
| `error`     | 运行时错误，需要处理，但通常不必即时      |
| `warning`   | 潜在问题，如使用了已弃用 API、遇到意外数据 |
| `notice`    | 正常运行，但值得关注的信息           |
| `info`      | 用户登录、订单确认等常规操作日志        |
| `debug`     | 开发时的详细调试信息              |

通道的 `level` 设置表示**最低日志级别**。
例如 `level` 为 `error` 时，只会记录 `error` 及以上（`critical`、`alert`、`emergency`）。

## 基本用法

### Log 门面

使用 `Illuminate\Support\Facades\Log` 门面按级别写入日志。

```php theme={null}
use Illuminate\Support\Facades\Log;

Log::emergency('系统已停机。');
Log::alert('数据库连接已断开。');
Log::critical('支付服务无响应。');
Log::error('更新用户数据失败。');
Log::warning('调用了已弃用的方法。');
Log::notice('配置文件已重载。');
Log::info('用户已登录。');
Log::debug('查询执行耗时：42ms');
```

在控制器中的示例：

```php theme={null}
<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    public function show(string $id): View
    {
        Log::info('显示用户资料。', ['user_id' => $id]);

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

### log() 辅助函数

使用 `log()` 辅助函数可以无需 import `Log` 门面直接写。

```php theme={null}
log('来自 helper 的日志。');

// 也可以指定级别和上下文
log('已创建用户。', 'info', ['user_id' => $user->id]);
```

### 附加上下文信息

传入上下文（数组）可与消息一起记录相关信息。

```php theme={null}
Log::info('登录失败。', [
    'user_id' => $user->id,
    'ip'      => $request->ip(),
    'reason'  => '密码不匹配',
]);
```

#### withContext() — 为通道后续所有日志附加公共上下文

若希望对特定通道之后的所有日志附加公共信息，可使用 `withContext()`。
适合像请求 ID 这样希望出现在所有日志中的信息。

```php theme={null}
Log::withContext(['request-id' => (string) Str::uuid()]);

// 之后所有日志都会自动包含 request-id
Log::info('开始处理。');
Log::error('发生错误。');
```

#### shareContext() — 对所有通道附加公共上下文

`withContext()` 只对目标通道生效，而 `shareContext()` 会作用于所有通道。

```php theme={null}
Log::shareContext(['app-version' => config('app.version')]);
```

## 通道配置

### stack 通道 — 同时写入多个通道

`stack` 通道让你一次调用同时写入多个通道。

```php theme={null}
// config/logging.php
'channels' => [
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['daily', 'slack'],
    ],

    'daily' => [
        'driver' => 'daily',
        'path'   => storage_path('logs/laravel.log'),
        'level'  => env('LOG_LEVEL', 'debug'),
        'days'   => 14,
    ],

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

以上配置将 `debug` 以上的日志写入 `daily`（文件），只有 `critical` 以上的日志才会发送到 `slack`。

<Tip>
  在生产环境，建议将 `slack` 通道级别设为 `error` 或 `critical`。
  若将琐碎日志推送到 Slack，会产生大量通知，重要告警反而容易被淹没。
</Tip>

### daily 通道 — 日志轮转

`daily` 通道按日期分文件保存，并自动清理旧文件。

```php theme={null}
'daily' => [
    'driver' => 'daily',
    'path'   => storage_path('logs/laravel.log'),
    'level'  => env('LOG_LEVEL', 'debug'),
    'days'   => env('LOG_DAILY_DAYS', 14), // 保留 14 天
],
```

<Warning>
  `days` 越小旧日志越快被删除。
  为在生产环境排查故障，请保留足够的保留期。
</Warning>

### 向 Slack 发送错误通知

获取 Slack 的 [Incoming Webhook URL](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks) 并配置到 `.env` 中。

```ini theme={null}
LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
```

```php theme={null}
// config/logging.php
'slack' => [
    'driver'   => 'slack',
    'url'      => env('LOG_SLACK_WEBHOOK_URL'),
    'username' => 'Laravel Error Bot',
    'emoji'    => ':fire:',
    'level'    => 'error',
],
```

在 `stack` 通道中加入 `slack` 并设置 `LOG_CHANNEL=stack`，发生错误时会自动通知。

### 写入特定通道

通过 `Log::channel()` 显式指定目标通道。

```php theme={null}
// 只写入 slack
Log::channel('slack')->error('支付服务无响应。');

// 同时写入多个通道
Log::stack(['daily', 'slack'])->critical('数据库连接失败。');
```

## 按需通道

使用 `Log::build()` 可以在不修改配置文件的情况下即时构建自定义通道。
适合测试或临时的输出目的。

```php theme={null}
use Illuminate\Support\Facades\Log;

$channel = Log::build([
    'driver' => 'single',
    'path'   => storage_path('logs/import-' . now()->format('Ymd') . '.log'),
]);

Log::stack([$channel])->info('开始导入 CSV。');
```

## 实用场景

### 通过中间件附加请求 ID

给所有日志附加同一个请求 ID，能大幅提升按请求追踪日志的能力。

<Steps>
  <Step title="创建中间件">
    ```shell theme={null}
    php artisan make:middleware AssignRequestId
    ```
  </Step>

  <Step title="实现 handle() 方法">
    ```php theme={null}
    <?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
    {
        public function handle(Request $request, Closure $next): Response
        {
            $requestId = (string) Str::uuid();

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

            $response = $next($request);

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

            return $response;
        }
    }
    ```
  </Step>

  <Step title="注册中间件">
    在 `bootstrap/app.php` 中作为全局中间件注册。

    ```php theme={null}
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(\App\Http\Middleware\AssignRequestId::class);
    })
    ```
  </Step>
</Steps>

配置好后，所有日志都会自动附带 `request-id`。

```
[2026-03-01 12:00:00] local.INFO: 用户已登录。 {"request-id":"550e8400-...","user_id":1}
[2026-03-01 12:00:00] local.INFO: 显示仪表盘。 {"request-id":"550e8400-..."}
```

### 记录弃用警告

可以将 PHP 或 Laravel 弃用功能的调用记录到日志中。

```php theme={null}
// config/logging.php
'deprecations' => [
    'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
    'trace'   => env('LOG_DEPRECATIONS_TRACE', false),
],
```

在 `.env` 中指定通道：

```ini theme={null}
LOG_DEPRECATIONS_CHANNEL=daily
```

## Laravel Pail — 实时日志监视

[Laravel Pail](https://github.com/laravel/pail) 是可以在终端实时查看应用日志的开发工具。

<Info>
  运行 Pail 需要 PHP 的 [PCNTL](https://www.php.net/manual/en/book.pcntl.php) 扩展。
</Info>

### 安装

```shell theme={null}
composer require --dev laravel/pail
```

### 基本用法

```shell theme={null}
# 流式查看日志
php artisan pail

# 详细展示（不省略）
php artisan pail -v

# 同时展示堆栈
php artisan pail -vv
```

### 日志过滤

```shell theme={null}
# 按关键字过滤
php artisan pail --filter="QueryException"

# 只按消息过滤
php artisan pail --message="登录"

# 按级别过滤
php artisan pail --level=error

# 只显示特定用户的日志
php artisan pail --user=1
```

## 小结

<AccordionGroup>
  <Accordion title="如何选择日志级别">
    | 级别          | 使用场景                   |
    | ----------- | ---------------------- |
    | `emergency` | 系统整体停机等致命故障            |
    | `alert`     | 必须由人立即介入的状态            |
    | `critical`  | 主要功能停摆的重大故障            |
    | `error`     | 意料之外的运行时错误，需要处理        |
    | `warning`   | 使用已弃用功能、遇到异常数据等需要关注的状态 |
    | `notice`    | 正常但值得记录的重要操作           |
    | `info`      | 用户操作、业务事件的记录           |
    | `debug`     | 开发期间的详细调试信息（生产环境通常不需要） |
  </Accordion>

  <Accordion title="通道选择指南">
    * **开发环境**：使用 `single` 或 `daily` 写文件
    * **生产环境**：使用 `stack` 组合 `daily`（文件保存）和 `slack`（错误通知）
    * **特定处理的日志**：使用 `Log::build()` 创建按需通道写入独立文件
    * **实时监视**：使用 `php artisan pail` 从终端查看
  </Accordion>

  <Accordion title="生产环境注意事项">
    * `debug` 日志中可能包含敏感信息，生产环境建议使用 `LOG_LEVEL=error` 或更高。
    * 日志文件请定期轮转，避免占满磁盘（使用 `daily` 通道的 `days` 设置）。
    * 向 Slack 等外部服务发送通知时注意速率限制，只推送严重错误。
  </Accordion>
</AccordionGroup>


## Related topics

- [Laravel Nightwatch 入门](/zh/blog/nightwatch-introduction.md)
- [错误处理](/zh/error-handling.md)
- [用 Laravel 构建 MCP 服务器](/zh/advanced/mcp-server.md)
- [Lottery 类](/zh/advanced/lottery.md)
- [Laravel Prompts](/zh/prompts.md)
