问题排查

在注册ServerProvider时,Sentry/Laravel/ServiceProvider先于AliyunLogProvider注册,而Sentry/Laravel/ServiceProvider的 register方法中(见下图)调用了$this->app->make('log'),此时log组件提前被绑定为单例模式的框架默认logger,导致后续AliyunLogProvider进行注册时,调用$this-app->configureMonologUsing(...),设置自定义日志失效。

官方文档服务提供者 中有一句介绍:

所有服务提供者都需要继承 Illuminate\Support\ServiceProvider 类。大多数服务提供者都包含 register 和 boot 方法。在 register 方法中,您应该只能将事务绑定到 服务容器。不应该在 register 方法中尝试注册任何事件监听器,路由或者任何其他功能。

这里Sentry在register方法调用$this->app->make('log')是不太合法的一个行为。

我们先看一下框架中log组件如何实现服务容器,主要的几个方法:

如下图代码所示,在Laravel\Lumen\Application.php文件里的registerLogBindings方法,可以看到Psr\Log\LoggerInterface名称使用了singleton的单例绑定模式,如果存在$this->monologConfigurator则优先使用,否则使用默认的Logger。

大家可能会疑问,最开始make函数调用的名称不是log吗,跟Psr\Log\LoggerInterface什么关系?

在Laravel\Lumen\Application.php框架核心代码中,$this->aliases(见Line:804)有一些框架默认的别名映射关系,其中'log'-> 'Psr\Log\LoggerInterface'。在调用make函数的时候,会先调用$this->getAlias(...)获取这个关系映射。

解决方案

Sentry/Laravel/ServiceProvider的注册放于AliyunLogProvider之后。