> ## 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`   | 由 factory 類別完全自訂通道            |

### 日誌等級

Laravel 支援 [RFC 5424](https://tools.ietf.org/html/rfc5424) 定義的 8 個日誌等級。
以嚴重度由高至低排列。

| 等級          | 使用範例                   |
| ----------- | ---------------------- |
| `emergency` | 整個系統無法使用，需立即處理         |
| `alert`     | 需人立即介入的狀態（例如 DB 連線中斷）  |
| `critical`  | 主要功能停擺的重大故障            |
| `error`     | 執行期錯誤，需處理但未必立即         |
| `warning`   | 潛在問題，如使用不建議 API 或非預期資料 |
| `notice`    | 正常但值得注意                |
| `info`      | 使用者登入、訂單確立等一般操作日誌      |
| `debug`     | 開發期詳細除錯資訊              |

通道的 `level` 設定代表**最低日誌等級**。
例如 `level` 為 `error` 時，僅會寫入 `error` 及以上等級（`critical`、`alert`、`emergency`）。

## 基本用法

### Log Facade

透過 `Illuminate\Support\Facades\Log` Facade 撰寫各等級的訊息。

```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` Facade 也能使用。

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

// 也可以指定等級與 context
log('已建立使用者。', 'info', ['user_id' => $user->id]);
```

### 附加脈絡（context）

將訊息與陣列的脈絡一併傳入，可統整記錄相關資訊。

```php theme={null}
Log::info('登入失敗。', [
    'user_id' => $user->id,
    'ip'      => $request->ip(),
    'reason'  => '密碼不符',
]);
```

#### withContext() — 對整個通道加上共通脈絡

若想對特定通道之後所有日誌都附上共通資訊，可以用 `withContext()`。
適合用來附上像 request 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',
],
```

將 `slack` 加入 `stack`，並設定 `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 匯入。');
```

## 實用範例

### 於中介軟體加上 request ID

為所有日誌加上共通的 request 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) 是一款可在終端機即時查看應用程式日誌的開發工具。與一般 `tail` 不同，它設計上可搭配包含 [Laravel Nightwatch](https://nightwatch.laravel.com)、Sentry、Flare 在內的所有日誌驅動運作。

<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

# 顯示 stack trace
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`   | 使用不建議 API 或出現非預期資料等需注意情況 |
    | `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-TW/blog/nightwatch-introduction.md)
- [錯誤處理](/zh-TW/error-handling.md)
- [用 Laravel 構建 MCP 伺服器](/zh-TW/advanced/mcp-server.md)
- [Laravel Prompts](/zh-TW/prompts.md)
- [Eloquent Observer 與模型事件](/zh-TW/advanced/eloquent-observers.md)
