From ab690f1fea81b0aded1286a61d4c0ec14c070687 Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Thu, 9 Apr 2026 12:58:11 -0400 Subject: [PATCH 1/6] Add OTLP runtime metrics system test New scenario OTLP_RUNTIME_METRICS that sets DD_METRICS_OTEL_ENABLED=true alongside DD_RUNTIME_METRICS_ENABLED=true. Tests verify OTel-native metric names (dotnet.*, jvm.*, go.*, v8js.*) appear in OTLP payloads and that DD-proprietary names (runtime.dotnet.*, runtime.go.*) do not. All languages marked as missing_feature in manifests until POC PRs are merged: - .NET: DataDog/dd-trace-dotnet#8299 - Go: DataDog/dd-trace-go#4611 - Node.js: DataDog/dd-trace-js#7869 - Java: DataDog/dd-trace-java#10985 Co-Authored-By: Claude Opus 4.6 (1M context) --- manifests/cpp.yml | 3 + manifests/dotnet.yml | 3 + manifests/golang.yml | 3 + manifests/java.yml | 3 + manifests/nodejs.yml | 3 + manifests/php.yml | 3 + manifests/python.yml | 3 + manifests/ruby.yml | 3 + tests/test_otlp_runtime_metrics.py | 113 ++++++++++++++++++++++++++ utils/_context/_scenarios/__init__.py | 11 +++ 10 files changed, 148 insertions(+) create mode 100644 tests/test_otlp_runtime_metrics.py diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 71007d8c424..14d8f10eda3 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -312,3 +312,6 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) tests/test_telemetry.py::Test_Telemetry::test_telemetry_message_has_datadog_container_id: "irrelevant (cgroup in weblog is 0::/, so this test can't work)" tests/test_telemetry.py::Test_Telemetry::test_telemetry_message_required_headers: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index c1cbe2a901e..0cff39a0e45 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -1196,3 +1196,6 @@ manifest: excluded_weblog: [uds, poc] tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (Re-enable when this automatically updates the dd-go files.) tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/golang.yml b/manifests/golang.yml index 15781f0d552..1b9b5e9feae 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1523,3 +1523,6 @@ manifest: net-http-orchestrion: '>=2.5.0' tests/test_v1_payloads.py::Test_V1PayloadByDefault: missing_feature (not implemented by default yet) tests/test_v1_payloads.py::Test_V1Payloads: v2.7.0 + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/java.yml b/manifests/java.yml index c16aff72818..0ea62e3a899 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -4371,3 +4371,6 @@ manifest: tests/test_the_test/test_json_report.py::Test_Mock: v0.2.1 tests/test_the_test/test_json_report.py::Test_NotReleased: missing_feature tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 9802fcaabc3..66ca278bb95 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2502,3 +2502,6 @@ manifest: tests/test_telemetry.py::Test_TelemetryV2: *ref_4_21_0 tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (This test causes too many friction. It has been replaced by alerts on slack channels) tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/php.yml b/manifests/php.yml index a793b55f53d..2e79c0a597c 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -1477,3 +1477,6 @@ manifest: tests/test_telemetry.py::Test_TelemetryV2::test_app_started_product_info: missing_feature (Product started missing (both in libdatadog and php)) tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (This test causes too many friction. It has been replaced by alerts on slack channels) tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index ed068eaa119..80d0d20392a 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -2372,3 +2372,6 @@ manifest: - declaration: missing_feature (Product started missing in app-started payload) excluded_weblog: [tornado, django-py3.13, fastapi, flask-poc, django-poc, python3.12, uds-flask, uwsgi-poc] tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 144872bdde7..f9dbe4db67a 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -2286,3 +2286,6 @@ manifest: - declaration: missing_feature (dd-client-library-version missing) component_version: <1.22.0 tests/test_v1_payloads.py: missing_feature + + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/tests/test_otlp_runtime_metrics.py b/tests/test_otlp_runtime_metrics.py new file mode 100644 index 00000000000..6da4fa32b44 --- /dev/null +++ b/tests/test_otlp_runtime_metrics.py @@ -0,0 +1,113 @@ +""" +Test that runtime metrics are exported via OTLP using OTel semantic convention names. + +When DD_RUNTIME_METRICS_ENABLED=true and DD_METRICS_OTEL_ENABLED=true, dd-trace-* +libraries should send runtime metrics via OTLP with OTel-native naming (dotnet.*, +jvm.*, go.*, v8js.*, etc.) instead of DD-proprietary naming (runtime.dotnet.*, +runtime.go.*, runtime.node.*, etc.). + +Related PRs: +- .NET: https://github.com/DataDog/dd-trace-dotnet/pull/8299 +- Go: https://github.com/DataDog/dd-trace-go/pull/4611 +- Node.js: https://github.com/DataDog/dd-trace-js/pull/7869 +- Java: https://github.com/DataDog/dd-trace-java/pull/10985 +""" + +from utils import context, features, interfaces, scenarios, weblog + + +# Specific OTel metric names that MUST be present per language +EXPECTED_METRICS = { + "dotnet": [ + "dotnet.gc.collections", + "dotnet.process.memory.working_set", + "dotnet.process.cpu.time", + ], + "golang": [ + "go.goroutine.count", + "go.memory.used", + "go.processor.limit", + ], + "nodejs": [ + "v8js.memory.heap.used", + "process.memory.usage", + ], + "java": [ + "jvm.memory.used", + "jvm.thread.count", + "jvm.cpu.count", + ], +} + + +def get_otlp_metric_names(): + """Extract all metric names from OTLP metric payloads captured by the proxy.""" + metric_names = set() + for data in interfaces.open_telemetry.get_data(path_filters="/v1/metrics"): + content = data.get("request", {}).get("content", {}) + for resource_metrics in content.get("resourceMetrics", []): + for scope_metrics in resource_metrics.get("scopeMetrics", []): + for metric in scope_metrics.get("metrics", []): + name = metric.get("name") + if name: + metric_names.add(name) + return metric_names + + +@scenarios.otlp_runtime_metrics +@features.runtime_metrics +class Test_OtlpRuntimeMetrics: + """Verify runtime metrics are sent via OTLP with OTel semantic convention names.""" + + def setup_main(self): + self.req = weblog.get("/") + + def test_main(self): + assert self.req.status_code == 200 + + library = context.library.name + if library not in EXPECTED_METRICS: + return + + metric_names = get_otlp_metric_names() + + expected = EXPECTED_METRICS[library] + for expected_name in expected: + assert expected_name in metric_names, ( + f"Expected OTel runtime metric '{expected_name}' not found for {library}. " + f"Got metrics: {sorted(metric_names)}" + ) + + +@scenarios.otlp_runtime_metrics +@features.runtime_metrics +class Test_OtlpRuntimeMetrics_NoDD_Names: + """Verify OTLP runtime metrics use OTel names, not DD-proprietary names.""" + + def setup_main(self): + self.req = weblog.get("/") + + def test_main(self): + assert self.req.status_code == 200 + + library = context.library.name + if library not in EXPECTED_METRICS: + return + + metric_names = get_otlp_metric_names() + + # DD-proprietary prefixes should NOT appear in OTLP payloads + dd_prefixes = { + "dotnet": "runtime.dotnet.", + "golang": "runtime.go.", + "nodejs": "runtime.node.", + "java": "jvm.heap_memory", # DD uses flat names like jvm.heap_memory + } + + dd_prefix = dd_prefixes.get(library) + if dd_prefix: + dd_named_metrics = [n for n in metric_names if n.startswith(dd_prefix)] + assert len(dd_named_metrics) == 0, ( + f"Found DD-proprietary metric names in OTLP payload for {library}: " + f"{dd_named_metrics}. Expected OTel-native names only." + ) diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index 20a17caca84..86313444db2 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -1154,6 +1154,17 @@ class _Scenarios: doc="Test runtime metrics", ) + otlp_runtime_metrics = EndToEndScenario( + "OTLP_RUNTIME_METRICS", + weblog_env={ + "DD_METRICS_OTEL_ENABLED": "true", + "DD_DOGSTATSD_START_DELAY": "0", + }, + runtime_metrics_enabled=True, + library_interface_timeout=20, + doc="Test runtime metrics exported via OTLP with OTel semantic convention names", + ) + # Appsec Lambda Scenarios appsec_lambda_default = LambdaScenario( "APPSEC_LAMBDA_DEFAULT", From f2a05f6e7de41bbc435bbe3c28917a3ce10adbea Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Thu, 9 Apr 2026 13:12:50 -0400 Subject: [PATCH 2/6] Fix OTLP runtime metrics scenario config - Remove DD_DOGSTATSD_START_DELAY (not using StatsD) - Add OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf - Route OTLP metrics to proxy for capture via OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://proxy:8127/v1/metrics - Keep runtime_metrics_enabled=True (sets DD_RUNTIME_METRICS_ENABLED=true) - DD_METRICS_OTEL_ENABLED=true enables the OTLP path in the tracer Co-Authored-By: Claude Opus 4.6 (1M context) --- utils/_context/_scenarios/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index 86313444db2..8bcb3781731 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -1158,7 +1158,8 @@ class _Scenarios: "OTLP_RUNTIME_METRICS", weblog_env={ "DD_METRICS_OTEL_ENABLED": "true", - "DD_DOGSTATSD_START_DELAY": "0", + "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", + "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": f"http://proxy:{ProxyPorts.open_telemetry_weblog}/v1/metrics", }, runtime_metrics_enabled=True, library_interface_timeout=20, From c97b7a2805ea454e3462e6f0f26578092571c316 Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Tue, 14 Apr 2026 12:45:23 -0400 Subject: [PATCH 3/6] Assert full OTLP runtime metric set per language Expand EXPECTED_METRICS from a spot-check subset to the complete instrument lists from each tracer's implementation: 19 dotnet.*, 8 go.*, 13 nodejs/v8js/process.*, 18 jvm.*. Made-with: Cursor --- tests/test_otlp_runtime_metrics.py | 56 +++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/tests/test_otlp_runtime_metrics.py b/tests/test_otlp_runtime_metrics.py index 6da4fa32b44..6a44695fbe4 100644 --- a/tests/test_otlp_runtime_metrics.py +++ b/tests/test_otlp_runtime_metrics.py @@ -16,26 +16,74 @@ from utils import context, features, interfaces, scenarios, weblog -# Specific OTel metric names that MUST be present per language +# All OTel semconv metric names that MUST be present per language. +# These are the complete instrument sets from each tracer's OTLP runtime metrics implementation. EXPECTED_METRICS = { "dotnet": [ + "dotnet.assembly.count", + "dotnet.exceptions", "dotnet.gc.collections", - "dotnet.process.memory.working_set", + "dotnet.gc.heap.total_allocated", + "dotnet.gc.last_collection.heap.fragmentation.size", + "dotnet.gc.last_collection.heap.size", + "dotnet.gc.last_collection.memory.committed_size", + "dotnet.gc.pause.time", + "dotnet.jit.compilation.time", + "dotnet.jit.compiled_il.size", + "dotnet.jit.compiled_methods", + "dotnet.monitor.lock_contentions", + "dotnet.process.cpu.count", "dotnet.process.cpu.time", + "dotnet.process.memory.working_set", + "dotnet.thread_pool.queue.length", + "dotnet.thread_pool.thread.count", + "dotnet.thread_pool.work_item.count", + "dotnet.timer.count", ], "golang": [ + "go.config.gogc", "go.goroutine.count", + "go.memory.allocated", + "go.memory.allocations", + "go.memory.gc.goal", + "go.memory.limit", "go.memory.used", "go.processor.limit", ], "nodejs": [ - "v8js.memory.heap.used", + "nodejs.eventloop.delay.max", + "nodejs.eventloop.delay.mean", + "nodejs.eventloop.delay.min", + "nodejs.eventloop.delay.p50", + "nodejs.eventloop.delay.p90", + "nodejs.eventloop.delay.p99", + "nodejs.eventloop.utilization", + "process.cpu.utilization", "process.memory.usage", + "v8js.memory.heap.limit", + "v8js.memory.heap.space.available_size", + "v8js.memory.heap.space.physical_size", + "v8js.memory.heap.used", ], "java": [ + "jvm.buffer.count", + "jvm.buffer.memory.limit", + "jvm.buffer.memory.used", + "jvm.class.count", + "jvm.class.loaded", + "jvm.class.unloaded", + "jvm.cpu.count", + "jvm.cpu.recent_utilization", + "jvm.cpu.time", + "jvm.file_descriptor.count", + "jvm.file_descriptor.limit", + "jvm.memory.committed", + "jvm.memory.init", + "jvm.memory.limit", "jvm.memory.used", + "jvm.memory.used_after_last_gc", + "jvm.system.cpu.utilization", "jvm.thread.count", - "jvm.cpu.count", ], } From 039d4172e508c31a643188390c0e6bef49af4c50 Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Wed, 15 Apr 2026 13:46:16 -0400 Subject: [PATCH 4/6] Fix OTLP runtime metrics test to use agent interface and standard proxy routing - Route OTLP metrics through agent via dd-otlp-path=agent header (matches otel_integrations pattern) - Read metrics from interfaces.agent.get_metrics() (matches existing RUNTIME_METRICS_ENABLED test) - Merge positive/negative test into single class - Enable for dotnet v3.42.0 Co-Authored-By: Claude Opus 4.6 (1M context) --- manifests/dotnet.yml | 3 +- tests/test_otlp_runtime_metrics.py | 62 ++++++++++----------------- utils/_context/_scenarios/__init__.py | 1 + 3 files changed, 24 insertions(+), 42 deletions(-) diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 0cff39a0e45..68226c1fab3 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -1197,5 +1197,4 @@ manifest: tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (Re-enable when this automatically updates the dd-go files.) tests/test_v1_payloads.py: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: v3.42.0 diff --git a/tests/test_otlp_runtime_metrics.py b/tests/test_otlp_runtime_metrics.py index 6a44695fbe4..12cc1c543ea 100644 --- a/tests/test_otlp_runtime_metrics.py +++ b/tests/test_otlp_runtime_metrics.py @@ -87,25 +87,31 @@ ], } +# DD-proprietary prefixes that should NOT appear when OTLP metrics are active +DD_PROPRIETARY_PREFIXES = { + "dotnet": "runtime.dotnet.", + "golang": "runtime.go.", + "nodejs": "runtime.node.", + "java": "jvm.heap_memory", +} + + +def get_runtime_metric_names(): + """Extract runtime metric names from the agent interface (agent -> backend series). -def get_otlp_metric_names(): - """Extract all metric names from OTLP metric payloads captured by the proxy.""" + Uses interfaces.agent.get_metrics() — the same approach as + Test_Config_RuntimeMetrics_Enabled in test_config_consistency.py. + """ metric_names = set() - for data in interfaces.open_telemetry.get_data(path_filters="/v1/metrics"): - content = data.get("request", {}).get("content", {}) - for resource_metrics in content.get("resourceMetrics", []): - for scope_metrics in resource_metrics.get("scopeMetrics", []): - for metric in scope_metrics.get("metrics", []): - name = metric.get("name") - if name: - metric_names.add(name) + for _, metric in interfaces.agent.get_metrics(): + metric_names.add(metric["metric"]) return metric_names @scenarios.otlp_runtime_metrics @features.runtime_metrics class Test_OtlpRuntimeMetrics: - """Verify runtime metrics are sent via OTLP with OTel semantic convention names.""" + """Verify runtime metrics are sent via OTLP with OTel names, not DD-proprietary names.""" def setup_main(self): self.req = weblog.get("/") @@ -117,8 +123,9 @@ def test_main(self): if library not in EXPECTED_METRICS: return - metric_names = get_otlp_metric_names() + metric_names = get_runtime_metric_names() + # All expected OTel-named metrics must be present expected = EXPECTED_METRICS[library] for expected_name in expected: assert expected_name in metric_names, ( @@ -126,36 +133,11 @@ def test_main(self): f"Got metrics: {sorted(metric_names)}" ) - -@scenarios.otlp_runtime_metrics -@features.runtime_metrics -class Test_OtlpRuntimeMetrics_NoDD_Names: - """Verify OTLP runtime metrics use OTel names, not DD-proprietary names.""" - - def setup_main(self): - self.req = weblog.get("/") - - def test_main(self): - assert self.req.status_code == 200 - - library = context.library.name - if library not in EXPECTED_METRICS: - return - - metric_names = get_otlp_metric_names() - - # DD-proprietary prefixes should NOT appear in OTLP payloads - dd_prefixes = { - "dotnet": "runtime.dotnet.", - "golang": "runtime.go.", - "nodejs": "runtime.node.", - "java": "jvm.heap_memory", # DD uses flat names like jvm.heap_memory - } - - dd_prefix = dd_prefixes.get(library) + # DD-proprietary names must NOT be present + dd_prefix = DD_PROPRIETARY_PREFIXES.get(library) if dd_prefix: dd_named_metrics = [n for n in metric_names if n.startswith(dd_prefix)] assert len(dd_named_metrics) == 0, ( - f"Found DD-proprietary metric names in OTLP payload for {library}: " + f"Found DD-proprietary metric names for {library}: " f"{dd_named_metrics}. Expected OTel-native names only." ) diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index 8bcb3781731..34298f8e0d6 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -1160,6 +1160,7 @@ class _Scenarios: "DD_METRICS_OTEL_ENABLED": "true", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": f"http://proxy:{ProxyPorts.open_telemetry_weblog}/v1/metrics", + "OTEL_EXPORTER_OTLP_METRICS_HEADERS": "dd-protocol=otlp,dd-otlp-path=agent", }, runtime_metrics_enabled=True, library_interface_timeout=20, From 51be9ee55e0fb6b38cc00da4094c4f663211bdf2 Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Wed, 15 Apr 2026 15:06:47 -0400 Subject: [PATCH 5/6] Fix manifest ordering and remove deleted test class references - Remove Test_OtlpRuntimeMetrics_NoDD_Names from all manifests (merged into single test) - Move test_otlp_runtime_metrics entries to correct alphabetical position - Apply ruff formatting from format.sh Co-Authored-By: Claude Opus 4.6 (1M context) --- manifests/cpp.yml | 4 +--- manifests/dotnet.yml | 3 +-- manifests/golang.yml | 4 +--- manifests/java.yml | 4 +--- manifests/nodejs.yml | 4 +--- manifests/php.yml | 4 +--- manifests/python.yml | 4 +--- manifests/ruby.yml | 4 +--- tests/test_otlp_runtime_metrics.py | 6 ++---- 9 files changed, 10 insertions(+), 27 deletions(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 14d8f10eda3..31f8eae501e 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -310,8 +310,6 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_telemetry.py::Test_Telemetry::test_telemetry_message_has_datadog_container_id: "irrelevant (cgroup in weblog is 0::/, so this test can't work)" tests/test_telemetry.py::Test_Telemetry::test_telemetry_message_required_headers: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 8f26ee0e994..080aa0b7efe 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -1122,6 +1122,7 @@ manifest: tests/test_library_conf.py::Test_HeaderTags_Wildcard_Response_Headers: missing_feature tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: v3.42.0 tests/test_profiling.py::Test_Profile: - weblog_declaration: "*": v1.0 # real version not known @@ -1199,5 +1200,3 @@ manifest: excluded_weblog: [uds, poc] tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (Re-enable when this automatically updates the dd-go files.) tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: v3.42.0 diff --git a/manifests/golang.yml b/manifests/golang.yml index adf232d7a00..1c2d21def0c 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1391,6 +1391,7 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile::test_process_tags_svc: missing_feature tests/test_protobuf.py: missing_feature tests/test_resource_renaming.py: @@ -1546,6 +1547,3 @@ manifest: net-http-orchestrion: '>=2.5.0' tests/test_v1_payloads.py::Test_V1PayloadByDefault: missing_feature (not implemented by default yet) tests/test_v1_payloads.py::Test_V1Payloads: v2.7.0 - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/java.yml b/manifests/java.yml index 3fc13e0d466..5fc8ce482ff 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -4193,6 +4193,7 @@ manifest: akka-http: irrelevant (integration injects Date header after bytecode injection occurs) play: irrelevant (integration injects Date header after bytecode injection occurs) tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile: - weblog_declaration: akka-http: v1.22.0 @@ -4424,6 +4425,3 @@ manifest: tests/test_the_test/test_json_report.py::Test_Mock: v0.2.1 tests/test_the_test/test_json_report.py::Test_NotReleased: missing_feature tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index cbe70a94700..59f3078677e 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2306,6 +2306,7 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile: *ref_5_16_0 tests/test_profiling.py::Test_Profile::test_process_tags: missing_feature tests/test_profiling.py::Test_Profile::test_process_tags_svc: missing_feature @@ -2529,6 +2530,3 @@ manifest: tests/test_telemetry.py::Test_TelemetryV2: *ref_4_21_0 tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (This test causes too many friction. It has been replaced by alerts on slack channels) tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/php.yml b/manifests/php.yml index 5b314f87fb5..6500636acf4 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -990,6 +990,7 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile: - declaration: missing_feature (profiling seems not to be activated) component_version: <1.16.0 @@ -1484,6 +1485,3 @@ manifest: tests/test_telemetry.py::Test_TelemetryV2::test_app_started_product_info: missing_feature (Product started missing (both in libdatadog and php)) tests/test_telemetry.py::Test_TelemetryV2::test_config_telemetry_completeness: irrelevant (This test causes too many friction. It has been replaced by alerts on slack channels) tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index 34f286acb79..5b6a96c84a6 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -2148,6 +2148,7 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile: - weblog_declaration: "*": v0.1 # actual version unknown @@ -2375,6 +2376,3 @@ manifest: - declaration: missing_feature (Product started missing in app-started payload) excluded_weblog: [tornado, django-py3.13, fastapi, flask-poc, django-poc, python3.12, uds-flask, uwsgi-poc] tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/manifests/ruby.yml b/manifests/ruby.yml index dfd00d4b521..e773622168f 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -1928,6 +1928,7 @@ manifest: tests/test_library_logs.py::Test_NoExceptions::test_dotnet: irrelevant (only for .NET) tests/test_library_logs.py::Test_NoExceptions::test_java_logs: irrelevant (only for Java) tests/test_library_logs.py::Test_NoExceptions::test_java_telemetry_logs: irrelevant (only for Java) + tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature tests/test_profiling.py::Test_Profile: # Modified by easy win activation script - declaration: missing_feature (temporary fix, scenario not working on dd-trace-rb CI) component_version: <2.24.0 @@ -2318,6 +2319,3 @@ manifest: - declaration: missing_feature (dd-client-library-version missing) component_version: <1.22.0 tests/test_v1_payloads.py: missing_feature - - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics: missing_feature - tests/test_otlp_runtime_metrics.py::Test_OtlpRuntimeMetrics_NoDD_Names: missing_feature diff --git a/tests/test_otlp_runtime_metrics.py b/tests/test_otlp_runtime_metrics.py index 12cc1c543ea..31119234394 100644 --- a/tests/test_otlp_runtime_metrics.py +++ b/tests/test_otlp_runtime_metrics.py @@ -1,5 +1,4 @@ -""" -Test that runtime metrics are exported via OTLP using OTel semantic convention names. +"""Test that runtime metrics are exported via OTLP using OTel semantic convention names. When DD_RUNTIME_METRICS_ENABLED=true and DD_METRICS_OTEL_ENABLED=true, dd-trace-* libraries should send runtime metrics via OTLP with OTel-native naming (dotnet.*, @@ -138,6 +137,5 @@ def test_main(self): if dd_prefix: dd_named_metrics = [n for n in metric_names if n.startswith(dd_prefix)] assert len(dd_named_metrics) == 0, ( - f"Found DD-proprietary metric names for {library}: " - f"{dd_named_metrics}. Expected OTel-native names only." + f"Found DD-proprietary metric names for {library}: {dd_named_metrics}. Expected OTel-native names only." ) From a56868c7eb822bc45fd5ce901a32d5c6f701d422 Mon Sep 17 00:00:00 2001 From: Maximo Bautista Date: Mon, 20 Apr 2026 10:24:28 -0400 Subject: [PATCH 6/6] Add OTLP_RUNTIME_METRICS scenario to CI workflow Register the new scenario in the GitHub Actions end-to-end workflow and the CI orchestrator scenario list. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/run-end-to-end.yml | 3 +++ utils/scripts/ci_orchestrators/workflow_data.py | 1 + 2 files changed, 4 insertions(+) diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 8ff38f3e45a..168ea6f06ff 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -255,6 +255,9 @@ jobs: - name: Run LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID"') run: ./run.sh LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID + - name: Run OTLP_RUNTIME_METRICS scenario + if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTLP_RUNTIME_METRICS"') + run: ./run.sh OTLP_RUNTIME_METRICS - name: Run RUNTIME_METRICS_ENABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"RUNTIME_METRICS_ENABLED"') run: ./run.sh RUNTIME_METRICS_ENABLED diff --git a/utils/scripts/ci_orchestrators/workflow_data.py b/utils/scripts/ci_orchestrators/workflow_data.py index 99d8296f2dd..e93fb6e146b 100644 --- a/utils/scripts/ci_orchestrators/workflow_data.py +++ b/utils/scripts/ci_orchestrators/workflow_data.py @@ -635,6 +635,7 @@ def _is_supported(library: str, weblog: str, scenario: str, _ci_environment: str "IPV6", "LIBRARY_CONF_CUSTOM_HEADER_TAGS", "LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID", + "OTLP_RUNTIME_METRICS", "PERFORMANCES", "PROFILING", "REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD",