diff --git a/src/Http/src/Http.php b/src/Http/src/Http.php index 8ce37f96b..374428775 100644 --- a/src/Http/src/Http.php +++ b/src/Http/src/Http.php @@ -96,11 +96,11 @@ public function handle(ServerRequestInterface $request): ResponseInterface callback: $callback, attributes: [ 'http.method' => $request->getMethod(), - 'http.url' => $request->getUri(), + 'http.url' => (string) $request->getUri(), 'http.headers' => $request->getHeaders(), ], scoped: true, - traceKind: TraceKind::SERVER + traceKind: TraceKind::SERVER, ); foreach ($tracer->getContext() as $key => $value) { diff --git a/src/Http/tests/HttpTest.php b/src/Http/tests/HttpTest.php index 755d74c97..87d985dd8 100644 --- a/src/Http/tests/HttpTest.php +++ b/src/Http/tests/HttpTest.php @@ -19,6 +19,7 @@ use Spiral\Telemetry\NullTracer; use Spiral\Telemetry\TracerFactoryInterface; use Spiral\Telemetry\TracerInterface; +use Spiral\Telemetry\TraceKind; use Spiral\Tests\Http\Diactoros\ResponseFactory; use Nyholm\Psr7\ServerRequest; @@ -263,7 +264,7 @@ public function testEventsShouldBeDispatched(): void public function testPassingTracerIntoScope(): void { $config = $this->getHttpConfig(); - $request = new ServerRequest('GET', '', ['foo' => ['bar']]); + $request = new ServerRequest('GET', 'http://example.org/path', ['foo' => ['bar']]); $http = new Http( $config, @@ -277,15 +278,115 @@ public function testPassingTracerIntoScope(): void return 'hello world'; }); - $tracerFactory->shouldReceive('make') + $tracerFactory + ->shouldReceive('make') ->once() - ->with(['foo' => ['bar']]) + ->with(['Host' => ['example.org'], 'foo' => ['bar']]) ->andReturn(new NullTracer($this->container)); $response = $http->handle($request); $this->assertSame('hello world', (string)$response->getBody()); } + public function testTraceAttributesAreSet(): void + { + $config = $this->getHttpConfig(); + $request = new ServerRequest('GET', 'http://example.org/path', ['foo' => ['bar']]); + + $tracer = $this->createMock(TracerInterface::class); + $tracer + ->expects($this->once()) + ->method('trace') + ->with( + 'GET http://example.org/path', + $this->anything(), + [ + 'http.method' => 'GET', + 'http.url' => 'http://example.org/path', + 'http.headers' => ['Host' => ['example.org'], 'foo' => ['bar']], + ], + true, + TraceKind::SERVER, + ) + ->willReturnCallback( + function ($name, $callback, $attributes, $scoped, $traceKind) { + self::assertSame($attributes, [ + 'http.method' => 'GET', + 'http.url' => 'http://example.org/path', + 'http.headers' => ['Host' => ['example.org'], 'foo' => ['bar']], + ]); + return $this->container + ->get(TracerInterface::class) + ->trace($name, $callback, $attributes, $scoped, $traceKind); + }, + ); + $tracer + ->expects($this->once()) + ->method('getContext') + ->willReturn([]); + + $tracerFactory = $this->createMock(TracerFactoryInterface::class); + $tracerFactory + ->expects($this->once()) + ->method('make') + ->willReturn($tracer); + + $http = new Http( + $config, + new Pipeline($this->container), + new ResponseFactory($config), + $this->container, + $tracerFactory, + ); + + $http->setHandler(function () { + return 'hello world'; + }); + + $response = $http->handle($request); + $this->assertSame('hello world', (string)$response->getBody()); + } + + public function testTraceContextIsAppliedToResponse(): void + { + $config = $this->getHttpConfig(); + $request = new ServerRequest('GET', '', ['foo' => ['bar']]); + + $http = new Http( + $config, + new Pipeline($this->container), + new ResponseFactory($config), + $this->container, + $tracerFactory = m::mock(TracerFactoryInterface::class), + ); + + $http->setHandler(function () { + return 'hello world'; + }); + + $tracerFactory + ->shouldReceive('make') + ->once() + ->andReturn($tracer = m::mock(TracerInterface::class)); + + $tracer + ->shouldReceive('trace') + ->once() + ->andReturnUsing(function($name, $callback, $attributes, $scoped, $traceKind) { + return $this->container->get(TracerInterface::class)->trace($name, $callback, $attributes, $scoped, $traceKind); + }); + + $tracer + ->shouldReceive('getContext') + ->once() + ->withNoArgs() + ->andReturn(['baz' => 'quux']); + + $response = $http->handle($request); + $this->assertSame('hello world', (string)$response->getBody()); + $this->assertSame(['quux'], $response->getHeader('baz')); + } + protected function getCore(array $middleware = []): Http { $config = $this->getHttpConfig($middleware);