diff --git a/README.md b/README.md index e58506b..0370bdd 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ sentry: - mySection priority_mapping: # optional, mapping of custom log levels to ones that's Sentry aware of mypriority: warning + ignore_exceptions: # optional, list of exception class names to ignore + - Tomaj\Hermes\Shutdown\ShutdownException + - App\MyCustomException db_tracing: true # optional, defaults to "false", wraps DB connection so it adds span for every query ``` @@ -48,7 +51,22 @@ Sentry only allows strict set of severities. By default any message with unknown You can map your custom *priority* to Sentry's *severity* in config by using `priority_mapping` as shown in the example. -The allowed set of Sentry severities can be checked in [Sentry's PHP repository](https://github.com/getsentry/sentry-php/blob/master/src/Severity.php). +The allowed set of Sentry severities can be checked in [Sentry's PHP repository](https://github.com/getsentry/sentry-php/blob/master/src/Severity.php). + +### Ignoring exceptions + +In some cases, you might want to prevent certain exceptions from being sent to Sentry while still logging them locally via Tracy. This is useful for expected exceptions like graceful shutdown signals or business logic exceptions that don't require monitoring. + +Use `ignore_exceptions` config option to specify exception class names that should be ignored: + +```neon +sentry: + ignore_exceptions: + - Tomaj\Hermes\Shutdown\ShutdownException + - App\MyCustomException +``` + +Ignored exceptions will still be logged to Tracy's local log files but won't be sent to Sentry. ## Usage diff --git a/src/DI/SentryExtension.php b/src/DI/SentryExtension.php index 63b718d..409aef5 100644 --- a/src/DI/SentryExtension.php +++ b/src/DI/SentryExtension.php @@ -39,20 +39,25 @@ public function loadConfiguration() $logger ->addSetup('setUserFields', [$this->config->user_fields]) ->addSetup('setSessionSections', [$this->config->session_sections]) - ->addSetup('setPriorityMapping', [$this->config->priority_mapping]); + ->addSetup('setPriorityMapping', [$this->config->priority_mapping]) + ->addSetup('setIgnoredExceptions', [$this->config->ignore_exceptions]); $integrations = []; if ($this->config->traces_sample_rate !== null) { $logger->addSetup('setTracesSampleRate', [$this->config->traces_sample_rate]); - $this->getContainerBuilder() + $builder = $this->getContainerBuilder(); + $builder ->addDefinition($this->prefix('applicationMonitor')) ->setFactory(ApplicationMonitor::class); - /** @var ServiceDefinition $application */ - $application = $this->getContainerBuilder()->getDefinition('application.application'); - $application->addSetup('@Rootpd\NetteSentry\ApplicationMonitor::hook', ['@self']); + // Only hook ApplicationMonitor if application service exists + if ($builder->hasDefinition('application.application')) { + /** @var ServiceDefinition $application */ + $application = $builder->getDefinition('application.application'); + $application->addSetup('@Rootpd\NetteSentry\ApplicationMonitor::hook', ['@self']); + } if ($this->config->profiles_sample_rate !== null) { $logger->addSetup('setProfilesSampleRate', [$this->config->profiles_sample_rate]); @@ -87,6 +92,7 @@ public function getConfigSchema(): Schema 'user_fields' => Expect::listOf(Expect::string())->default([]), 'session_sections' => Expect::listOf(Expect::string())->default([]), 'priority_mapping' => Expect::arrayOf(Expect::string(), Expect::string())->default([]), + 'ignore_exceptions' => Expect::listOf(Expect::string())->default([]), 'traces_sample_rate' => Expect::float()->dynamic(), 'profiles_sample_rate' => Expect::float()->dynamic(), diff --git a/src/SentryLogger.php b/src/SentryLogger.php index 34f0fe2..7dc4a76 100644 --- a/src/SentryLogger.php +++ b/src/SentryLogger.php @@ -30,6 +30,7 @@ class SentryLogger extends Logger private array $userFields = []; private array $sessionSections = []; private array $priorityMapping = []; + private array $ignoredExceptions = []; private ?float $tracesSampleRate = null; private ?float $profilesSampleRate = null; @@ -84,6 +85,11 @@ public function setPriorityMapping(array $priorityMapping) $this->priorityMapping = $priorityMapping; } + public function setIgnoredExceptions(array $ignoredExceptions) + { + $this->ignoredExceptions = $ignoredExceptions; + } + public function setTracesSampleRate(float $tracesSampleRate) { $this->tracesSampleRate = $tracesSampleRate; @@ -123,6 +129,16 @@ public function log($value, $priority = ILogger::INFO) return $response; } + // Check if exception should be ignored + if ($value instanceof Throwable) { + foreach ($this->ignoredExceptions as $ignoredException) { + if ($value instanceof $ignoredException) { + // Still log to Tracy, but skip sending to Sentry + return $response; + } + } + } + configureScope(function (Scope $scope) use ($severity) { if (!$severity) { return; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index aa80ed9..ec319c2 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -7,4 +7,5 @@ // Configure environment Environment::setupTester(); Environment::setupTimezone(); -Environment::setupVariables(__DIR__); +// Suppress deprecation warning from ninjify/nunjuck (uses deprecated lcg_value() in PHP 8.4+) +@Environment::setupVariables(__DIR__);