You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel应用异常输出多日志通道问题排查问询

Laravel 10.13.5 日志异常问题

我负责的Laravel 10.13.5应用出现异常:同一条日志语句同时输出带有local和production环境标识的日志,日志示例如下:

[2024-02-21 13:05:47] local.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  
[2024-02-21 13:05:47] local.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  
[2024-02-21 13:05:47] local.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  
[2024-02-21 13:05:47] local.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  
[2024-02-21 13:05:47] production.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  
[2024-02-21 13:05:47] production.INFO: UserDao.getByMatricule C182697 on 10.48.86.7  

日志调用代码:

Log::info('UserDao.getByMatricule ' . $matricule . ' on ' . $ip);

可以看到日志的环境标识在记录过程中从local切换到production,但config/logging.php中并没有配置名为local或production的日志通道。

应用.env配置:

APP_NAME=Laravel  
APP_ENV=local  
APP_DEBUG=false  
APP_URL=http://localhost  
LOG_CHANNEL=stack  
LOG_DEPRECATIONS_CHANNEL=null  
LOG_LEVEL=debug  

额外信息

  • 存在生产和测试两台服务器,代码完全一致,仅数据库凭据不同;.env其余配置(含APP_ENV、APP_KEY)完全相同
  • config/app.php和config/logging.php在两台服务器上一致,其中config/app.php里的配置为'env' => env('APP_ENV', 'production')
  • 应用已上线多年,该问题仅偶尔出现(55.7万行日志中仅出现70次)
  • 两台服务器均位于反向代理后
  • 用户反馈看到无权限内容,怀疑存在环境不匹配问题

问题

  1. 当前配置下,Laravel为何会输出带有两种不同环境标识的日志?
  2. 这些local和production标识是如何产生的?

附config/logging.php配置:

<?php

use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
use Monolog\Processor\PsrLogMessageProcessor;

return [

    /*
    |--------------------------------------------------------------------------
    | 默认日志通道
    |--------------------------------------------------------------------------
    |
    | 该选项定义写入日志时使用的默认日志通道,此处指定的名称必须与
    | 下方"channels"配置数组中定义的通道名称匹配。
    |
    */

    'default' => env('LOG_CHANNEL', 'stack'),

    /*
    |--------------------------------------------------------------------------
    | 弃用日志通道
    |--------------------------------------------------------------------------
    |
    | 该选项控制用于记录PHP和库特性弃用警告的日志通道,帮助你
    | 为依赖项的即将到来的大版本更新做好准备。
    |
    */

    'deprecations' => [
        'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
        'trace' => false,
    ],

    /*
    |--------------------------------------------------------------------------
    | 日志通道
    |--------------------------------------------------------------------------
    |
    | 你可以在此配置应用的日志通道。Laravel默认使用Monolog PHP日志库,
    | 这让你可以使用各种强大的日志处理器/格式化器。
    |
    | 可用驱动:"single", "daily", "slack", "syslog",
    |          "errorlog", "monolog",
    |          "custom", "stack"
    |
    */

    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single'],
            'ignore_exceptions' => false,
        ],

        'single' => [
            'driver' => 'single',
            'path' => storage_path('logs/laravel.log'),
            'level' => env('LOG_LEVEL', 'debug'),
            'replace_placeholders' => true,
        ],

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => env('LOG_LEVEL', 'debug'),
            'days' => 14,
            'replace_placeholders' => true,
        ],

        'slack' => [
            'driver' => 'slack',
            'url' => env('LOG_SLACK_WEBHOOK_URL'),
            'username' => 'Laravel Log',
            'emoji' => ':boom:',
            'level' => env('LOG_LEVEL', 'critical'),
            'replace_placeholders' => true,
        ],

        'papertrail' => [
            'driver' => 'monolog',
            'level' => env('LOG_LEVEL', 'debug'),
            'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
            'handler_with' => [
                'host' => env('PAPERTRAIL_URL'),
                'port' => env('PAPERTRAIL_PORT'),
                'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
            ],
            'processors' => [PsrLogMessageProcessor::class],
        ],

        'stderr' => [
            'driver' => 'monolog',
            'level' => env('LOG_LEVEL', 'debug'),
            'handler' => StreamHandler::class,
            'formatter' => env('LOG_STDERR_FORMATTER'),
            'with' => [
                'stream' => 'php://stderr',
            ],
            'processors' => [PsrLogMessageProcessor::class],
        ],

        'syslog' => [
            'driver' => 'syslog',
            'level' => env('LOG_LEVEL', 'debug'),
            'facility' => LOG_USER,
            'replace_placeholders' => true,
        ],

        'errorlog' => [
            'driver' => 'errorlog',
            'level' => env('LOG_LEVEL', 'debug'),
            'replace_placeholders' => true,
        ],

        'null' => [
            'driver' => 'monolog',
            'handler' => NullHandler::class,
        ],

        'emergency' => [
            'path' => storage_path('logs/laravel.log'),
        ],
    ],

];

解答

问题1:为何会输出带有两种不同环境标识的日志?

这种异常大概率是PHP-FPM(或其他进程管理器)的进程环境变量污染导致的:

  • 两台服务器的.env中APP_ENV都是local,但如果进程管理器的子进程在重启、回收时没有正确清除环境变量,可能会有个别子进程继承了旧的(甚至是跨服务器的)APP_ENV=production环境变量。
  • 当请求被分配到这个异常进程时,Laravel会基于错误的APP_ENV值初始化日志组件,导致日志标记为production;正常进程则使用正确的local环境,从而出现同一批次请求同时输出两种环境标识日志的情况。
  • 反向代理/负载均衡配置错误导致同一请求被转发到两台服务器,也可能出现日志混合,但结合“仅偶尔出现”的特征,进程环境变量污染的可能性更高。

问题2:这些local和production标识是如何产生的?

你看到的local/production并不是日志通道名称,而是Laravel默认日志格式化器自动添加的环境标识:

  • Laravel的默认日志格式会将APP_ENV的值作为日志前缀的一部分(比如local.INFO里的local就是当前进程的APP_ENV值)。
  • 你的config/logging.php中实际使用的是stack→single通道,只是因为个别进程的APP_ENV被污染为production,导致日志前缀显示了错误的环境标识,看起来像是输出到了不同通道。

内容的提问来源于stack exchange,提问作者madgangmixers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 13:35:03