Skip to content

feat(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED and DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED#3752

Open
jbdelhommeau wants to merge 11 commits intoDataDog:masterfrom
jbdelhommeau:feat/3751-pdo-prepared-statements-enabled
Open

feat(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED and DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED#3752
jbdelhommeau wants to merge 11 commits intoDataDog:masterfrom
jbdelhommeau:feat/3751-pdo-prepared-statements-enabled

Conversation

@jbdelhommeau
Copy link
Copy Markdown

@jbdelhommeau jbdelhommeau commented Mar 30, 2026

Summary

Two complementary PHP PDO configuration variables — a PHP port of the Go tracer's WithIgnoreQueryTypes():

  1. DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED (boolean, default true) — suppress PDO.prepare + PDOStatement.execute spans
  2. DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED (boolean, default true) — suppress connection and transaction lifecycle spans

Closes #3751

Rationale — Go tracer parité

In the Go tracer, WithIgnoreQueryTypes(QueryType...) lets users opt out of specific operation types at code level. PHP exposes the same control as environment variables (no redeployment required):

PHP variable Go WithIgnoreQueryTypes equivalent
DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED=false QueryTypePrepare
DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED=false QueryTypeConnect + QueryTypeBegin + QueryTypeCommit + QueryTypeRollback

This is also consistent with DD_TRACE_REDIS_LIFECYCLE_COMMANDS_ENABLED added in PR #3757 for Redis/Predis.

Behaviour

DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED

Span true (default) false
PDO.prepare
PDOStatement.execute
PDO.exec / PDO.query

DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED

Span true (default) false
PDO.__construct
PDO.connect
PDO.beginTransaction (new)
PDO.commit
PDO.rollBack (new)
PDO.exec / PDO.query / prepared statements

Connection metadata (out.host, db.system, etc.) is always preserved via ObjectKVStore regardless of flags, so data command spans keep their tags.

Changes

File Change
ext/configuration.h Two new CONFIG(BOOL, ...) declarations
src/DDTrace/Integrations/PDO/PDOIntegration.php Per-call flag checks via install_hook; __construct + connect converted from trace_method; beginTransaction and rollBack added as new traced methods
metadata/supported-configurations.json Both variables documented
tests/Integrations/PDO/PDOTest.php Tests for both flags; existing tests updated for new beginTransaction/rollBack spans
tests/randomized/config/envs.php Both variables added to randomized coverage

Implementation notes

  • All lifecycle hooks use install_hook with a per-call dd_trace_env_config() check — necessary because hooks are registered once at init() time but config can change per-request (test isolation via putEnvAndReloadConfig).
  • PDO::__construct uses prehook+posthook pair: prehook creates the span (covers constructor duration), posthook stores ObjectKVStore metadata (requires constructor to have completed) and sets span attributes.
  • PDOStatement::execute uses $hook->data = true sentinel to avoid a second dd_trace_env_config() call in the posthook.

Test plan

  • testPDOPreparedStatementsDisabled — no prepare/execute spans when flag=false
  • testPDOPreparedStatementsDisabledDoesNotAffectExec — exec still traced
  • testPDOLifecycleCommandsDisabled — no construct/commit spans; exec still traced
  • testPDOLifecycleCommandsDisabledTransactions — no beginTransaction/commit/rollBack; exec still traced
  • All 34 PDO tests pass (default true preserves existing behaviour)

🤖 Generated with Claude Code

@bwoebi
Copy link
Copy Markdown
Collaborator

bwoebi commented Mar 30, 2026

Hey @jbdelhommeau,

I think it's worth adding such a config given that it's been a repeated ask.

However is the goal really fully eliminating all traces of queries being executed at all via prepared statement?
I feel like we should rather aim at finding ways to coalesce consecutive prepare+execute or repeated execute statements?

(the tracer has facilities to extend the duration of already closed spans etc.)

@jbdelhommeau
Copy link
Copy Markdown
Author

cc @bwoebi !
No it's more to avoid noise about useless PREPARED STATEMENTS span.
When you generate few request we can generate a lot span and consume our monthly span credit with a poor business value.

Like the dd-trace-go I backported this feature.

jbdelhommeau and others added 5 commits March 30, 2026 19:13
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ENABLED=false

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ollBack 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 <noreply@anthropic.com>
@jbdelhommeau jbdelhommeau changed the title feat(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED to disable prepare/execute spans feat(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED and DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(pdo): add DD_TRACE_PDO_PREPARED_STATEMENTS_ENABLED and DD_TRACE_PDO_LIFECYCLE_COMMANDS_ENABLED

2 participants