Laravel 日志实战:Channel 体系、结构化上下文与生产配置
Laravel 日志中文实战:config/logging.php 频道配置、single/daily/stack/monolog/custom 五种驱动、Log 门面与 context 结构化字段、FilterHandler 级别过滤、tap 自定义 Monolog、生产环境 JSON 输出,以及观测云 DataKit 采集告警落地方案。
Laravel 的日志体系建立在 Monolog 之上,用"频道(channel)+ 驱动(driver)"的声明式配置把 Monolog 的灵活性包装成了优雅的框架体验。本文讲解频道驱动的选择、结构化上下文的写法、生产配置清单,以及观测云平台落地方案。
核心要点速览
- 一切配置在 config/logging.php:默认频道由
LOG_CHANNEL环境变量控制,代码里Log::info()即用。 - daily 驱动优于 single:按天轮转 + 自动清理(days 参数),告别单个巨型日志文件。
- stack 驱动实现多路输出:一条日志同时进多个频道,是"文件 + 告警"组合的基础。
- 生产落地:JSON 格式 stdout 输出,观测云 DataKit 采集,监控器告警。
快速上手: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());
}
}
}
生产配置清单
LOG_CHANNEL=stack(daily + stderr)或容器环境直接 stderr;- JSON 化:tap 注入 JsonFormatter;
- 级别走环境变量
LOG_LEVEL=info; - daily 的 days 按磁盘与合规要求设置(14-30 天);
- 队列消费者日志与 Web 日志同频道或按业务分频道。
观测云落地:Laravel 日志采集与分析
- 应用侧:JSON 输出 stdout/stderr(容器)或 daily 文件(主机)。不要在应用内直推远程日志服务——采集交给 DataKit,应用与后端解耦。
- DataKit 采集:容器 stdout 自动采集;主机
conf.d/log/logging.conf的logfiles指向storage/logs/laravel-*.log,source: laravel、service标识服务。JSON 自动解析。 - Pipeline 标准化:
level_name映射标准status,datetime解析为time,context 字段顶层化。 - 检索告警:日志查看器按 status/service 过滤,聚类分析归纳异常;监控器对 error 以上级别、特定异常关键字设阈值,告警策略路由钉钉/企业微信/飞书。
- 链路关联:接入 OpenTelemetry PHP 探针后 trace_id 进日志,与观测云 APM 双向跳转。
- 成本控制:多索引按级别拆保留策略,历史数据转发归档对象存储。
常见问题(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 或开启查询日志可以,但生产慎开——量极大且可能含敏感数据。排障时临时开启,或用观测云 APM 的数据库链路分析替代。
系列阅读
- 上一篇:Monolog 实战指南
- 下一篇:Log4php 实战指南
- 相关阅读:PHP 日志实战 | 微服务日志最佳实践