Skip to content

feat: report OTLP export status in startup log - #19265

Draft
bm1549 wants to merge 1 commit into
mainfrom
brian.marks/otlp-export-startup-log
Draft

feat: report OTLP export status in startup log#19265
bm1549 wants to merge 1 commit into
mainfrom
brian.marks/otlp-export-startup-log

Conversation

@bm1549

@bm1549 bm1549 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Description

Adds three boolean fields to the tracer's startup diagnostic log ("DATADOG TRACER CONFIGURATION"), emitted from collect() in ddtrace/internal/debug.py:

  • otlp_traces_export_enabled: reflects agent_config.trace_otlp_export_enabled (OTLP trace export, opt-in via OTEL_TRACES_EXPORTER=otlp)
  • otlp_metrics_export_enabled: reflects config._otel_metrics_enabled
  • otlp_logs_export_enabled: reflects config._otel_logs_enabled

This makes the OTLP export configuration visible in the startup log, which helps with support and debugging. It is part of a cross-tracer effort, so the JSON keys are identical across the dd-trace-* libraries.

Testing

  • test_standard_tags asserts the three keys are present and boolean.
  • test_otlp_export_enabled_fields_default runs in a subprocess with the OTLP-related env cleared and asserts all three default to False.
  • test_otlp_export_enabled_fields_set runs in a subprocess with OTEL_TRACES_EXPORTER=otlp and the metrics/logs flags enabled, and asserts all three report True.

Risks

None. The change only adds fields to an existing diagnostic log. No existing fields or behavior change.

Additional Notes

No release note is needed: this change only adds fields to the tracer's internal startup diagnostic log and does not change customer-facing behavior. The PR carries the changelog/no-changelog label.


Related PRs — cross-tracer OTLP startup-log effort

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🔄 Datadog auto-retried 1 job - 1 passed on retry View in Datadog

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 8beb3e0 | Docs | Datadog PR Page | Give us feedback!

@pr-commenter

pr-commenter Bot commented Jul 24, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-07-25 03:11:10

Comparing candidate commit 8beb3e0 in PR branch brian.marks/otlp-export-startup-log with baseline commit 1eda3bc in branch main.

Found 0 performance improvements and 3 performance regressions! Performance is the same for 612 metrics, 10 unstable metrics.

scenario:iastaspectsospath-ospathbasename_aspect

  • 🟥 execution_time [+86.677µs; +94.605µs] or [+20.442%; +22.312%]

scenario:span-start

  • 🟥 execution_time [+1.544ms; +1.683ms] or [+10.088%; +10.994%]

scenario:tracer-small

  • 🟥 execution_time [+31.167µs; +33.720µs] or [+8.179%; +8.849%]

@bm1549 bm1549 added the changelog/no-changelog A changelog entry is not required for this PR. label Jul 24, 2026
@bm1549
bm1549 force-pushed the brian.marks/otlp-export-startup-log branch from e09dd49 to 0025fca Compare July 24, 2026 21:30
@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Codeowners resolved as

ddtrace/internal/debug.py                                               @DataDog/apm-core-python
tests/integration/test_debug.py                                         @DataDog/apm-core-python

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Jul 24, 2026

Copy link
Copy Markdown

Circular import analysis

⚠️ Existing circular imports

There are 3 circular imports that already exist on the base branch and have not been changed by this PR.

ddtrace.trace -> ddtrace._trace.tracer -> ddtrace.internal.debug -> ddtrace.trace
ddtrace -> ddtrace.trace -> ddtrace._trace.tracer -> ddtrace.internal.debug -> ddtrace
ddtrace -> ddtrace.trace -> ddtrace._trace.tracer -> ddtrace.internal.debug -> ddtrace.internal.runtime.runtime_metrics -> ddtrace

Add three boolean fields to the tracer's startup diagnostic log
("DATADOG TRACER CONFIGURATION") indicating whether each telemetry
signal is exported over OTLP:

- otlp_traces_export_enabled: reflects agent_config.trace_otlp_export_enabled
  (opt-in via OTEL_TRACES_EXPORTER=otlp; export is routed through
  libdatadog's native OTLP trace exporter)
- otlp_metrics_export_enabled: reflects config._otel_metrics_enabled
- otlp_logs_export_enabled: reflects config._otel_logs_enabled

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bm1549
bm1549 force-pushed the brian.marks/otlp-export-startup-log branch from 0025fca to 8beb3e0 Compare July 25, 2026 02:40
gh-worker-dd-mergequeue-cf854d Bot pushed a commit that referenced this pull request Jul 27, 2026
## Description

When `DD_LOGS_OTEL_ENABLED=true`, the OTLP logs pipeline attaches an OpenTelemetry `LoggingHandler` to the Python root logger. ddtrace's own loggers (`ddtrace.*`) and the OpenTelemetry exporter's loggers (`opentelemetry.*`) propagate to root, so the handler captured the tracer's own log records: the per-export debug line and the exporter's export-failure warnings/errors. Exporting those records emits more log records, which were captured and exported again. The result is a self-amplifying export loop. This happens whenever those records reach the effective log level: with `DD_TRACE_DEBUG=true` (the per-export debug line), or on export failures (warnings/errors at the default level).

The fix attaches a self-telemetry exclusion filter to the OTLP `LoggingHandler` that drops records whose logger name is in the `ddtrace` or `opentelemetry` namespaces. Matching is exact-or-dotted-prefix (`ddtrace` / `ddtrace.*`, `opentelemetry` / `opentelemetry.*`), so application loggers such as `ddtrace_myapp` are not affected. The filter is attached only to the handler ddtrace itself installs; application-configured handlers are not modified. Application logs are still captured and exported.

This was discovered during cross-tracer startup-log work. It is an independent, pre-existing bug, so it ships on its own branch.

## Testing

Adds `tests/opentelemetry/test_logs.py::test_otel_logs_exporter_excludes_self_telemetry`. With `DD_LOGS_OTEL_ENABLED=true`, it emits a `ddtrace.*` record, an `opentelemetry.*` record, and an application record, flushes the exporter to a mock gRPC log service, and asserts the application record is exported while the two self-telemetry records are not. The test fails without the fix and passes with it. It runs across the OpenTelemetry versions already covered by the `opentelemetry` test venv.

## Risks

Low. The change only adds a logging filter to the handler ddtrace creates. Records from the `ddtrace` and `opentelemetry` logger namespaces are no longer exported through this pipeline; application logs are unchanged. The filter binds to the handler instance, so it persists across `logging.basicConfig` reconfiguration, which is the reconfiguration API the OpenTelemetry SDK patches to re-add the same handler instance (`dictConfig`/`fileConfig` are not patched by the SDK).

## Additional Notes

Includes a reno release note. No configuration or public API changes.

---
### Context
Independent, pre-existing bug surfaced while adding OTLP export-status fields to the tracer startup log across dd-trace-* (the Python system-test for the logs field hung on this loop). Related:
- Startup-log feature (dd-trace-py): #19265
- system-tests coverage that surfaced it: DataDog/system-tests#7376


Co-authored-by: brian.marks <brian.marks@datadoghq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos changelog/no-changelog A changelog entry is not required for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant