diff --git a/src/Instrumentation/PDO/composer.json b/src/Instrumentation/PDO/composer.json index 934292abe..442b64f49 100644 --- a/src/Instrumentation/PDO/composer.json +++ b/src/Instrumentation/PDO/composer.json @@ -27,6 +27,7 @@ "phpstan/phpstan-phpunit": "^1.0", "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", + "open-telemetry/test-utils": "^0.2.0", "phpunit/phpunit": "^9.5", "vimeo/psalm": "6.4.0" }, diff --git a/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php b/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php index 7248cec69..9398c8701 100644 --- a/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php +++ b/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php @@ -15,11 +15,14 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor; use OpenTelemetry\SDK\Trace\TracerProvider; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\TestUtils\TraceStructureAssertionTrait; use PDO; use PHPUnit\Framework\TestCase; class PDOInstrumentationTest extends TestCase { + use TraceStructureAssertionTrait; + private ScopeInterface $scope; /** @var ArrayObject */ private ArrayObject $storage; @@ -113,7 +116,7 @@ public function test_pdo_sqlite_subclass(): void // Test that the subclass-specific methods work $db->createFunction('test_function', static fn ($value) => strtoupper($value)); - + // Test that standard PDO operations still work $db->exec($this->fillDB()); $span = $this->storage->offsetGet(1); @@ -288,7 +291,7 @@ public function test_span_hierarchy_with_pdo_operations(): void $serverSpan = $tracer->spanBuilder('HTTP GET /api/users') ->setSpanKind(SpanKind::KIND_SERVER) ->startSpan(); - + // Create scope for server span $serverScope = Context::storage()->attach($serverSpan->storeInContext(Context::getCurrent())); @@ -297,7 +300,7 @@ public function test_span_hierarchy_with_pdo_operations(): void $internalSpan = $tracer->spanBuilder('processUserData') ->setSpanKind(SpanKind::KIND_INTERNAL) ->startSpan(); - + // Create scope for internal span $internalScope = Context::storage()->attach($internalSpan->storeInContext(Context::getCurrent())); @@ -340,6 +343,63 @@ public function test_span_hierarchy_with_pdo_operations(): void // Detach scopes $internalScope->detach(); + $internalSpan->end(); $serverScope->detach(); + $serverSpan->end(); + + $this->assertTraceStructure( + $this->storage, + [ + [ + 'name' => 'HTTP GET /api/users', + 'kind' => SpanKind::KIND_SERVER, + 'attributes' => [], + 'children' => [ + [ + 'name' => 'processUserData', + 'kind' => SpanKind::KIND_INTERNAL, + 'attributes' => [], + 'children' => [ + [ + 'name' => 'PDO::__construct', + 'kind' => SpanKind::KIND_CLIENT, + 'attributes' => [ + TraceAttributes::DB_SYSTEM_NAME => 'sqlite', + ], + ], + [ + 'name' => 'PDO::exec', + 'kind' => SpanKind::KIND_CLIENT, + 'attributes' => [ + TraceAttributes::DB_SYSTEM_NAME => 'sqlite', + ], + ], + [ + 'name' => 'PDO::prepare', + 'kind' => SpanKind::KIND_CLIENT, + 'attributes' => [ + TraceAttributes::DB_SYSTEM_NAME => 'sqlite', + ], + ], + [ + 'name' => 'PDOStatement::execute', + 'kind' => SpanKind::KIND_CLIENT, + 'attributes' => [ + TraceAttributes::DB_SYSTEM_NAME => 'sqlite', + ], + ], + [ + 'name' => 'PDOStatement::fetchAll', + 'kind' => SpanKind::KIND_CLIENT, + 'attributes' => [ + TraceAttributes::DB_SYSTEM_NAME => 'sqlite', + ], + ], + ], + ], + ], + ], + ] + ); } }