From 6a14cf9e28728b2e9c8fff77757cea1741ce71f1 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 11 Jul 2022 21:38:49 +1000 Subject: [PATCH] Tracer references tests (#759) * adding tests for tracer provider behaviour a recent bug highlighted that if there is no reference to a tracer provider, then the shared state will shutdown, even if that shared state is being used by active tracers. Adding a phpdoc comment explaining this behavior, and some tests to demonstrate it * moving tests into integration * removing accidental covers annotation --- examples/traces/demo/src/index.php | 4 +- src/SDK/Trace/TracerProvider.php | 6 ++- tests/Integration/SDK/TracerProviderTest.php | 49 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 tests/Integration/SDK/TracerProviderTest.php diff --git a/examples/traces/demo/src/index.php b/examples/traces/demo/src/index.php index 5e0097d02..6819a53df 100644 --- a/examples/traces/demo/src/index.php +++ b/examples/traces/demo/src/index.php @@ -70,12 +70,12 @@ //middleware starts root span based on route pattern, sets status from http code $app->add(function (Request $request, RequestHandler $handler) use ($tracer) { - $carrier = TraceContextPropagator::getInstance()->extract($request->getHeaders()); + $parent = TraceContextPropagator::getInstance()->extract($request->getHeaders()); $routeContext = RouteContext::fromRequest($request); $route = $routeContext->getRoute(); $root = $tracer->spanBuilder($route->getPattern()) ->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9)) - ->setParent($carrier) + ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) ->startSpan(); $root->activate(); diff --git a/src/SDK/Trace/TracerProvider.php b/src/SDK/Trace/TracerProvider.php index 61623bb78..e981ea6a8 100644 --- a/src/SDK/Trace/TracerProvider.php +++ b/src/SDK/Trace/TracerProvider.php @@ -63,7 +63,11 @@ public function forceFlush(): bool return $this->tracerSharedState->getSpanProcessor()->forceFlush(); } - /** @inheritDoc */ + /** + * @inheritDoc + * @note Getting a tracer without keeping a strong reference to the TracerProvider will cause the TracerProvider to + * immediately shut itself down including its shared state, ie don't do this: $tracer = (new TracerProvider())->getTracer('foo') + */ public function getTracer( string $name, ?string $version = null, diff --git a/tests/Integration/SDK/TracerProviderTest.php b/tests/Integration/SDK/TracerProviderTest.php new file mode 100644 index 000000000..74328ddb8 --- /dev/null +++ b/tests/Integration/SDK/TracerProviderTest.php @@ -0,0 +1,49 @@ +prophesize(SpanProcessorInterface::class); + // @phpstan-ignore-next-line + $spanProcessor->shutdown()->shouldBeCalledTimes(1); + + /* Because no reference is kept to the TracerProvider, it will immediately __destruct and shutdown, + which will also shut down span processors in shared state. */ + $tracer = (new TracerProvider($spanProcessor->reveal()))->getTracer('test'); + + $spanProcessor->checkProphecyMethodsPredictions(); + } + + /** + * @doesNotPerformAssertions + */ + public function test_tracer_remains_in_scope(): void + { + $prophet = new Prophet(); + $spanProcessor = $prophet->prophesize(SpanProcessorInterface::class); + // @phpstan-ignore-next-line + $spanProcessor->shutdown()->shouldBeCalledTimes(0); + + $tracerProvider = new TracerProvider($spanProcessor->reveal()); + $tracer = $tracerProvider->getTracer('test'); + + $spanProcessor->checkProphecyMethodsPredictions(); + } +}