更改来自供应商bundle的订户的优先级



设置一些上下文我正在研究Symfony 4.4 API,它使用名为EkinoNewRelicBundle的供应商将数据通信到New Relic API。该供应商使用名为RequestListener的订阅者订阅symmonfy的kernel.request事件,以定义发送到New Relic API的数据。

我有一个问题在特定情况下,当存在导致498的身份验证问题时,来自SecurityBundle的另一个订阅者抛出异常,停止请求处理。不幸的是,EkinoNewRelicBundle订阅者的一个名为setTransactionName的方法的优先级低于SecurityBundle订阅者,导致Ekino在进程停止时无法正确设置数据。

通过手工编辑供应商,我发现setTransactionName上的10优先级足以在SecurityBundle之前执行。

我正在寻找一种在运行时编辑RequestListener优先级的优先级的方法。到目前为止,我已经尝试了:

  • 覆盖但由于优先级是在类的公共静态方法中定义的,并且似乎是直接在EventDispatcher中加载的,因此没有配置可以重写;
  • 使用编译器传递来操作定义,但与上面一样,没有要编辑的定义,因为它似乎直接加载在EventDispatcher中;
  • 允许Ekino订阅者编辑优先级,禁用Ekino配置中的侦听器,但这会导致我新定义的订阅者的配置问题,因为它无法自动连接。

是否有一种简单的方法来更改供应商订阅者中订阅事件的优先级?

维护人员确实在七年前讨论过这个问题,当时配置仍然可以通过编译器传递到EkinoNewRelicBundle问题。

根据如何覆盖包的任何部分Symfony文档

如果你想修改由bundle创建的服务,你可以使用装饰服务。

由于EkinoNewRelicBundleListenerRequestListener是一个在配置中注册并由Symfony自动配置的服务,您可以创建一个装饰器并添加一个自定义getSubscribedEvents()方法来覆盖优先级。

创建装饰器

// /src/Decorator/EkinoRequestListenerDecorator.php
namespace AppDecorator;
use EkinoNewRelicBundleListenerKernelRequestEvent;
use EkinoNewRelicBundleListenerRequestListener;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentHttpKernelKernelEvents;
class EkinoRequestListenerDecorator implements EventSubscriberInterface
{
/** 
* @var RequestListener
*/
private $decorated;
public function __construct(RequestListener $decorated)
{
$this->decorated = $decorated;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => [
['setApplicationName', 255],
['setIgnoreTransaction', 31],
['setTransactionName', 10],
],
];
}
public function setApplicationName(KernelRequestEvent $event): void
{
$this->decorated->setApplicationName($event);
}
public function setIgnoreTransaction(KernelRequestEvent $event): void
{
$this->decorated->setIgnoreTransaction($event);
}
public function setTransactionName(KernelRequestEvent $event): void
{
$this->decorated->setTransactionName($event);
}
}

配置装饰器

decorates选项告诉容器AppDecoratorEkinoRequestListenerDecorator

此配置将EkinoNewRelicBundleListenerRequestListener替换为新的CC_15,但保留a引用旧的为AppDecoratorEkinoRequestListenerDecorator.inner

# /config/services.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true      # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# ...
AppDecoratorEkinoRequestListenerDecorator:
decorates: EkinoNewRelicBundleListenerRequestListener
arguments: ['@AppDecoratorEkinoRequestListenerDecorator.inner']

调试事件调度程序

php bin/console debug:event-dispatcher kernel.request

结果kernel.request事件调度程序

之前
Registered Listeners for "kernel.request" Event
===============================================
------- ------------------------------------------------------------------------------------------------------- ---------- 
Order   Callable                                                                                                Priority  
------- ------------------------------------------------------------------------------------------------------- ---------- 
#3      EkinoNewRelicBundleListenerRequestListener::setApplicationName()                                     255       
#8      EkinoNewRelicBundleListenerRequestListener::setIgnoreTransaction()                                   31            
#21     EkinoNewRelicBundleListenerRequestListener::setTransactionName()                                     -10       
------- ------------------------------------------------------------------------------------------------------- ---------- 

Registered Listeners for "kernel.request" Event
===============================================
------- ------------------------------------------------------------------------------------------------------- ---------- 
Order   Callable                                                                                                Priority  
------- ------------------------------------------------------------------------------------------------------- ----------     
#3      AppDecoratorEkinoRequestListenerDecorator::setApplicationName()                                       255       
#8      AppDecoratorEkinoRequestListenerDecorator::setIgnoreTransaction()                                     31
#13     AppDecoratorEkinoRequestListenerDecorator::setTransactionName()                                       10        
------- ------------------------------------------------------------------------------------------------------- ---------- 

结果容器事件监听器

$instance->addListener('kernel.request', [0 => function () {
return ($this->privates['App\Decorator\EkinoRequestListenerDecorator'] ?? $this->getEkinoRequestListenerDecoratorService());
}, 1 => 'setApplicationName'], 255);
$instance->addListener('kernel.request', [0 => function () {
return ($this->privates['App\Decorator\EkinoRequestListenerDecorator'] ?? $this->getEkinoRequestListenerDecoratorService());
}, 1 => 'setIgnoreTransaction'], 31);
$instance->addListener('kernel.request', [0 => function () {
return ($this->privates['App\Decorator\EkinoRequestListenerDecorator'] ?? $this->getEkinoRequestListenerDecoratorService());
}, 1 => 'setTransactionName'], 10);

//...
protected function getEkinoRequestListenerDecoratorService()
{
return $this->privates['App\Decorator\EkinoRequestListenerDecorator'] = new AppDecoratorEkinoRequestListenerDecorator(new EkinoNewRelicBundleListenerRequestListener(($this->privates['Ekino\NewRelicBundle\NewRelic\Config'] ?? $this->getConfigService()), ($this->privates['Ekino\NewRelicBundle\NewRelic\BlackholeInteractor'] ?? ($this->privates['Ekino\NewRelicBundle\NewRelic\BlackholeInteractor'] = new EkinoNewRelicBundleNewRelicBlackholeInteractor())), [], [], new EkinoNewRelicBundleTransactionNamingStrategyRouteNamingStrategy()));
}

相关内容

  • 没有找到相关文章

最新更新