diff --git a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php index 68ebd161..089c48b3 100644 --- a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php +++ b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php @@ -92,6 +92,30 @@ public static function register(): void array $params, ?Response $response, ?\Throwable $exception + ): void { + $scope = Context::storage()->scope(); + if (null === $scope || null === $exception) { + return; + } + + $span = Span::fromContext($scope->context()); + $scope->detach(); + $span->recordException($exception, [ + TraceAttributes::EXCEPTION_ESCAPED => true, + ]); + if (null !== $response && $response->getStatusCode() >= Response::HTTP_INTERNAL_SERVER_ERROR) { + $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); + } + } + ); + + hook( + HttpKernel::class, + 'terminate', + post: static function ( + HttpKernel $kernel, + array $params, + ?\Throwable $exception ): void { $scope = Context::storage()->scope(); if (null === $scope) { @@ -101,6 +125,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); $request = ($params[0] instanceof Request) ? $params[0] : null; + $response = ($params[1] instanceof Response) ? $params[1] : null; if (null !== $request) { $routeName = $request->attributes->get('_route', ''); diff --git a/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php b/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php index 03a8227d..231313cf 100644 --- a/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php +++ b/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php @@ -29,7 +29,15 @@ public function test_http_kernel_handle_exception(): void throw new \RuntimeException(); }); $this->assertCount(0, $this->storage); - $kernel->handle(new Request()); + + $response = $kernel->handle(new Request()); + $kernel->terminate(new Request(), $response); + + $this->assertArrayHasKey( + TraceResponsePropagator::TRACERESPONSE, + $response->headers->all(), + 'traceresponse header is present if TraceResponsePropagator is present' + ); } public function test_http_kernel_marks_root_as_erroneous(): void @@ -40,7 +48,8 @@ public function test_http_kernel_marks_root_as_erroneous(): void }); $this->assertCount(0, $this->storage); - $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true); + $response = $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true); + $kernel->terminate(new Request(), $response); $this->assertCount(1, $this->storage); $this->assertSame(500, $this->storage[0]->getAttributes()->get(TraceAttributes::HTTP_RESPONSE_STATUS_CODE)); @@ -55,7 +64,8 @@ public function test_http_kernel_handle_attributes(): void $request = new Request(); $request->attributes->set('_route', 'test_route'); - $kernel->handle($request); + $response = $kernel->handle($request); + $kernel->terminate($request, $response); $attributes = $this->storage[0]->getAttributes(); $this->assertCount(1, $this->storage); @@ -78,7 +88,9 @@ public function test_http_kernel_handle_stream_response(): void })); $this->assertCount(0, $this->storage); - $kernel->handle(new Request()); + $response = $kernel->handle(new Request()); + $kernel->terminate(new Request(), $response); + $this->assertCount(1, $this->storage); $this->assertNull($this->storage[0]->getAttributes()->get(TraceAttributes::HTTP_RESPONSE_BODY_SIZE)); } @@ -88,7 +100,9 @@ public function test_http_kernel_handle_binary_file_response(): void $kernel = $this->getHttpKernel(new EventDispatcher(), fn () => new BinaryFileResponse(__FILE__)); $this->assertCount(0, $this->storage); - $kernel->handle(new Request()); + $response = $kernel->handle(new Request()); + $kernel->terminate(new Request(), $response); + $this->assertCount(1, $this->storage); $this->assertNull($this->storage[0]->getAttributes()->get(TraceAttributes::HTTP_RESPONSE_BODY_SIZE)); @@ -101,7 +115,9 @@ public function test_http_kernel_handle_with_empty_route(): void $request = new Request(); $request->attributes->set('_route', ''); - $kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, true); + $response = $kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, true); + $kernel->terminate(new Request(), $response); + $this->assertCount(1, $this->storage); $this->assertFalse($this->storage[0]->getAttributes()->has(TraceAttributes::HTTP_ROUTE)); @@ -112,7 +128,9 @@ public function test_http_kernel_handle_without_route(): void $kernel = $this->getHttpKernel(new EventDispatcher()); $this->assertCount(0, $this->storage); - $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true); + $response = $kernel->handle(new Request(), HttpKernelInterface::MAIN_REQUEST, true); + $kernel->terminate(new Request(), $response); + $this->assertCount(1, $this->storage); $this->assertFalse($this->storage[0]->getAttributes()->has(TraceAttributes::HTTP_ROUTE)); @@ -125,7 +143,9 @@ public function test_http_kernel_handle_subrequest(): void $request = new Request(); $request->attributes->set('_controller', 'ErrorController'); - $kernel->handle($request, HttpKernelInterface::SUB_REQUEST); + $response = $kernel->handle($request, HttpKernelInterface::SUB_REQUEST); + $kernel->terminate($request, $response); + $this->assertCount(1, $this->storage); $span = $this->storage[0];