From 7a2c73636a3f03c93a07a35a7d7fce91940cf557 Mon Sep 17 00:00:00 2001 From: Martin Linzmayer Date: Mon, 1 Dec 2025 14:54:56 +0100 Subject: [PATCH 1/3] feat(metrics): add metrics for symfony --- composer.json | 2 +- src/EventListener/ConsoleListener.php | 10 ++-- src/EventListener/MetricsRequestListener.php | 24 ++++++++ src/Resources/config/services.yaml | 4 ++ tests/End2End/App/Command/MetricsCommand.php | 22 ++++++++ .../App/Controller/MetricsController.php | 20 +++++++ tests/End2End/App/KernelWithMetrics.php | 17 ++++++ tests/End2End/App/metrics.yml | 9 +++ tests/End2End/App/routing.yml | 4 ++ tests/End2End/MetricsCommandTest.php | 56 +++++++++++++++++++ tests/End2End/MetricsEnd2EndTest.php | 46 +++++++++++++++ 11 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 src/EventListener/MetricsRequestListener.php create mode 100644 tests/End2End/App/Command/MetricsCommand.php create mode 100644 tests/End2End/App/Controller/MetricsController.php create mode 100644 tests/End2End/App/KernelWithMetrics.php create mode 100644 tests/End2End/App/metrics.yml create mode 100644 tests/End2End/MetricsCommandTest.php create mode 100644 tests/End2End/MetricsEnd2EndTest.php diff --git a/composer.json b/composer.json index b092c8ca..50dc4781 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "php": "^7.2||^8.0", "guzzlehttp/psr7": "^2.1.1", "jean85/pretty-package-versions": "^1.5||^2.0", - "sentry/sentry": "^4.18", + "sentry/sentry": "^4.19", "symfony/cache-contracts": "^1.1||^2.4||^3.0", "symfony/config": "^4.4.20||^5.0.11||^6.0||^7.0||^8.0", "symfony/console": "^4.4.20||^5.0.11||^6.0||^7.0||^8.0", diff --git a/src/EventListener/ConsoleListener.php b/src/EventListener/ConsoleListener.php index 2ef88afa..6d2d28c0 100644 --- a/src/EventListener/ConsoleListener.php +++ b/src/EventListener/ConsoleListener.php @@ -8,6 +8,7 @@ use Sentry\EventHint; use Sentry\ExceptionMechanism; use Sentry\Logs\Logs; +use Sentry\Metrics\TraceMetrics; use Sentry\State\HubInterface; use Sentry\State\Scope; use Symfony\Component\Console\Event\ConsoleCommandEvent; @@ -36,8 +37,8 @@ class ConsoleListener /** * Constructor. * - * @param HubInterface $hub The current hub - * @param bool $captureErrors Whether to capture console errors + * @param HubInterface $hub The current hub + * @param bool $captureErrors Whether to capture console errors */ public function __construct(HubInterface $hub, bool $captureErrors = true) { @@ -61,7 +62,7 @@ public function handleConsoleCommandEvent(ConsoleCommandEvent $event): void } if ($input instanceof ArgvInput) { - $scope->setExtra('Full command', (string) $input); + $scope->setExtra('Full command', (string)$input); } } @@ -73,6 +74,7 @@ public function handleConsoleCommandEvent(ConsoleCommandEvent $event): void public function handleConsoleTerminateEvent(ConsoleTerminateEvent $event): void { Logs::getInstance()->flush(); + TraceMetrics::getInstance()->flush(); $this->hub->popScope(); } @@ -84,7 +86,7 @@ public function handleConsoleTerminateEvent(ConsoleTerminateEvent $event): void public function handleConsoleErrorEvent(ConsoleErrorEvent $event): void { $this->hub->configureScope(function (Scope $scope) use ($event): void { - $scope->setTag('console.command.exit_code', (string) $event->getExitCode()); + $scope->setTag('console.command.exit_code', (string)$event->getExitCode()); if ($this->captureErrors) { $hint = EventHint::fromArray([ diff --git a/src/EventListener/MetricsRequestListener.php b/src/EventListener/MetricsRequestListener.php new file mode 100644 index 00000000..1b9252dd --- /dev/null +++ b/src/EventListener/MetricsRequestListener.php @@ -0,0 +1,24 @@ +flush(); + } +} diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index c4aba752..d06cf86c 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -78,6 +78,10 @@ services: tags: - { name: kernel.event_listener, event: kernel.terminate, method: handleKernelTerminateEvent, priority: 10 } + Sentry\SentryBundle\EventListener\MetricsRequestListener: + tags: + - { name: kernel.event_listener, event: kernel.terminate, method: handleKernelTerminateEvent, priority: 10 } + # Command Sentry\SentryBundle\Command\SentryTestCommand: arguments: ['@Sentry\State\HubInterface'] diff --git a/tests/End2End/App/Command/MetricsCommand.php b/tests/End2End/App/Command/MetricsCommand.php new file mode 100644 index 00000000..a4814cd1 --- /dev/null +++ b/tests/End2End/App/Command/MetricsCommand.php @@ -0,0 +1,22 @@ +count('test-counter', 10); + trace_metrics()->gauge('test-gauge', 20.51); + trace_metrics()->distribution('test-distribution', 100.81); + + return 0; + } + +} diff --git a/tests/End2End/App/Controller/MetricsController.php b/tests/End2End/App/Controller/MetricsController.php new file mode 100644 index 00000000..a431f05b --- /dev/null +++ b/tests/End2End/App/Controller/MetricsController.php @@ -0,0 +1,20 @@ +count('test-counter', 10); + trace_metrics()->gauge('test-gauge', 20.51); + trace_metrics()->distribution('test-distribution', 100.81); + + return new Response(); + } + +} diff --git a/tests/End2End/App/KernelWithMetrics.php b/tests/End2End/App/KernelWithMetrics.php new file mode 100644 index 00000000..84a3d5f1 --- /dev/null +++ b/tests/End2End/App/KernelWithMetrics.php @@ -0,0 +1,17 @@ +load(__DIR__ . '/metrics.yml'); + } +} diff --git a/tests/End2End/App/metrics.yml b/tests/End2End/App/metrics.yml new file mode 100644 index 00000000..f80092b5 --- /dev/null +++ b/tests/End2End/App/metrics.yml @@ -0,0 +1,9 @@ +services: + Sentry\SentryBundle\Tests\End2End\App\Controller\MetricsController: + autowire: true + tags: + - { name: controller.service_arguments } + + Sentry\SentryBundle\Tests\End2End\App\Command\MetricsCommand: + autowire: true + tags: [ { name: 'console.command', command: 'metrics:test' } ] diff --git a/tests/End2End/App/routing.yml b/tests/End2End/App/routing.yml index b7b1f6d6..caaa9f5d 100644 --- a/tests/End2End/App/routing.yml +++ b/tests/End2End/App/routing.yml @@ -85,3 +85,7 @@ logging_before_send_logs: buffer_flush: path: /buffer-flush defaults: { _controller: 'Sentry\SentryBundle\Tests\End2End\App\Controller\BufferFlushController::testBufferFlush' } + +metrics: + path: /metrics + defaults: { _controller: 'Sentry\SentryBundle\Tests\End2End\App\Controller\MetricsController::metrics'} diff --git a/tests/End2End/MetricsCommandTest.php b/tests/End2End/MetricsCommandTest.php new file mode 100644 index 00000000..618f9164 --- /dev/null +++ b/tests/End2End/MetricsCommandTest.php @@ -0,0 +1,56 @@ +application = new Application(self::bootKernel()); + } + + public function testMetricsInCommand(): void + { + $this->application->doRun(new ArgvInput(['bin/console', 'metrics:test']), new NullOutput()); + + $this->assertCount(1, StubTransport::$events); + $metrics = StubTransport::$events[0]->getMetrics(); + + $this->assertCount(3, $metrics); + + $count = $metrics[0]; + $this->assertSame('test-counter', $count->getName()); + $this->assertSame(10.0, $count->getValue()); + + $gauge = $metrics[1]; + $this->assertSame('test-gauge', $gauge->getName()); + $this->assertSame(20.51, $gauge->getValue()); + + $distribution = $metrics[2]; + $this->assertSame('test-distribution', $distribution->getName()); + $this->assertSame(100.81, $distribution->getValue()); + } +} diff --git a/tests/End2End/MetricsEnd2EndTest.php b/tests/End2End/MetricsEnd2EndTest.php new file mode 100644 index 00000000..bbc72643 --- /dev/null +++ b/tests/End2End/MetricsEnd2EndTest.php @@ -0,0 +1,46 @@ + true]); + + $client->request('GET', '/metrics'); + $this->assertSame(200, $client->getResponse()->getStatusCode()); + + $this->assertCount(1, StubTransport::$events); + $metrics = StubTransport::$events[0]->getMetrics(); + $this->assertCount(3, $metrics); + + $count = $metrics[0]; + $this->assertSame('test-counter', $count->getName()); + $this->assertSame(10.0, $count->getValue()); + + $gauge = $metrics[1]; + $this->assertSame('test-gauge', $gauge->getName()); + $this->assertSame(20.51, $gauge->getValue()); + + $distribution = $metrics[2]; + $this->assertSame('test-distribution', $distribution->getName()); + $this->assertSame(100.81, $distribution->getValue()); + } +} From 454dd867520981958434403cba791a7776066af5 Mon Sep 17 00:00:00 2001 From: Martin Linzmayer Date: Mon, 1 Dec 2025 14:56:55 +0100 Subject: [PATCH 2/3] CS + Lint --- src/EventListener/ConsoleListener.php | 8 ++++---- src/EventListener/MetricsRequestListener.php | 2 ++ tests/End2End/App/Command/MetricsCommand.php | 5 +++-- tests/End2End/App/Controller/MetricsController.php | 5 +++-- tests/End2End/MetricsEnd2EndTest.php | 4 +++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/EventListener/ConsoleListener.php b/src/EventListener/ConsoleListener.php index 6d2d28c0..4ec7a523 100644 --- a/src/EventListener/ConsoleListener.php +++ b/src/EventListener/ConsoleListener.php @@ -37,8 +37,8 @@ class ConsoleListener /** * Constructor. * - * @param HubInterface $hub The current hub - * @param bool $captureErrors Whether to capture console errors + * @param HubInterface $hub The current hub + * @param bool $captureErrors Whether to capture console errors */ public function __construct(HubInterface $hub, bool $captureErrors = true) { @@ -62,7 +62,7 @@ public function handleConsoleCommandEvent(ConsoleCommandEvent $event): void } if ($input instanceof ArgvInput) { - $scope->setExtra('Full command', (string)$input); + $scope->setExtra('Full command', (string) $input); } } @@ -86,7 +86,7 @@ public function handleConsoleTerminateEvent(ConsoleTerminateEvent $event): void public function handleConsoleErrorEvent(ConsoleErrorEvent $event): void { $this->hub->configureScope(function (Scope $scope) use ($event): void { - $scope->setTag('console.command.exit_code', (string)$event->getExitCode()); + $scope->setTag('console.command.exit_code', (string) $event->getExitCode()); if ($this->captureErrors) { $hint = EventHint::fromArray([ diff --git a/src/EventListener/MetricsRequestListener.php b/src/EventListener/MetricsRequestListener.php index 1b9252dd..3d8124fe 100644 --- a/src/EventListener/MetricsRequestListener.php +++ b/src/EventListener/MetricsRequestListener.php @@ -1,5 +1,7 @@ count('test-counter', 10); @@ -18,5 +20,4 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - } diff --git a/tests/End2End/App/Controller/MetricsController.php b/tests/End2End/App/Controller/MetricsController.php index a431f05b..2fa01561 100644 --- a/tests/End2End/App/Controller/MetricsController.php +++ b/tests/End2End/App/Controller/MetricsController.php @@ -1,13 +1,15 @@ count('test-counter', 10); @@ -16,5 +18,4 @@ public function metrics(): Response return new Response(); } - } diff --git a/tests/End2End/MetricsEnd2EndTest.php b/tests/End2End/MetricsEnd2EndTest.php index bbc72643..d206bf1c 100644 --- a/tests/End2End/MetricsEnd2EndTest.php +++ b/tests/End2End/MetricsEnd2EndTest.php @@ -1,5 +1,7 @@ true]); From 2da899b2485b0ccc90360550c94fd9bbe4c8f3ad Mon Sep 17 00:00:00 2001 From: Martin Linzmayer Date: Mon, 1 Dec 2025 15:46:08 +0100 Subject: [PATCH 3/3] namespace --- tests/End2End/MetricsCommandTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/End2End/MetricsCommandTest.php b/tests/End2End/MetricsCommandTest.php index 618f9164..a86a0f13 100644 --- a/tests/End2End/MetricsCommandTest.php +++ b/tests/End2End/MetricsCommandTest.php @@ -2,10 +2,9 @@ declare(strict_types=1); -namespace End2End; +namespace Sentry\SentryBundle\Tests\End2End; use Sentry\SentryBundle\Tests\End2End\App\KernelWithMetrics; -use Sentry\SentryBundle\Tests\End2End\StubTransport; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\Console\Input\ArgvInput;