日志写不进storage/logs/主因是权限不足、LOG_CHANNEL配置为stderr或channel未指向文件驱动;需确保storage目录可写、检查logging.php中stack是否包含single/daily、并按环境设置LOG_CHANNEL与LOG_LEVEL。

日志写不进 storage/logs/,八成是权限、LOG_CHANNEL 配置或驱动路径没对上;不是代码写错了,而是环境和配置没对齐。
为什么 storage/logs/laravel.log 没更新?
最常见原因就三个:目录不可写、日志被重定向到 stderr、或者 channel 配置压根没指向文件驱动。
-
storage/目录必须对 Web 服务器用户(如www-data或nginx)可写,用chmod -R 775 storage/更安全,别直接777 - 检查
.env:如果设了LOG_CHANNEL=stderr,日志会输出到标准错误流(比如 Docker 的docker logs),不会落盘——这不是 bug,是目标变了 - 看
config/logging.php中'default' => env('LOG_CHANNEL', 'stack'),再确认'stack'的channels数组里是否真包含'single'或'daily'这类文件驱动
怎么按环境切 daily / single / stack?
不用改代码,全靠 .env 和 config/logging.php 联动控制。
- 开发环境推荐:
LOG_CHANNEL=stack+LOG_LEVEL=debug,stack的channels包含['single', 'stderr'],方便终端实时看 + 文件留存 - 生产环境建议:
LOG_CHANNEL=stack,但stack的channels改成['daily'],并设LOG_LEVEL=error减少 I/O 压力 -
'daily'通道可配'days' => 14控制保留天数,避免日志无限膨胀
Log::info() 和 Log::channel('xxx')->info() 有什么实际区别?
前者走默认通道(通常是 stack),后者强制指定通道,本质是路由分流,不是功能差异。
- 想隔离审计日志?先在
config/logging.php的channels里加一个'audit',driver设为'single',path指向storage_path('logs/audit.log') - 调用时写
Log::channel('audit')->info('user_id: '.$userId, ['action' => 'delete_post']),结构化数据会自动 JSON 化 - 注意:
audit通道不会继承stack的 Slack 处理器,要发告警得单独配slack驱动或复用已有 handler
怎么让 SQL 查询自动进日志?
别手动调 DB::enableQueryLog(),那只是临时调试手段;真正轻量又稳定的方案是配环境 + DB 配置。
- 确保
APP_DEBUG=true且LOG_LEVEL=debug,Laravel 会在 debug 级别自动记录慢查询和所有查询(只要没关log_queries) - 检查
config/database.php对应连接的配置,必须有'log_queries' => env('DB_LOG_QUERIES', false),并在.env中设DB_LOG_QUERIES=true - 这个机制依赖 Monolog 的处理器链,不是简单 echo,所以日志格式统一、上下文完整,比手捞
getQueryLog()更可靠
最易忽略的点:自定义 channel(比如 audit)的 level 是独立配置的,哪怕全局 LOG_LEVEL=debug,如果 'audit' => ['level' => 'info'],那 debug 级别日志照样不会进去。


















