原因

之前公司项目从 5.2.* 升级到 5.8.*,因为代码中很多地方没有严格判断,例如直接获取数组中的值,导致跑出 Notice: Key 不存在。

然后我们在 App\Providers\AppServiceProvider 中设置了如下代码:

if ($this->app->environment() == 'production') {
    // 忽略 Notice 和 Warning
    error_reporting(E_ALL^E_NOTICE^E_WARNING);
}

测试以后发现,原来访问出错的页面,现在页不跑出一场了,本以为这样就完事了。但是后面的几天中还是会频繁的收到 Sentry 的通知邮件,都是关于数组中 Key 没有定义等类似的错误。

排查

于是乎我在本地开发环境,进行了代码的断点跟踪,最后发现原来 Sentry 的捕获机制导致的问题,当发生 Notice 和 Warning 的异常时,虽然 PHP 层忽略了,但是 Sentry 的扩展包依然可以捕获到,并发送到 Sentry。

经过一番研究 Sentry 的文旦,最后发现可以通过配置文件来制定要上报的错误类型:

return [
    'dsn' => env('SENTRY_DSN'),
    'server_name' => env('SERVER_NAME'),
    'environment' => env('APP_ENV'),
    'error_types' => E_ALL^E_NOTICE^E_WARNING,
    'attach_stacktrace' => true,

    // capture release as git sha
    // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')),

    // Capture bindings on SQL queries
    'breadcrumbs' => [
        // Capture Laravel logs in breadcrumbs
        'logs' => true,

        // Capture SQL queries in breadcrumbs
        'sql_queries' => true,

        // Capture bindings on SQL queries logged in breadcrumbs
        'sql_bindings' => true,

        // Capture queue job information in breadcrumbs
        'queue_info' => true,

        // Capture command information in breadcrumbs
        'command_info' => true,
    ],
];

上面的 error_types 就可以设置要忽略的异常类型,这样设置以后,就不会再将 Notice 和 Warning 的异常发送给 Sentry 了。

但是从代码的健壮性上来说,这种方式只是掩耳盗铃,不可取。但是在实际项目中不允许你大动业务逻辑,而且也没有那个时间来优化这些问题。

所以只能选择暂时性的忽略,等到以后有空了再去优化。

I hope this is helpful, Happy hacking…