Skip to content

Conversation

@rachelyangdog
Copy link
Contributor

@rachelyangdog rachelyangdog commented Nov 13, 2025

Description

  • Adds support for OpenTelemetry Metrics integration with Datadog.

Changes:

  • Added new configurations DD_METRICS_OTEL_ENABLED (enable OTel metrics support) and DD_HOSTNAME
  • Added OTel endpoint configuration according to the OTel Metrics RFC
  • Sets default metrics temporality to "delta" (according to RFC
  • Added auto configuring of OTLP endpoints using DD_TRACE_AGENT_URL and/or DD_AGENT_HOST
  • Added gRPC and HTTP protocol and port selection
  • Added resource attribute mapping
  • Added functions to support collection of telemetry metrics for configuration (actual implementation will be added in a separate PR)

Please refer to this document containing known discrepancies of the PHP OTel Metrics implementation

Reviewer checklist

  • Test coverage seems ok.
  • Appropriate labels assigned.

@rachelyangdog rachelyangdog requested review from a team as code owners November 13, 2025 20:56
@rachelyangdog rachelyangdog marked this pull request as draft November 13, 2025 20:56
@rachelyangdog rachelyangdog requested a review from bwoebi November 13, 2025 20:56
@codecov-commenter
Copy link

codecov-commenter commented Nov 13, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.65%. Comparing base (14dc0a4) to head (0670208).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3487      +/-   ##
==========================================
- Coverage   61.73%   61.65%   -0.08%     
==========================================
  Files         143      143              
  Lines       13015    13015              
  Branches     1702     1702              
==========================================
- Hits         8035     8025      -10     
- Misses       4221     4228       +7     
- Partials      759      762       +3     

see 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 14dc0a4...0670208. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rachelyangdog rachelyangdog changed the title WIP: otel metrics telemetry feat: support OpenTelemetry Metrics Nov 17, 2025
@rachelyangdog rachelyangdog marked this pull request as ready for review November 17, 2025 16:46
@pr-commenter
Copy link

pr-commenter bot commented Nov 17, 2025

Benchmarks [ tracer ]

Benchmark execution time: 2025-12-15 21:08:34

Comparing candidate commit 0670208 in PR branch rachel.yang/otel-metrics-part2-telemetry with baseline commit 14dc0a4 in branch master.

Found 4 performance improvements and 15 performance regressions! Performance is the same for 175 metrics, 0 unstable metrics.

scenario:ComposerTelemetryBench/benchTelemetryParsing-opcache

  • 🟥 execution_time [+0.498µs; +1.702µs] or [+3.888%; +13.299%]

scenario:ContextPropagationBench/benchExtractHeaders128Bit-opcache

  • 🟥 execution_time [+787.688ns; +820.312ns] or [+90.400%; +94.145%]

scenario:ContextPropagationBench/benchExtractTraceContext64Bit-opcache

  • 🟥 execution_time [+837.449ns; +920.551ns] or [+95.490%; +104.966%]

scenario:ContextPropagationBench/benchInject128Bit-opcache

  • 🟥 execution_time [+749.412ns; +810.588ns] or [+44.555%; +48.192%]

scenario:HookBench/benchWithoutHook-opcache

  • 🟩 execution_time [-5.680µs; -4.900µs] or [-10.207%; -8.807%]

scenario:LogsInjectionBench/benchLogsNullBaseline-opcache

  • 🟩 execution_time [-1.318µs; -1.116µs] or [-6.006%; -5.089%]

scenario:LogsInjectionBench/benchLogsNullInjection-opcache

  • 🟩 execution_time [-1.250µs; -1.140µs] or [-5.717%; -5.213%]

scenario:MessagePackSerializationBench/benchMessagePackSerialization

  • 🟥 execution_time [+4.299µs; +5.381µs] or [+4.179%; +5.230%]

scenario:MessagePackSerializationBench/benchMessagePackSerialization-opcache

  • 🟥 execution_time [+8.812µs; +11.328µs] or [+8.402%; +10.801%]

scenario:SamplingRuleMatchingBench/benchRegexMatching1

  • 🟥 execution_time [+102.282ns; +135.318ns] or [+8.937%; +11.823%]

scenario:SamplingRuleMatchingBench/benchRegexMatching2

  • 🟥 execution_time [+83.559ns; +126.841ns] or [+7.182%; +10.903%]

scenario:SamplingRuleMatchingBench/benchRegexMatching3

  • 🟥 execution_time [+82.083ns; +133.917ns] or [+7.084%; +11.557%]

scenario:SamplingRuleMatchingBench/benchRegexMatching4

  • 🟥 execution_time [+104.623ns; +153.177ns] or [+9.083%; +13.299%]

scenario:SpanBench/benchOpenTelemetryAPI

  • 🟥 mem_peak [+1.773MB; +1.778MB] or [+4.293%; +4.305%]

scenario:SpanBench/benchOpenTelemetryAPI-opcache

  • 🟥 mem_peak [+1.747MB; +1.750MB] or [+4.543%; +4.551%]

scenario:TraceSerializationBench/benchSerializeTrace

  • 🟩 execution_time [-30.487µs; -12.813µs] or [-6.817%; -2.865%]

scenario:WordPressBench/benchWordPressBaseline-opcache

  • 🟥 mem_peak [+150.424KB; +150.424KB] or [+3.137%; +3.137%]

scenario:WordPressBench/benchWordPressDdprof-opcache

  • 🟥 mem_peak [+150.424KB; +150.424KB] or [+3.137%; +3.137%]

scenario:WordPressBench/benchWordPressOverhead-opcache

  • 🟥 mem_peak [+150.424KB; +150.424KB] or [+3.137%; +3.137%]

@PROFeNoM
Copy link
Contributor

PROFeNoM commented Dec 9, 2025

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ 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".

Comment on lines 12 to 14
if (\dd_trace_env_config('DD_TRACE_REPORT_HOSTNAME')) {
$attributes['host.name'] = \dd_trace_env_config('DD_HOSTNAME');
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overriding host.name with empty DD_HOSTNAME

When DD_TRACE_REPORT_HOSTNAME is true but DD_HOSTNAME is unset, this hook always adds a host.name attribute with an empty string before calling ResourceInfo::merge. In OpenTelemetry, merge gives precedence to the attributes of the resource being merged in, so this empty value will overwrite the hostname the upstream Host detector already populated. The result is that OTel metrics exported with hostname reporting enabled lose the actual hostname and carry a blank host.name. Skip setting the attribute when DD_HOSTNAME is empty or fall back to the detected hostname to avoid clobbering the original value.

Useful? React with 👍 / 👎.

Comment on lines +2864 to +2872
} else if (params_count == 3 && FUNCTION_NAME_MATCHES("track_telemetry_metrics")) {
zval *metric_name = ZVAL_VARARG_PARAM(params, 0);
zval *metric_value = ZVAL_VARARG_PARAM(params, 1);
zval *tags = ZVAL_VARARG_PARAM(params, 2);
if (Z_TYPE_P(metric_name) == IS_STRING && Z_TYPE_P(tags) == IS_STRING) {
ddtrace_metric_register_buffer(Z_STR_P(metric_name), DDOG_METRIC_TYPE_COUNT, DDOG_METRIC_NAMESPACE_TRACERS);
ddtrace_metric_add_point(Z_STR_P(metric_name), zval_get_double(metric_value), Z_STR_P(tags));
RETVAL_TRUE;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Major)
I believe we should type-validate metric_value here, just as we did for metric_name and tags, because currently we are calling zval_get_double(metric_value) without verifying it's numeric.

This may or may not cause a crash if someone passes a non-numeric vakue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bob just told me that "zval_get_double() is infallible and always safe to use", so perhaps I made you do this change for nothing, oops 😬

Copy link
Contributor

@PROFeNoM PROFeNoM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! :shipit: Just one or two little things and its good to go for me 👍

Comment on lines +2864 to +2872
} else if (params_count == 3 && FUNCTION_NAME_MATCHES("track_telemetry_metrics")) {
zval *metric_name = ZVAL_VARARG_PARAM(params, 0);
zval *metric_value = ZVAL_VARARG_PARAM(params, 1);
zval *tags = ZVAL_VARARG_PARAM(params, 2);
if (Z_TYPE_P(metric_name) == IS_STRING && Z_TYPE_P(tags) == IS_STRING) {
ddtrace_metric_register_buffer(Z_STR_P(metric_name), DDOG_METRIC_TYPE_COUNT, DDOG_METRIC_NAMESPACE_TRACERS);
ddtrace_metric_add_point(Z_STR_P(metric_name), zval_get_double(metric_value), Z_STR_P(tags));
RETVAL_TRUE;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bob just told me that "zval_get_double() is infallible and always safe to use", so perhaps I made you do this change for nothing, oops 😬

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.

4 participants