From 165454d81ae2cda4e05cce39dda820b8d4c94312 Mon Sep 17 00:00:00 2001 From: Felix Gradinaru Date: Sat, 15 Aug 2026 18:15:11 +0200 Subject: [PATCH] feat: add sdkOptions passthrough for Sentry SDK client options Flownative.Sentry.sdkOptions lets projects configure any YAML-representable Sentry SDK option (e.g. max_request_body_size, send_default_pii) without a package change. Options set explicitly by this package always win; the before_send* callbacks, ignore_exceptions and integrations are reserved and rejected at boot with the offending settings path; in_app_exclude entries are merged with the package defaults. --- .../InvalidConfigurationException.php | 18 +++++ Classes/SentryClient.php | 69 ++++++++++++++++--- Configuration/Settings.yaml | 8 +++ 3 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 Classes/Exception/InvalidConfigurationException.php diff --git a/Classes/Exception/InvalidConfigurationException.php b/Classes/Exception/InvalidConfigurationException.php new file mode 100644 index 0000000..c4b8ae3 --- /dev/null +++ b/Classes/Exception/InvalidConfigurationException.php @@ -0,0 +1,18 @@ +excludeExceptionMessagePatterns = $settings['capture']['excludeExceptionMessagePatterns'] ?? []; $this->excludeExceptionCodes = $settings['capture']['excludeExceptionCodes'] ?? []; $this->errorLevel = $settings['errorLevel'] ?? error_reporting(); + $this->sdkOptions = $this->validateSdkOptions($settings['sdkOptions'] ?? []); + } + + /** + * @throws InvalidConfigurationException + */ + private function validateSdkOptions(mixed $sdkOptions): array + { + if (!is_array($sdkOptions)) { + throw new InvalidConfigurationException( + 'Flownative.Sentry.sdkOptions must be an array of Sentry SDK options', + 1755264001 + ); + } + foreach (self::RESERVED_SDK_OPTIONS as $reservedOption) { + if (array_key_exists($reservedOption, $sdkOptions)) { + throw new InvalidConfigurationException( + sprintf( + 'The Sentry SDK option "%s" cannot be set via Flownative.Sentry.sdkOptions.%s because it is managed by this package', + $reservedOption, + $reservedOption + ), + 1755264002 + ); + } + } + return $sdkOptions; } public function initializeObject(): void @@ -126,20 +171,26 @@ public function initializeObject(): void $representationSerializer ); - \Sentry\init([ + $inAppExclude = [ + FLOW_PATH_ROOT . '/Packages/Application/Flownative.Sentry/Classes/', + FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Aop/', + FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Error/', + FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Log/', + FLOW_PATH_ROOT . '/Packages/Libraries/neos/flow-log/' + ]; + if (isset($this->sdkOptions['in_app_exclude'])) { + $inAppExclude = array_values(array_unique(array_merge($inAppExclude, (array)$this->sdkOptions['in_app_exclude']))); + } + + // Options set explicitly by this package always win over sdkOptions + \Sentry\init(array_replace($this->sdkOptions, [ 'dsn' => $this->dsn, 'environment' => $this->environment, 'release' => $this->release, 'sample_rate' => $this->sampleRate, 'traces_sample_rate' => $this->tracesSampleRate, 'ignore_exceptions' => array_keys(array_filter($this->excludeExceptionTypes)), - 'in_app_exclude' => [ - FLOW_PATH_ROOT . '/Packages/Application/Flownative.Sentry/Classes/', - FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Aop/', - FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Error/', - FLOW_PATH_ROOT . '/Packages/Framework/Neos.Flow/Classes/Log/', - FLOW_PATH_ROOT . '/Packages/Libraries/neos/flow-log/' - ], + 'in_app_exclude' => $inAppExclude, 'attach_stacktrace' => true, 'error_types' => $this->errorLevel, 'before_send' => function (Event $event, ?EventHint $hint): ?Event { @@ -150,7 +201,7 @@ public function initializeObject(): void return $event; } - ]); + ])); $client = SentrySdk::getCurrentHub()->getClient(); if (!$client) { diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index b8ba3d8..8718a7f 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -6,6 +6,14 @@ Flownative: sampleRate: 1.0 tracesSampleRate: 0 errorLevel: null + + # Additional Sentry SDK client options passed to \Sentry\init(). Options set + # explicitly by this package (dsn, environment, release, sample rates, error + # level, exception excludes) always take precedence. The before_send* + # callbacks, ignore_exceptions and integrations cannot be set here. + # in_app_exclude entries are merged with the package defaults. + sdkOptions: {} + capture: excludeExceptionTypes: 'Neos\Flow\Mvc\Controller\Exception\InvalidControllerException': true