
日志默认存哪儿、怎么看
Laravel 默认把日志写到 storage/logs/laravel.log,每行开头带时间戳和级别(如 [2024-05-12 14:23:01] production.ERROR:)。直接用 tail -f storage/logs/laravel.log 实时看最常用。
注意:如果项目部署在生产环境且用了 php artisan config:cache,但没运行 php artisan config:clear 就改过 config/logging.php,日志可能还写老位置,甚至静默失败——这时候 laravel.log 不更新,也看不到错误。
- 开发时用
php artisan tinker测试日志:Log::error('test');,立刻查文件确认是否落盘 - 线上服务器若启用了 SELinux 或严格权限(比如
storage目录属主不是 web server 用户),chmod -R 755 storage不够,得确保storage/logs可写,否则日志直接丢弃,不报错 - 日志文件超过
daily配置的days(默认 7 天)会被自动清理,别等找不到了才想起备份
怎么让 Laravel 写进自定义文件(比如 api.log)
核心是改 config/logging.php 里的 channel,不是改 Log:: 调用方式。Laravel 的 Log:: 是门面,背后走的是配置里定义的 channel。
比如要新增一个叫 api 的 channel,专门记 API 请求日志:
/*
在 config/logging.php 的 'channels' 数组里加:
*/
'api' => [
'driver' => 'single',
'path' => storage_path('logs/api.log'),
'level' => 'debug',
],然后代码里用 Log::channel('api')->info('API called'); 就会写进 storage/logs/api.log。
- 别漏掉
storage_path()—— 写成绝对路径或相对路径(如./logs/api.log)会导致日志写到错目录,甚至写失败无提示 - 如果用
stackdriver 组合多个 channel,记得检查每个子 channel 的level,低优先级 channel(如level => 'warning')会过滤掉info日志 - 自定义 channel 名不能叫
stderr或errorlog这类 PHP 内置通道名,否则行为不可控
日志内容太乱?怎么控制格式和字段
Laravel 默认用 Monolog\Formatter\LineFormatter,但只输出消息体和基础元数据。想加 trace、请求 ID、用户 ID,得配 tap 或换 formatter。
常见做法是在 channel 配置里加 tap 数组,引用一个闭包或类来修改 Monolog 实例:
'api' => [
'driver' => 'single',
'path' => storage_path('logs/api.log'),
'tap' => [App\Logging\AddRequestContext::class],
],然后在 AddRequestContext 的 __invoke 方法里调用 $logger->pushProcessor(...) 加上下文处理器。
- 别在
tap里做耗时操作(比如查数据库),日志是同步阻塞的,会影响接口响应 - Monolog 的
LineFormatter默认不输出上下文数组内容,得设includeStacktraces或换JsonFormatter,否则Log::info('msg', ['user_id' => 123])的数组部分可能被截断或忽略 - 如果用了 Horizon 或队列,队列任务里的日志不会自动带上 HTTP 上下文(如 request id),必须手动传或靠
JobProcessed事件补全
日志写不进去?排查这三件事
不是代码问题,大概率卡在权限、配置加载、或 driver 不兼容上。
- 执行
php -r "var_dump(is_writable(storage_path('logs')));",返回bool(false)就说明磁盘权限不对,别信ls -l看着有写权限就没事——PHP CLI 和 Web Server 用户可能不同 - 运行
php artisan tinker后输入config('logging.channels.api'),如果输出null,说明配置没生效,检查是否缓存了配置(config:cache)且没清缓存 - 用了
syslog或papertrail这类外部 driver 时,本地storage/logs必然为空——这不是 bug,是设计如此;但新手常误以为“日志丢了”,其实得去对应服务端查
日志系统本身不报错,它只是默默放弃写入。最可靠的验证方式永远是:改配置 → 清缓存 → 手动触发一条日志 → 立刻检查目标路径是否存在、内容是否更新、权限是否匹配。









