From 4172d62fcd12cb640ca8ca9e04c01c56fea6409a Mon Sep 17 00:00:00 2001 From: Cedric Ziel Date: Fri, 12 Jul 2024 00:47:55 +0200 Subject: [PATCH] feat: Record handled exceptions (#280) This change records exceptions even if they are handled by the Kernel. This is handy for apps that have an error handler registered. --- src/SymfonyInstrumentation.php | 24 +++++++++++++++++++ .../SymfonyInstrumentationTest.php | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/SymfonyInstrumentation.php b/src/SymfonyInstrumentation.php index 898ca0f..0c05a9b 100644 --- a/src/SymfonyInstrumentation.php +++ b/src/SymfonyInstrumentation.php @@ -141,5 +141,29 @@ public static function register(): void $span->end(); } ); + + hook( + HttpKernel::class, + 'handleThrowable', + pre: static function ( + HttpKernel $kernel, + array $params, + string $class, + string $function, + ?string $filename, + ?int $lineno, + ): array { + /** @var \Throwable $throwable */ + $throwable = $params[0]; + + Span::getCurrent() + ->recordException($throwable, [ + TraceAttributes::EXCEPTION_ESCAPED => true, + ]) + ->setStatus(StatusCode::STATUS_ERROR, $throwable->getMessage()); + + return $params; + }, + ); } } diff --git a/tests/Integration/SymfonyInstrumentationTest.php b/tests/Integration/SymfonyInstrumentationTest.php index 37548aa..7bbe0a6 100644 --- a/tests/Integration/SymfonyInstrumentationTest.php +++ b/tests/Integration/SymfonyInstrumentationTest.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Tests\Instrumentation\Symfony\tests\Integration; use OpenTelemetry\API\Trace\SpanKind; +use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Contrib\Propagation\ServerTiming\ServerTimingPropagator; use OpenTelemetry\Contrib\Propagation\TraceResponse\TraceResponsePropagator; use OpenTelemetry\SDK\Trace\ImmutableSpan; @@ -18,6 +19,7 @@ use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -40,6 +42,28 @@ public function test_http_kernel_handle_exception(): void ); } + public function test_http_kernel_marks_root_as_erroneous(): void + { + $this->expectException(HttpException::class); + $kernel = $this->getHttpKernel(new EventDispatcher(), function () { + throw new HttpException(500, 'foo'); + }); + $this->assertCount(0, $this->storage); + + $response = $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true); + + $this->assertCount(1, $this->storage); + $this->assertSame(500, $this->storage[0]->getAttributes()->get(TraceAttributes::HTTP_RESPONSE_STATUS_CODE)); + + $this->assertSame(StatusCode::STATUS_ERROR, $this->storage[0]->getStatus()->getCode()); + + $this->assertArrayHasKey( + TraceResponsePropagator::TRACERESPONSE, + $response->headers->all(), + 'traceresponse header is present if TraceResponsePropagator is present' + ); + } + public function test_http_kernel_handle_attributes(): void { $kernel = $this->getHttpKernel(new EventDispatcher());