From f3a61cc97c08faf6b547ab6c66201ab782036541 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:18:26 +0200 Subject: [PATCH 01/11] feat(pdo): declare DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED config --- ext/configuration.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/configuration.h b/ext/configuration.h index 599d2ed4eb..2ef199e639 100644 --- a/ext/configuration.h +++ b/ext/configuration.h @@ -138,6 +138,7 @@ enum ddtrace_sidecar_connection_mode { CONFIG(BOOL, DD_TRACE_HEALTH_METRICS_ENABLED, "false", .ini_change = zai_config_system_ini_change) \ CONFIG(DOUBLE, DD_TRACE_HEALTH_METRICS_HEARTBEAT_SAMPLE_RATE, "0.001") \ CONFIG(BOOL, DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE, "false") \ + CONFIG(BOOL, DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED, "true") \ CONFIG(BOOL, DD_TRACE_HTTP_CLIENT_SPLIT_BY_DOMAIN, "false") \ CONFIG(BOOL, DD_TRACE_REDIS_CLIENT_SPLIT_BY_HOST, "false") \ CONFIG(BOOL, DD_EXCEPTION_REPLAY_ENABLED, "false", .ini_change = ddtrace_alter_DD_EXCEPTION_REPLAY_ENABLED) \ From 579b021f3393af1822bfb33cfdfb9560b2f017fd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:18:28 +0200 Subject: [PATCH 02/11] docs(pdo): document DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED in supported-configurations --- metadata/supported-configurations.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index f4a3c4d064..6783dae455 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -1878,6 +1878,13 @@ "default": "true" } ], + "DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED": [ + { + "implementation": "A", + "type": "boolean", + "default": "true" + } + ], "DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED": [ { "implementation": "A", From f41a2e3b37ceca72c16b9e79a1a9bd6322e05118 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:18:37 +0200 Subject: [PATCH 03/11] test(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED to randomized config --- tests/randomized/config/envs.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/randomized/config/envs.php b/tests/randomized/config/envs.php index e79466fdd7..57d9aae2d4 100644 --- a/tests/randomized/config/envs.php +++ b/tests/randomized/config/envs.php @@ -29,6 +29,7 @@ 'DD_TRACE_AUTO_FLUSH_ENABLED' => ['true'], 'DD_TAGS' => ['tag_1:hi,tag_2:hello'], 'DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE' => ['true'], + 'DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED' => ['false'], 'DD_TRACE_HTTP_CLIENT_SPLIT_BY_DOMAIN' => ['true'], 'DD_TRACE_REDIS_CLIENT_SPLIT_BY_HOST' => ['true'], 'DD_TRACE_MEASURE_COMPILE_TIME' => ['false'], From 36021c2dc012bc520e0605fa9bd715169fe99c99 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:19:54 +0200 Subject: [PATCH 04/11] test(pdo): add tests for DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED Co-Authored-By: Claude Sonnet 4.6 --- tests/Integrations/PDO/PDOTest.php | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/Integrations/PDO/PDOTest.php b/tests/Integrations/PDO/PDOTest.php index 3e7261cbbd..9bf65d9e4e 100644 --- a/tests/Integrations/PDO/PDOTest.php +++ b/tests/Integrations/PDO/PDOTest.php @@ -50,6 +50,7 @@ protected function envsToCleanUpAtTearDown() { return [ 'DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE', + 'DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED', 'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED', 'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED', 'DD_SERVICE_MAPPING', @@ -489,6 +490,44 @@ public function testPDOStatementOkPeerServiceEnabled() ]); } + public function testPDOPreparedStatementsDisabled() + { + $this->putEnvAndReloadConfig(['DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED=false']); + + $query = "SELECT * FROM tests WHERE id = ?"; + $traces = $this->isolateTracer(function () use ($query) { + $pdo = $this->pdoInstance(); + $stmt = $pdo->prepare($query); + $stmt->execute([1]); + $results = $stmt->fetchAll(); + $this->assertEquals('Tom', $results[0]['name']); + $stmt->closeCursor(); + $stmt = null; + $pdo = null; + }); + // PDO.prepare and PDOStatement.execute spans must NOT appear + $this->assertSpans($traces, [ + SpanAssertion::exists('PDO.__construct'), + ]); + } + + public function testPDOPreparedStatementsDisabledDoesNotAffectExec() + { + $this->putEnvAndReloadConfig(['DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED=false']); + + $traces = $this->isolateTracer(function () { + $pdo = $this->pdoInstance(); + $pdo->exec("SELECT * FROM tests WHERE id = 1"); + $pdo = null; + }); + // PDO.exec span must still appear when prepared statements are disabled + $this->assertSpans($traces, [ + SpanAssertion::exists('PDO.__construct'), + SpanAssertion::build('PDO.exec', 'pdo', 'sql', 'SELECT * FROM tests WHERE id = 1') + ->withExactTags($this->baseTags()), + ]); + } + public function testPDOStatementSplitByDomain() { $this->putEnvAndReloadConfig(['DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE=true']); From 52b622591b33c10ffe16579ef9aa03e7c7f0340e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:21:27 +0200 Subject: [PATCH 05/11] feat(pdo): skip prepare/execute spans when DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED=false --- src/DDTrace/Integrations/PDO/PDOIntegration.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/DDTrace/Integrations/PDO/PDOIntegration.php b/src/DDTrace/Integrations/PDO/PDOIntegration.php index 7cdd94e90d..271666f2e9 100644 --- a/src/DDTrace/Integrations/PDO/PDOIntegration.php +++ b/src/DDTrace/Integrations/PDO/PDOIntegration.php @@ -117,6 +117,11 @@ public static function init(): int // public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] ) \DDTrace\install_hook('PDO::prepare', static function (HookData $hook) { list($query) = $hook->args; + + if (!\dd_trace_env_config("DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED")) { + return; // No span; post-hook still propagates connection metadata + } + $hook->data = $query; $span = $hook->span(); @@ -131,7 +136,7 @@ public static function init(): int }, static function (HookData $hook) { $pdo = $hook->returned; ObjectKVStore::propagate($hook->instance, $pdo, PDOIntegration::CONNECTION_TAGS_KEY); - if ($pdo instanceof \PDOStatement) { + if ($pdo instanceof \PDOStatement && isset($hook->data)) { \dd_trace_internal_fn("force_overwrite_property", $pdo, "queryString", $hook->data); // Restore the query string minus the DBM injected stuff } }); @@ -148,9 +153,14 @@ public static function init(): int \DDTrace\install_hook( 'PDOStatement::execute', static function (HookData $hook) { - $hook->span(); + if (\dd_trace_env_config("DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED")) { + $hook->span(); + } }, static function (HookData $hook) { + if (!\dd_trace_env_config("DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED")) { + return; + } $span = $hook->span(); $instance = $hook->instance; Integration::handleOrphan($span); From c1c7a5d265d19e73ed34c9d3887c56f6d2bf169a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 14:25:15 +0200 Subject: [PATCH 06/11] refactor(pdo): use hook->data sentinel to avoid double dd_trace_env_config call Co-Authored-By: Claude Sonnet 4.6 --- src/DDTrace/Integrations/PDO/PDOIntegration.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/DDTrace/Integrations/PDO/PDOIntegration.php b/src/DDTrace/Integrations/PDO/PDOIntegration.php index 271666f2e9..12f1db8f04 100644 --- a/src/DDTrace/Integrations/PDO/PDOIntegration.php +++ b/src/DDTrace/Integrations/PDO/PDOIntegration.php @@ -137,7 +137,7 @@ public static function init(): int $pdo = $hook->returned; ObjectKVStore::propagate($hook->instance, $pdo, PDOIntegration::CONNECTION_TAGS_KEY); if ($pdo instanceof \PDOStatement && isset($hook->data)) { - \dd_trace_internal_fn("force_overwrite_property", $pdo, "queryString", $hook->data); // Restore the query string minus the DBM injected stuff + \dd_trace_internal_fn("force_overwrite_property", $pdo, "queryString", $hook->data); // Only reached when span was created (flag enabled) and DBM may have modified queryString; restores the original query } }); @@ -154,11 +154,12 @@ public static function init(): int 'PDOStatement::execute', static function (HookData $hook) { if (\dd_trace_env_config("DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED")) { + $hook->data = true; $hook->span(); } }, static function (HookData $hook) { - if (!\dd_trace_env_config("DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED")) { + if (!isset($hook->data)) { return; } $span = $hook->span(); From 8e8e2285b5a6684ea1b7e38c6c95724be5365237 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 19:13:58 +0200 Subject: [PATCH 07/11] feat(pdo): declare DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED config Co-Authored-By: Claude Sonnet 4.6 --- ext/configuration.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/configuration.h b/ext/configuration.h index 2ef199e639..3f38a2d5dd 100644 --- a/ext/configuration.h +++ b/ext/configuration.h @@ -139,6 +139,7 @@ enum ddtrace_sidecar_connection_mode { CONFIG(DOUBLE, DD_TRACE_HEALTH_METRICS_HEARTBEAT_SAMPLE_RATE, "0.001") \ CONFIG(BOOL, DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE, "false") \ CONFIG(BOOL, DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED, "true") \ + CONFIG(BOOL, DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED, "true") \ CONFIG(BOOL, DD_TRACE_HTTP_CLIENT_SPLIT_BY_DOMAIN, "false") \ CONFIG(BOOL, DD_TRACE_REDIS_CLIENT_SPLIT_BY_HOST, "false") \ CONFIG(BOOL, DD_EXCEPTION_REPLAY_ENABLED, "false", .ini_change = ddtrace_alter_DD_EXCEPTION_REPLAY_ENABLED) \ From 33597d482c0470c7562abc98e299bfeea1daf5bf Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 19:14:01 +0200 Subject: [PATCH 08/11] test(pdo): add tests for DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED Co-Authored-By: Claude Sonnet 4.6 --- tests/Integrations/PDO/PDOTest.php | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/Integrations/PDO/PDOTest.php b/tests/Integrations/PDO/PDOTest.php index 9bf65d9e4e..34d8a113ab 100644 --- a/tests/Integrations/PDO/PDOTest.php +++ b/tests/Integrations/PDO/PDOTest.php @@ -51,6 +51,7 @@ protected function envsToCleanUpAtTearDown() return [ 'DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE', 'DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED', + 'DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED', 'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED', 'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED', 'DD_SERVICE_MAPPING', @@ -528,6 +529,47 @@ public function testPDOPreparedStatementsDisabledDoesNotAffectExec() ]); } + public function testPDOLifecycleCommandsDisabled() + { + $this->putEnvAndReloadConfig(['DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED=false']); + + $traces = $this->isolateTracer(function () { + $pdo = $this->pdoInstance(); + $pdo->exec("SELECT * FROM tests WHERE id = 1"); + $pdo = null; + }); + // PDO.__construct and PDO.commit spans must NOT appear; PDO.exec must still appear + $this->assertSpans($traces, [ + SpanAssertion::build('PDO.exec', 'pdo', 'sql', 'SELECT * FROM tests WHERE id = 1') + ->withExactTags($this->baseTags()), + ]); + } + + public function testPDOLifecycleCommandsDisabledTransactions() + { + $this->putEnvAndReloadConfig(['DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED=false']); + + $query = "INSERT INTO tests (id, name) VALUES (1000, 'Sam')"; + $traces = $this->isolateTracer(function () use ($query) { + $pdo = $this->pdoInstance(); + $pdo->beginTransaction(); + $pdo->exec($query); + $pdo->commit(); + $pdo = null; + }); + // PDO.beginTransaction, PDO.commit must NOT appear; PDO.exec must still appear + $this->assertSpans($traces, [ + SpanAssertion::build('PDO.exec', 'pdo', 'sql', $query) + ->withExactTags($this->baseTags()) + ->withExactMetrics([ + Tag::DB_ROW_COUNT => 1.0, + Tag::ANALYTICS_KEY => 1.0, + '_dd.agent_psr' => 1.0, + '_sampling_priority_v1' => 1.0, + ]), + ]); + } + public function testPDOStatementSplitByDomain() { $this->putEnvAndReloadConfig(['DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE=true']); From 7a291320c044b0055abf5e9111fe2a20ade6d559 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 19:14:04 +0200 Subject: [PATCH 09/11] feat(pdo): skip lifecycle spans when DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED=false Co-Authored-By: Claude Sonnet 4.6 --- .../Integrations/PDO/PDOIntegration.php | 69 +++++++++++++++---- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/src/DDTrace/Integrations/PDO/PDOIntegration.php b/src/DDTrace/Integrations/PDO/PDOIntegration.php index 12f1db8f04..72ca29d56b 100644 --- a/src/DDTrace/Integrations/PDO/PDOIntegration.php +++ b/src/DDTrace/Integrations/PDO/PDOIntegration.php @@ -42,24 +42,42 @@ public static function init(): int } // public PDO::__construct ( string $dsn [, string $username [, string $passwd [, array $options ]]] ) - \DDTrace\trace_method('PDO', '__construct', function (SpanData $span, array $args) { - Integration::handleOrphan($span); - $span->name = $span->resource = 'PDO.__construct'; - $connectionMetadata = PDOIntegration::extractConnectionMetadata($args); - ObjectKVStore::put($this, PDOIntegration::CONNECTION_TAGS_KEY, $connectionMetadata); - // We have to use $connectionMetadata as a medium, instead of $this (aka the PDO instance) because in - // PHP 5.* $this is NULL in this callback when there is a connection error. - PDOIntegration::setCommonSpanInfo($connectionMetadata, $span); - }); + \DDTrace\install_hook( + 'PDO::__construct', + static function (HookData $hook) { + if (\dd_trace_env_config("DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED")) { + $hook->span(); + $hook->data = true; + } + }, + static function (HookData $hook) { + $connectionMetadata = PDOIntegration::extractConnectionMetadata($hook->args); + // $hook->instance may be NULL on connection error (PHP 5.* compat note still applies) + if ($hook->instance !== null) { + ObjectKVStore::put($hook->instance, PDOIntegration::CONNECTION_TAGS_KEY, $connectionMetadata); + } + if (!isset($hook->data)) { + return; + } + $span = $hook->span(); + Integration::handleOrphan($span); + $span->name = $span->resource = 'PDO.__construct'; + PDOIntegration::setCommonSpanInfo($connectionMetadata, $span); + } + ); if (PHP_VERSION_ID >= 80400) { // public PDO::connect ( string $dsn [, string $username [, string $passwd [, array $options ]]] ) - \DDTrace\trace_method('PDO', 'connect', static function (SpanData $span, array $args, $pdo) { + \DDTrace\install_hook('PDO::connect', static function (HookData $hook) { + if (!\dd_trace_env_config("DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED")) { + return; + } + $span = $hook->span(); Integration::handleOrphan($span); $span->name = $span->resource = 'PDO.connect'; - $connectionMetadata = self::extractConnectionMetadata($args); - ObjectKVStore::put($pdo, self::CONNECTION_TAGS_KEY, $connectionMetadata); - self::setCommonSpanInfo($connectionMetadata, $span); + $connectionMetadata = PDOIntegration::extractConnectionMetadata($hook->args); + ObjectKVStore::put($hook->instance, PDOIntegration::CONNECTION_TAGS_KEY, $connectionMetadata); + PDOIntegration::setCommonSpanInfo($connectionMetadata, $span); }); } @@ -141,14 +159,39 @@ public static function init(): int } }); + // public bool PDO::beginTransaction ( void ) + \DDTrace\install_hook('PDO::beginTransaction', static function (HookData $hook) { + if (!\dd_trace_env_config("DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED")) { + return; + } + $span = $hook->span(); + Integration::handleOrphan($span); + $span->name = $span->resource = 'PDO.beginTransaction'; + PDOIntegration::setCommonSpanInfo($hook->instance, $span); + }); + // public bool PDO::commit ( void ) \DDTrace\install_hook('PDO::commit', static function (HookData $hook) { + if (!\dd_trace_env_config("DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED")) { + return; + } $span = $hook->span(); Integration::handleOrphan($span); $span->name = $span->resource = 'PDO.commit'; PDOIntegration::setCommonSpanInfo($hook->instance, $span); }); + // public bool PDO::rollBack ( void ) + \DDTrace\install_hook('PDO::rollBack', static function (HookData $hook) { + if (!\dd_trace_env_config("DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED")) { + return; + } + $span = $hook->span(); + Integration::handleOrphan($span); + $span->name = $span->resource = 'PDO.rollBack'; + PDOIntegration::setCommonSpanInfo($hook->instance, $span); + }); + // public bool PDOStatement::execute ([ array $input_parameters ] ) \DDTrace\install_hook( 'PDOStatement::execute', From 93b0487a2a1cc9e116a4d90effbeead758568322 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 19:14:07 +0200 Subject: [PATCH 10/11] docs(pdo): document DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED Co-Authored-By: Claude Sonnet 4.6 --- metadata/supported-configurations.json | 7 +++++++ tests/randomized/config/envs.php | 1 + 2 files changed, 8 insertions(+) diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 6783dae455..1e1eca1d96 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -1878,6 +1878,13 @@ "default": "true" } ], + "DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED": [ + { + "implementation": "A", + "type": "boolean", + "default": "true" + } + ], "DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED": [ { "implementation": "A", diff --git a/tests/randomized/config/envs.php b/tests/randomized/config/envs.php index 57d9aae2d4..21e0c6fca0 100644 --- a/tests/randomized/config/envs.php +++ b/tests/randomized/config/envs.php @@ -30,6 +30,7 @@ 'DD_TAGS' => ['tag_1:hi,tag_2:hello'], 'DD_TRACE_DB_CLIENT_SPLIT_BY_INSTANCE' => ['true'], 'DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED' => ['false'], + 'DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED' => ['false'], 'DD_TRACE_HTTP_CLIENT_SPLIT_BY_DOMAIN' => ['true'], 'DD_TRACE_REDIS_CLIENT_SPLIT_BY_HOST' => ['true'], 'DD_TRACE_MEASURE_COMPILE_TIME' => ['false'], From 2d534b780df0573d1a6f495e96f9e08cd9f90643 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Delhommeau Date: Mon, 30 Mar 2026 19:27:41 +0200 Subject: [PATCH 11/11] fix(pdo): update existing tests to account for new beginTransaction/rollBack spans Add SpanAssertion::exists('PDO.beginTransaction') to the five failing tests that call $pdo->beginTransaction() but had no corresponding span assertion after DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED began tracing that method. Co-Authored-By: Claude Sonnet 4.6 --- tests/Integrations/PDO/PDOTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Integrations/PDO/PDOTest.php b/tests/Integrations/PDO/PDOTest.php index 34d8a113ab..7bc58dd111 100644 --- a/tests/Integrations/PDO/PDOTest.php +++ b/tests/Integrations/PDO/PDOTest.php @@ -234,6 +234,7 @@ public function testPDOExecOk() }); $this->assertSpans($traces, [ SpanAssertion::exists('PDO.__construct'), + SpanAssertion::exists('PDO.beginTransaction'), SpanAssertion::build('PDO.exec', 'pdo', 'sql', $query) ->withExactTags($this->baseTags()) ->withExactMetrics([ @@ -261,6 +262,7 @@ public function testPDOExecError() }); $this->assertSpans($traces, [ SpanAssertion::exists('PDO.__construct'), + SpanAssertion::exists('PDO.beginTransaction'), SpanAssertion::build('PDO.exec', 'pdo', 'sql', $query) ->setError('PDO error', 'SQL error: 42000. Driver error: 1064. Driver-specific error data: You have an error in your SQL syntax') ->withExactTags($this->baseTags()), @@ -285,6 +287,7 @@ public function testPDOExecException() }); $this->assertSpans($traces, [ SpanAssertion::exists('PDO.__construct'), + SpanAssertion::exists('PDO.beginTransaction'), SpanAssertion::build('PDO.exec', 'pdo', 'sql', $query) ->setError('PDOException', static::ERROR_EXEC, true) ->withExactTags($this->baseTags()), @@ -409,6 +412,7 @@ public function testPDOCommit() }); $this->assertSpans($traces, [ SpanAssertion::exists('PDO.__construct'), + SpanAssertion::exists('PDO.beginTransaction'), SpanAssertion::exists('PDO.exec'), SpanAssertion::build('PDO.commit', 'pdo', 'sql', 'PDO.commit') ->withExactTags($this->baseTags()), @@ -900,6 +904,7 @@ public function testNoFakeServices() }); $this->assertSpans($traces, [ SpanAssertion::exists('PDO.__construct'), + SpanAssertion::exists('PDO.beginTransaction'), SpanAssertion::build('PDO.exec', 'configured_service', 'sql', $query) ->withExactTags($this->baseTags()) ->withExactMetrics([Tag::DB_ROW_COUNT => 1.0, Tag::ANALYTICS_KEY => 1.0]),