From 90812badcdb3125ec145de1de308f85afd372feb Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Mon, 2 Jun 2025 15:23:00 +0200 Subject: [PATCH] feat: improve shopware exception ignoring --- src/Integration/FilterExceptionEvent.php | 36 ++++++++++++++++ .../UseShopwareExceptionIgnores.php | 29 +++++-------- src/Resources/config/packages/sentry.yaml | 8 ++++ src/ShopwareSentryBundle.php | 31 +++++++++++++- ...lterShopwareExceptionIgnoresSubscriber.php | 41 +++++++++++++++++++ 5 files changed, 125 insertions(+), 20 deletions(-) create mode 100644 src/Integration/FilterExceptionEvent.php create mode 100644 src/Resources/config/packages/sentry.yaml create mode 100644 src/Subscriber/FilterShopwareExceptionIgnoresSubscriber.php diff --git a/src/Integration/FilterExceptionEvent.php b/src/Integration/FilterExceptionEvent.php new file mode 100644 index 0000000..1ede160 --- /dev/null +++ b/src/Integration/FilterExceptionEvent.php @@ -0,0 +1,36 @@ +exceptions; + } + + /** + * @param ExceptionDataBag[] $exceptions + */ + public function setExceptions(array $exceptions): void + { + $this->exceptions = $exceptions; + } + + + +} diff --git a/src/Integration/UseShopwareExceptionIgnores.php b/src/Integration/UseShopwareExceptionIgnores.php index 001a477..b0b479c 100644 --- a/src/Integration/UseShopwareExceptionIgnores.php +++ b/src/Integration/UseShopwareExceptionIgnores.php @@ -5,34 +5,25 @@ use Sentry\Event; use Sentry\Integration\IntegrationInterface; use Sentry\State\Scope; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class UseShopwareExceptionIgnores implements IntegrationInterface { - /** - * @param array $exceptions - */ - public function __construct(private readonly array $exceptions) {} + public function __construct(private readonly EventDispatcherInterface $eventDispatcher) + { + } public function setupOnce(): void { - $exceptions = $this->exceptions; - - Scope::addGlobalEventProcessor(function (Event $event) use ($exceptions): ?Event { - $eventExceptions = $event->getExceptions()[0] ?? null; + $eventDispatcher = $this->eventDispatcher; - if ($eventExceptions === null) { + Scope::addGlobalEventProcessor(static function (Event $event) use ($eventDispatcher): ?Event { + $exceptions = $event->getExceptions(); + if (empty($exceptions)) { return $event; } - - $config = $exceptions[$eventExceptions->getType()] ?? []; - - if (!isset($config['log_level'])) { - return $event; - } - - if ($config['log_level'] === 'notice') { - return null; - } + $exceptions = $eventDispatcher->dispatch(new FilterExceptionEvent($exceptions))->getExceptions(); + $event->setExceptions($exceptions); return $event; }); diff --git a/src/Resources/config/packages/sentry.yaml b/src/Resources/config/packages/sentry.yaml new file mode 100644 index 0000000..be1afe3 --- /dev/null +++ b/src/Resources/config/packages/sentry.yaml @@ -0,0 +1,8 @@ +sentry: + options: + ignore_exceptions: + - 'Shopware\Storefront\Framework\Routing\Exception\SalesChannelMappingException' + - 'Shopware\Core\Framework\Api\Controller\Exception\AuthThrottledException' + - 'Shopware\Core\Framework\RateLimiter\Exception\RateLimitExceededException' + - 'Symfony\Component\Console\Exception\CommandNotFoundException' + - 'League\OAuth2\Server\Exception\OAuthServerException' diff --git a/src/ShopwareSentryBundle.php b/src/ShopwareSentryBundle.php index 18cc3b4..d7870f4 100644 --- a/src/ShopwareSentryBundle.php +++ b/src/ShopwareSentryBundle.php @@ -7,11 +7,18 @@ use Frosh\SentryBundle\Integration\UseShopwareExceptionIgnores; use Frosh\SentryBundle\Listener\FixRequestUrlListener; use Frosh\SentryBundle\Listener\SalesChannelContextListener; +use Frosh\SentryBundle\Subscriber\FilterShopwareExceptionIgnoresSubscriber; use Frosh\SentryBundle\Subscriber\FlowLogSubscriber; use Frosh\SentryBundle\Subscriber\ScheduledTaskSubscriber; use Shopware\Core\System\SalesChannel\Event\SalesChannelContextCreatedEvent; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Loader\DelegatingLoader; +use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; +use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Event\RequestEvent; @@ -21,6 +28,8 @@ class ShopwareSentryBundle extends Bundle { public function build(ContainerBuilder $container): void { + $this->loadConfiguration($container); + $container ->register(SalesChannelContextListener::class) ->addTag('kernel.event_listener', ['event' => SalesChannelContextCreatedEvent::class, 'method' => '__invoke']) @@ -37,7 +46,7 @@ public function build(ContainerBuilder $container): void $container ->register(UseShopwareExceptionIgnores::class) - ->addArgument('%frosh_sentry.exclude_exceptions%'); + ->addArgument(new Reference('event_dispatcher')); $container ->register(ScheduledTaskSubscriber::class) @@ -45,6 +54,11 @@ public function build(ContainerBuilder $container): void ->addArgument('%frosh_sentry.report_scheduled_tasks%') ->addTag('kernel.event_subscriber'); + $container + ->register(FilterShopwareExceptionIgnoresSubscriber::class) + ->addArgument('%frosh_sentry.exclude_exceptions%') + ->addTag('kernel.event_subscriber'); + $container ->register(FlowLogSubscriber::class) ->addTag('kernel.event_subscriber'); @@ -56,4 +70,19 @@ public function getContainerExtension(): ExtensionInterface { return new FroshSentryExtension(); } + + private function loadConfiguration(ContainerBuilder $container): void + { + $locator = new FileLocator('Resources/config'); + $resolver = new LoaderResolver([ + new YamlFileLoader($container, $locator), + new GlobFileLoader($container, $locator), + new DirectoryLoader($container, $locator), + ]); + + $configLoader = new DelegatingLoader($resolver); + $confDir = \rtrim($this->getPath(), '/') . '/Resources/config'; + $configLoader->load($confDir . '/{packages}/*.yaml', 'glob'); + + } } diff --git a/src/Subscriber/FilterShopwareExceptionIgnoresSubscriber.php b/src/Subscriber/FilterShopwareExceptionIgnoresSubscriber.php new file mode 100644 index 0000000..10aaaca --- /dev/null +++ b/src/Subscriber/FilterShopwareExceptionIgnoresSubscriber.php @@ -0,0 +1,41 @@ + 'filterSentryExceptions', + ]; + } + + + public function filterSentryExceptions(FilterExceptionEvent $event): void + { + $filteredExceptions = []; + foreach ($event->getExceptions() as $exception) { + + $exceptionLogLevel = $this->shopwareExceptionConfig[$exception->getType()]['log_level'] ?? null; + + if ($exceptionLogLevel === 'notice') { + continue; + } + + $filteredExceptions[] = $exception; + } + + $event->setExceptions($filteredExceptions); + + + } +}