From 9a241417f92b1887fc70b80b39b0853037a7f385 Mon Sep 17 00:00:00 2001 From: Matthias Vogel Date: Fri, 11 Aug 2023 16:39:29 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20configurable=20options=20for?= =?UTF-8?q?=20sentry=20tracing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes/Service/ConfigService.php | 30 +++++++++++++++++++ .../SentryService.php} | 20 +++++++------ Classes/Utility/GuzzleUtility.php | 4 +-- Classes/Utility/TimingUtility.php | 14 ++++++--- Configuration/Services.yaml | 5 ++-- Tests/TimingUtilityTest.php | 2 ++ ext_conf_template.txt | 8 +++++ 7 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 Classes/Service/ConfigService.php rename Classes/{Utility/SentryUtility.php => Service/SentryService.php} (87%) create mode 100644 ext_conf_template.txt diff --git a/Classes/Service/ConfigService.php b/Classes/Service/ConfigService.php new file mode 100644 index 0000000..f1c5b49 --- /dev/null +++ b/Classes/Service/ConfigService.php @@ -0,0 +1,30 @@ +getConfig('stop_watch_limit') ?? 100_000); + } + + public function tracesSampleRate(): ?float + { + $tracesSampleRate = $this->getConfig('sentry_sample_rate'); + return $tracesSampleRate === null ? null : (float)$tracesSampleRate; + } + + public function enableTracing(): ?bool + { + $tracesSampleRate = $this->tracesSampleRate(); + return $tracesSampleRate === null ? null : (bool)$tracesSampleRate; + } + + private function getConfig(string $path): ?string + { + return $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['server_timing'][$path] ?? null; + } +} diff --git a/Classes/Utility/SentryUtility.php b/Classes/Service/SentryService.php similarity index 87% rename from Classes/Utility/SentryUtility.php rename to Classes/Service/SentryService.php index 5c112b9..959ef31 100644 --- a/Classes/Utility/SentryUtility.php +++ b/Classes/Service/SentryService.php @@ -2,21 +2,24 @@ declare(strict_types=1); -namespace Kanti\ServerTiming\Utility; +namespace Kanti\ServerTiming\Service; use Kanti\ServerTiming\Dto\ScriptResult; use Kanti\ServerTiming\Dto\StopWatch; use Pluswerk\Sentry\Service\Sentry; use Psr\Http\Message\ServerRequestInterface; -use Sentry\ClientBuilder; use Sentry\SentrySdk; use Sentry\Tracing\Span; use Sentry\Tracing\SpanContext; use Sentry\Tracing\SpanStatus; use Sentry\Tracing\TransactionContext; -final class SentryUtility +final class SentryService { + public function __construct(private readonly ConfigService $configService) + { + } + /** * @param StopWatch[] $stopWatches */ @@ -38,12 +41,8 @@ public function sendSentryTrace(ScriptResult $result, array $stopWatches): void $options = $client->getOptions(); - $options->setProfilesSampleRate(1.0); // TODO do not hard code!!! - $options->setTracesSampleRate(1.0); // TODO do not hard code!!! - $options->setEnableTracing(true); // TODO do not hard code!!! - - $client = (new ClientBuilder($options))->getClient(); - $hub->bindClient($client); + $options->setTracesSampleRate($this->configService->tracesSampleRate() ?? $options->getTracesSampleRate()); + $options->setEnableTracing($this->configService->enableTracing() ?? $options->getEnableTracing()); $transactionContext = new TransactionContext(); if ($result->isCli()) { @@ -77,7 +76,10 @@ public function sendSentryTrace(ScriptResult $result, array $stopWatches): void $hub->setSpan($transaction); + $should = $options->shouldAttachStacktrace(); + $options->setAttachStacktrace(false); $transaction->finish($stopWatches[0]->stopTime); + $options->setAttachStacktrace($should); } private function setContextFromRequest(TransactionContext $transactionContext, ScriptResult $result): void diff --git a/Classes/Utility/GuzzleUtility.php b/Classes/Utility/GuzzleUtility.php index ab28545..fcc9750 100644 --- a/Classes/Utility/GuzzleUtility.php +++ b/Classes/Utility/GuzzleUtility.php @@ -13,8 +13,8 @@ final class GuzzleUtility { public static function getHandler(): ?Closure { - if (ServerRequestFactory::fromGlobals()->getUri()->getPath() === '/typo3/module/system/config') { - // fix bug in Configuration module + if (str_starts_with($_SERVER['REQUEST_URI'] ?? '', '/typo3/module/system/config')) { + // fix bug in Configuration Backend module return null; } diff --git a/Classes/Utility/TimingUtility.php b/Classes/Utility/TimingUtility.php index d6f2583..2f46fd1 100644 --- a/Classes/Utility/TimingUtility.php +++ b/Classes/Utility/TimingUtility.php @@ -8,6 +8,8 @@ use Exception; use Kanti\ServerTiming\Dto\ScriptResult; use Kanti\ServerTiming\Dto\StopWatch; +use Kanti\ServerTiming\Service\SentryService; +use Kanti\ServerTiming\Service\ConfigService; use Psr\Http\Message\ResponseInterface; use SplObjectStorage; use TYPO3\CMS\Core\Context\Context; @@ -27,9 +29,12 @@ final class TimingUtility private readonly Closure $registerShutdownFunction; - public function __construct(Closure $registerShutdownFunction = null) + private readonly ConfigService $configService; + + public function __construct(Closure $registerShutdownFunction = null, ConfigService $configService = null) { $this->registerShutdownFunction = $registerShutdownFunction ?? register_shutdown_function(...); + $this->configService = $configService ?? new ConfigService(); } public static function getInstance(Closure $registerShutdownFunction = null): TimingUtility @@ -105,8 +110,9 @@ public function stopWatchInternal(string $key, string $info = ''): StopWatch $this->order[] = $phpStopWatch; } - // TODO limit to x watches - $this->order[] = $stopWatch; + if (count($this->order) < $this->configService->stopWatchLimit()) { + $this->order[] = $stopWatch; + } if (!$this->registered) { $x = $this->registerShutdownFunction; @@ -131,7 +137,7 @@ public function shutdown(ScriptResult $result): ?ResponseInterface $stopWatch->stopIfNot(); } - GeneralUtility::makeInstance(SentryUtility::class)->sendSentryTrace($result, $this->order); + GeneralUtility::makeInstance(SentryService::class)->sendSentryTrace($result, $this->order); if (!$this->shouldAddHeader()) { return $result->response; diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 58895c0..f7914d6 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -2,11 +2,12 @@ services: _defaults: autowire: true autoconfigure: true - public: false + public: true Kanti\ServerTiming\: resource: '../Classes/*' - exclude: '../Classes/SqlLogging/*' + # SqlLogging can be removed from exclude if only TYPO3 12 and above are required + exclude: '../Classes/{Dto,SqlLogging}/*' Kanti\ServerTiming\EventListener\ConsoleCommandEventListener: tags: diff --git a/Tests/TimingUtilityTest.php b/Tests/TimingUtilityTest.php index 463601f..03b918b 100644 --- a/Tests/TimingUtilityTest.php +++ b/Tests/TimingUtilityTest.php @@ -5,6 +5,7 @@ namespace Kanti\ServerTiming\Tests; use Generator; +use Kanti\ServerTiming\Service\ConfigService; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; @@ -15,6 +16,7 @@ #[CoversClass(TimingUtility::class)] #[CoversClass(StopWatch::class)] +#[CoversClass(ConfigService::class)] final class TimingUtilityTest extends TestCase { protected function setUp(): void diff --git a/ext_conf_template.txt b/ext_conf_template.txt new file mode 100644 index 0000000..31d4735 --- /dev/null +++ b/ext_conf_template.txt @@ -0,0 +1,8 @@ +# cat=sentry; type=integer; label=StopWatch Limit +stop_watch_limit = 100000 + +# cat=sentry; type=string; label=Sentry Sample Rate between 0.0 and 1.0 (empty: keep default) +sentry_sample_rate = + +# cat=sentry; type=string; label=Sentry CLI Sample Rate between 0.0 and 1.0 (empty: keep default) +sentry_cli_sample_rate =