feat(otel): add support for opentelemetry logs#3748
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3748 +/- ##
==========================================
- Coverage 68.85% 68.78% -0.08%
==========================================
Files 166 166
Lines 19015 19015
Branches 1792 1792
==========================================
- Hits 13093 13079 -14
- Misses 5111 5124 +13
- Partials 811 812 +1
Flags with carried forward coverage won't be shown. Click here to find out more. Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: 663d0f6 | Docs | Datadog PR Page | Give us feedback! |
Benchmarks [ tracer ]Benchmark execution time: 2026-05-12 18:03:48 Comparing candidate commit 663d0f6 in PR branch Found 0 performance improvements and 1 performance regressions! Performance is the same for 193 metrics, 0 unstable metrics. scenario:LogsInjectionBench/benchLogsInfoInjection-opcache
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0b32bc04a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…olver The previous override flipped OTEL_PHP_AUTOLOAD_ENABLED=true whenever DD_LOGS_OTEL_ENABLED or DD_METRICS_OTEL_ENABLED was set. That caused two unintended side effects: 1. SdkAutoloader::environmentBasedInitializer builds *all three* providers (Tracer, Meter, Logger), each defaulting to OTLP exporters via OTEL_TRACES_EXPORTER / OTEL_METRICS_EXPORTER / OTEL_LOGS_EXPORTER. So opting into Datadog's OTel logs path could silently activate OTLP trace + metric export for any user code reaching for Globals::tracerProvider() / meterProvider(). 2. SdkAutoloader::registerInstrumentations runs ServiceLoader::load on the OTel auto-instrumentation SPI, registering every contrib-auto-* package present on the classpath — completely unrelated to logs. DD_LOGS_OTEL_ENABLED now only triggers our existing bridge-file load (via dd_perform_autoload) and the DatadogResolver defaults for OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, mirroring the pattern DD_METRICS_OTEL_ENABLED already follows. Users wire their own LoggerProvider (and may opt into OTEL_PHP_AUTOLOAD_ENABLED themselves with full knowledge of its side effects). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The function was added in the original WIP commit but never wired via .env_config_fallback in configuration.h. The metrics counterpart hooks DD_INTEGRATION_METRICS_ENABLED, but PHP has no equivalent DD_INTEGRATION_LOGS_ENABLED to attach this to. Dead code; removing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous one-line guard in DDTrace\Log\DatadogLogger was wrong on two fronts: 1. DatadogLogger is the @internal logger we use for our own integrations' diagnostic output — it is never funneled through OTel logs and so does not need an OTel-aware path. 2. The real log-injection mechanism lives in LogsIntegration, which hooks Psr\Log\LoggerInterface methods to stamp dd.trace_id / dd.span_id / dd.service / dd.version / dd.env into the log call. PHP loggers aren't autowired to OTel — users opt in by attaching the OpenTelemetry\Contrib\Logs\Monolog\Handler (from open-telemetry/opentelemetry-logger-monolog) to a Monolog\Logger. Only calls landing on a logger with that handler attached produce an OTLP LogRecord; the rest still go to files / syslog / etc. and want dd.* injection as before. So instead of a blanket disable, this scopes the skip to exactly the loggers that are OTel-routed: when DD_LOGS_OTEL_ENABLED=true, the PSR-3 hook checks $hook->instance for a Monolog\Logger with an OpenTelemetry\Contrib\Logs\Monolog\Handler in its handler stack, and returns early only in that case. Non-Monolog and non-OTel-routed loggers keep getting dd.* injection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds DD_LOGS_OTEL_ENABLED to the metadata file. CI's generate-supported-configurations.sh check rejects commits that leave ext/configuration.h and metadata/supported-configurations.json out of sync. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bwoebi
left a comment
There was a problem hiding this comment.
Looks ready for merging to me now.
Note the rationale (Datadog Agent already handles host attribution; container IDs leaking as host.name would break correlation) so the strip behavior isn't mysterious to future readers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reverts the earlier change to use the bare deployment.environment key. The OTel semantic conventions moved to deployment.environment.name (the .name suffix is the current canonical form). System-tests' FR03 still passes because the upstream Environment detector handles compatibility: when OTEL_RESOURCE_ATTRIBUTES sets deployment.environment, the cross- language contract is satisfied without us needing to emit the bare key ourselves. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per Bob's review: the install_hook on Protocols::contentType assigned \$hook->args[0] directly but never propagated the change into the called method (the dd-trace-php hook API requires \$hook->overrideArguments(...) for that). So the fallback never actually replaced an invalid protocol, and the SDK's UnexpectedValueException kept reaching the caller anyway. Drop the hook entirely. Throwing on an unrecognized protocol is the right behavior — silently substituting 'http/protobuf' would have hidden configuration errors. The 404 warning hook stays; that one is functional and useful. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t derivation The existing LogsTest.php was almost entirely smoke tests (assert classes exist, assert provider is non-null). Add one real-feature assertion: with DD_LOGS_OTEL_ENABLED=true and DD_AGENT_HOST set, DatadogResolver should return the agent-derived OTLP logs endpoint (http://<agent>:4318/v1/logs) when neither OTEL_EXPORTER_OTLP_LOGS_ENDPOINT nor OTEL_EXPORTER_OTLP_ENDPOINT is set. This is the load-bearing wiring that lets users opt into OTel logs with a single env var — system-tests covers it end-to-end, but having a phpunit assertion guards against regressions during local development. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI run revealed putEnvAndReloadConfig doesn't repropagate DD_AGENT_HOST
through ddtrace_reload_config the way it does for boolean configs like
DD_LOGS_OTEL_ENABLED — the test was getting the registered default
('localhost') back rather than the override, so the hardcoded
'http://test-agent.example:4318/v1/logs' assertion failed.
Rewrite to assert on the URL *shape* (http scheme + :4318/v1/logs suffix)
which is the actual load-bearing wiring this PR adds, and which doesn't
depend on overriding DD_AGENT_HOST at runtime.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
Adds OpenTelemetry logs support to dd-trace-php, gated behind a new DD_LOGS_OTEL_ENABLED configuration flag.
New config flag:
DD_LOGS_OTEL_ENABLED(default: false) enables OTel log collection and OTLP export. When enabled, Datadog's own log injection is suppressed so the two pipelines don't conflict.Reviewer checklist