Laravel 日志实战:Channel 体系、结构化上下文与生产配置

Laravel 日志中文实战:config/logging.php 频道配置、single/daily/stack/monolog/custom 五种驱动、Log 门面与 context 结构化字段、FilterHandler 级别过滤、tap 自定义 Monolog、生产环境 JSON 输出,以及观测云 DataKit 采集告警落地方案。

最佳实践
Laravel 日志实战:Channel 体系、结构化上下文与生产配置技术指南封面

Laravel 的日志体系建立在 Monolog 之上,用"频道(channel)+ 驱动(driver)"的声明式配置把 Monolog 的灵活性包装成了优雅的框架体验。本文讲解频道驱动的选择、结构化上下文的写法、生产配置清单,以及采集后的字段验证。

核心要点速览

  • 一切配置在 config/logging.php:默认频道由 LOG_CHANNEL 环境变量控制,代码里 Log::info() 即用。
  • daily 驱动优于 single:按天轮转 + 自动清理(days 参数),告别单个巨型日志文件。
  • stack 驱动实现多路输出:一条日志同时进多个频道,是"文件 + 告警"组合的基础。
  • 采集验证:检查 Web 与队列进程的输出位置、JSON 字段和日志时间。

快速上手:Log 门面与结构化上下文

use Illuminate\Support\Facades\Log;

Log::info("订单创建成功", ["order_id" => $order->id, "amount" => $order->amount]);
Log::warning("库存不足", ["sku" => $sku]);
Log::error("扣款失败", ["order_id" => $order->id, "exception" => $e]);

// 指定频道
Log::channel("payments")->info("支付回调", $payload);

第二个参数是 context 数组(结构化字段),底层 Monolog 会把它序列化进日志。

六种频道驱动怎么选?

驱动 行为 适用
single 写入单个文件 storage/logs/laravel.log 本地开发
daily 按天轮转,days 控制保留天数 生产主机部署
syslog / errorlog 写系统日志 / PHP error_log 与系统日志整合
stack 聚合多个频道同时输出 生产多路输出
monolog 直接调用任意 Monolog Handler 高级定制(FilterHandler 等)
custom 工厂创建完全自定义 logger 特殊集成
// config/logging.php
"channels" => [
    "stack" => [
        "driver" => "stack",
        "channels" => ["daily", "stderr"],
        "ignore_exceptions" => false,
    ],
    "daily" => [
        "driver" => "daily",
        "path" => storage_path("logs/laravel.log"),
        "level" => env("LOG_LEVEL", "info"),
        "days" => 14,
    ],
    "stderr" => [
        "driver" => "monolog",
        "handler" => \Monolog\Handler\StreamHandler::class,
        "with" => ["stream" => "php://stderr"],
    ],
],

用 monolog 驱动做精细控制

monolog 驱动可以直接使用任意 Monolog Handler,例如 FilterHandler——只有精确匹配的级别才进入该频道(而非最低级别放行):

"alerts" => [
    "driver" => "monolog",
    "handler" => \Monolog\Handler\FilterHandler::class,
    "with" => [
        "handler" => new \Monolog\Handler\StreamHandler(storage_path("logs/critical.log")),
        "acceptedLevels" => [\Monolog\Level::Critical, \Monolog\Level::Alert, \Monolog\Level::Emergency],
    ],
],

tap:给频道注入自定义逻辑

"daily" => [
    "driver" => "daily",
    "path" => storage_path("logs/laravel.log"),
    "tap" => [App\Logging\CustomizeFormatter::class],
],

tap 类拿到 Monolog 实例后可换 formatter、加 processor——生产 JSON 化就靠它:

class CustomizeFormatter
{
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
            $handler->setFormatter(new \Monolog\Formatter\JsonFormatter());
        }
    }
}

生产配置清单

  1. LOG_CHANNEL=stack(daily + stderr)或容器环境直接 stderr;
  2. JSON 化:tap 注入 JsonFormatter;
  3. 级别走环境变量 LOG_LEVEL=info;
  4. daily 的 days 按磁盘与合规要求设置(14-30 天);
  5. 队列消费者日志与 Web 日志同频道或按业务分频道。

检查采集后的 Laravel 日志

先选定一种输出方式:容器用 stdout/stderr,主机部署可采集 daily 文件。在观测云 DataKit 的日志采集配置中指定文件路径,例如 storage/logs/laravel-*.log,并为当前 JSON 格式选择 Pipeline。

拿一条带异常与 context 的样本检查 level_name、datetime、job_id 是否按预期解析;将级别映射到 status,并核对日志时间。Web 请求和队列任务各测一次,避免只验证 Web 进程的日志配置。

确认字段后再按日志检测文档设置失败规则。例如只检查目标队列的任务失败,保留 job_id 供后续定位,而不是把所有 error 日志混成同一类故障。

常见问题(FAQ)

single 和 daily 到底选哪个?

生产一律 daily。single 的文件无限增长,排查时打开都费劲;daily 按天切分、自动清理,还可配合系统 logrotate 做更复杂的归档策略。

队列任务(Queue Worker)的日志在哪?

同在配置的频道里。Horizon/queue worker 是独立进程,日志同样走 Log 门面;建议用 context 加 job_id、queue 字段,平台侧按字段过滤还原任务执行。

Laravel 的异常都记到哪里?

框架异常处理器(App\Exceptions\Handler)默认把未处理异常写进默认频道。想定制(比如特定异常不记录、或附加业务上下文),重写 Handler 的 report 逻辑。

日志里能看到 SQL 吗?

DB::listen 或开启查询日志可以,但生产慎开——量极大且可能含敏感数据。排障时限制开启范围和持续时间,并检查 SQL 参数是否包含敏感数据。

系列阅读


获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台