From 1f1fec115b80c4413c9a0542556bd3bfa2182cb7 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 13:40:20 -0400 Subject: [PATCH 01/10] feat(cpp): enable stable config origin telemetry tests Add cpp entries to telemetry_name_mapping for non-native stable config keys (DD_LOGS_INJECTION, DD_PROFILING_ENABLED, DD_DYNAMIC_INSTRUMENTATION_ENABLED, DD_TRACE_DEBUG, DD_RUNTIME_METRICS_ENABLED, DD_DATA_STREAMS_ENABLED, DD_TAGS, DD_TRACE_PROPAGATION_STYLE). Remove the missing_feature manifest entries for Test_Stable_Configuration_Origin since dd-trace-cpp now reports these configs in telemetry. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- manifests/cpp.yml | 5 ----- tests/parametric/test_telemetry.py | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index f9bc4141c20..cb3c4e14e20 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,11 +266,6 @@ manifest: tests/parametric/test_telemetry.py::Test_Consistent_Configs: missing_feature tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) - tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case - : missing_feature (extended configs are not supported) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case - : missing_feature (extended configs are not supported) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: ">1.0.0" tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: '>=2.0.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar::test_telemetry_sca_enabled_propagated: missing_feature # Created by easy win activation script diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index 8c3537d997e..d9d6632f161 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -47,6 +47,7 @@ "ruby": "DD_LOGS_INJECTION", "golang": ["DD_LOGS_INJECTION", "trace.logs_enabled"], "java": "DD_LOGS_INJECTION_ENABLED", + "cpp": "DD_LOGS_INJECTION", }, "trace_header_tags": { "dotnet": "DD_TRACE_HEADER_TAGS", @@ -79,6 +80,7 @@ "ruby": "DD_PROFILING_ENABLED", "golang": ["DD_PROFILING_ENABLED", "profiling_enabled"], "java": "DD_PROFILING_ENABLED", + "cpp": "DD_PROFILING_ENABLED", }, "appsec_enabled": { "dotnet": "DD_APPSEC_ENABLED", @@ -95,6 +97,7 @@ "java": "DD_DATA_STREAMS_ENABLED", "golang": ["DD_DATA_STREAMS_ENABLED", "data_streams_enabled"], "ruby": "DD_DATA_STREAMS_ENABLED", + "cpp": "DD_DATA_STREAMS_ENABLED", }, "runtime_metrics_enabled": { "java": "DD_RUNTIME_METRICS_ENABLED", @@ -103,6 +106,7 @@ "python": "DD_RUNTIME_METRICS_ENABLED", "ruby": "DD_RUNTIME_METRICS_ENABLED", "golang": ["DD_RUNTIME_METRICS_ENABLED", "runtime_metrics_enabled"], + "cpp": "DD_RUNTIME_METRICS_ENABLED", }, "dynamic_instrumentation_enabled": { "java": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", @@ -112,6 +116,7 @@ "php": "dynamic_instrumentation.enabled", "ruby": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", "golang": ["DD_DYNAMIC_INSTRUMENTATION_ENABLED", "dynamic_instrumentation_enabled"], + "cpp": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", }, "trace_debug_enabled": { "php": "trace.debug", @@ -119,6 +124,7 @@ "ruby": "DD_TRACE_DEBUG", "python": "DD_TRACE_DEBUG", "golang": ["trace_debug_enabled", "DD_TRACE_DEBUG"], + "cpp": "DD_TRACE_DEBUG", }, "tags": { "java": "DD_TRACE_TAGS", @@ -127,6 +133,7 @@ "nodejs": "DD_TAGS", "golang": ["DD_TAGS", "trace_tags"], "ruby": "DD_TAGS", + "cpp": "DD_TAGS", }, "trace_propagation_style": { "java": "DD_TRACE_PROPAGATION_STYLE", @@ -134,6 +141,7 @@ "php": "trace.propagation_style", "golang": ["DD_TRACE_PROPAGATION_STYLE", "trace.propagation_style"], "ruby": "DD_TRACE_PROPAGATION_STYLE", + "cpp": "DD_TRACE_PROPAGATION_STYLE", }, } From 45fc9fbafe14d42f13d015d3128aafc5fac208af Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 13:59:53 -0400 Subject: [PATCH 02/10] fix(cpp): skip SDK_DEFAULT_STABLE_CONFIG for C++ tracer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C++ doesn't natively support profiling, runtime metrics, data streams, or logs injection — it should not be expected to report default values for these products. Empty the default config dict for C++. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- tests/parametric/test_config_consistency.py | 44 +++++++++++---------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/tests/parametric/test_config_consistency.py b/tests/parametric/test_config_consistency.py index 983fbaa4465..3b6c120e42a 100644 --- a/tests/parametric/test_config_consistency.py +++ b/tests/parametric/test_config_consistency.py @@ -377,26 +377,30 @@ def test_dogstatsd_custom_port(self, test_library: APMLibrary): assert resp["dd_dogstatsd_port"] == "8150" -SDK_DEFAULT_STABLE_CONFIG = { - "dd_runtime_metrics_enabled": "false" if context.library not in ("java", "dotnet") else "true", - "dd_profiling_enabled": "1" - if context.library == "php" - else "true" - if context.library == "golang" - else "false", # Profiling is enabled as "1" by default in PHP if loaded. As for Go, the profiler must be started manually, so it is enabled by default when started - "dd_data_streams_enabled": "false" - if context.library != "dotnet" - else "true", # Data streams is now enabled by default in non-serverless environments in dotnet - "dd_logs_injection": { - "dotnet": "true", - "ruby": "true", - "java": "true", - "golang": None, - "python": "true", - "nodejs": "true", - "php": "true", - }.get(context.library.name, "false"), # Enabled by default in ruby -} +SDK_DEFAULT_STABLE_CONFIG = ( + {} + if context.library == "cpp" + else { + "dd_runtime_metrics_enabled": "false" if context.library not in ("java", "dotnet") else "true", + "dd_profiling_enabled": "1" + if context.library == "php" + else "true" + if context.library == "golang" + else "false", # Profiling is enabled as "1" by default in PHP if loaded. As for Go, the profiler must be started manually, so it is enabled by default when started + "dd_data_streams_enabled": "false" + if context.library != "dotnet" + else "true", # Data streams is now enabled by default in non-serverless environments in dotnet + "dd_logs_injection": { + "dotnet": "true", + "ruby": "true", + "java": "true", + "golang": None, + "python": "true", + "nodejs": "true", + "php": "true", + }.get(context.library.name, "false"), # Enabled by default in ruby + } +) class QuotedStr(str): From 13a8bcea80c01e6044c8e00b5954dfb24ad8dbe8 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 14:04:44 -0400 Subject: [PATCH 03/10] fix(cpp): include dd_trace_enabled in SDK_DEFAULT_STABLE_CONFIG C++ natively reports trace_enabled, so include it in the default config checks to verify that setting one stable config value doesn't affect the native config values. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- tests/parametric/test_config_consistency.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/parametric/test_config_consistency.py b/tests/parametric/test_config_consistency.py index 3b6c120e42a..96d7c562558 100644 --- a/tests/parametric/test_config_consistency.py +++ b/tests/parametric/test_config_consistency.py @@ -378,7 +378,11 @@ def test_dogstatsd_custom_port(self, test_library: APMLibrary): SDK_DEFAULT_STABLE_CONFIG = ( - {} + { + # C++ natively reports trace_enabled but doesn't support product enablement + # flags like profiling, runtime_metrics, data_streams, or logs_injection. + "dd_trace_enabled": "true", + } if context.library == "cpp" else { "dd_runtime_metrics_enabled": "false" if context.library not in ("java", "dotnet") else "true", From 14a6e4526511b6949e887ade24d9aaa9159158bf Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 14:36:52 -0400 Subject: [PATCH 04/10] refactor(cpp): split Test_Stable_Configuration_Origin into universal and product-specific classes Split Test_Stable_Configuration_Origin into two classes: - Test_Stable_Configuration_Origin: uses DD_TRACE_ENABLED and DD_VERSION (universal, all languages including C++) - Test_Stable_Configuration_Origin_Product_Enablement: uses product-specific configs (logs injection, DI, etc.) Update all manifests to reference the new class for extended config tests, add missing_feature for cpp on the product enablement class, and add type: ignore comment for mypy on SDK_DEFAULT_STABLE_CONFIG. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- manifests/cpp.yml | 1 + manifests/dotnet.yml | 2 +- manifests/golang.yml | 4 +- manifests/java.yml | 2 +- manifests/nodejs.yml | 4 +- manifests/php.yml | 2 +- manifests/python.yml | 2 +- manifests/ruby.yml | 2 +- tests/parametric/test_config_consistency.py | 2 +- tests/parametric/test_telemetry.py | 139 +++++++++++++++++++- 10 files changed, 149 insertions(+), 11 deletions(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index cb3c4e14e20..cb75f8e236e 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,6 +266,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Consistent_Configs: missing_feature tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) + tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement: missing_feature tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: ">1.0.0" tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: '>=2.0.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar::test_telemetry_sca_enabled_propagated: missing_feature # Created by easy win activation script diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 8d479cb0296..7c481575c19 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -997,7 +997,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v3.28.0 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: missing_feature (Not implemented) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v2.45.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v2.50.0 diff --git a/manifests/golang.yml b/manifests/golang.yml index 5edfebee32f..21bc0b5c7ae 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1176,9 +1176,9 @@ manifest: tests/parametric/test_telemetry.py::Test_Defaults: missing_feature tests/parametric/test_telemetry.py::Test_Environment: missing_feature tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v2.1.0-dev.2 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case : missing_feature (extended configs are not supported) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case : missing_feature (extended configs are not supported) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: '>=2.5.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature::test_telemetry_event_not_propagated: missing_feature # Created by easy win activation script diff --git a/manifests/java.yml b/manifests/java.yml index 228d06d4589..3e11458ef88 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3718,7 +3718,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: 1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: 1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v1.27.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 362600a1d0c..56c42f76fb0 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2090,9 +2090,9 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (does not collect otel_env.invalid metrics for otel_resource_attributes) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: *ref_5_41_0 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: missing_feature (Not implemented) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1709) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case : - declaration: missing_feature (extended configs are not supported) component_version: <=5.75.0 tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: *ref_4_23_0 diff --git a/manifests/php.yml b/manifests/php.yml index a34ffdd4594..5f7015c1f77 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -840,7 +840,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v1.9.0 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: missing_feature tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index 5c8cc4e7abe..43f72a98436 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1772,7 +1772,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (OTEL Sampling config is mapped to a different datadog config) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (OTEL Sampling config is mapped to a different datadog config) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v3.7.0.dev - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1630) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v2.5.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v2.9.0 diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 3ce450c1853..f286e7cfe02 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -1535,7 +1535,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature (Temporarily disabled to move to environment variables as telemetry keys) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1631) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: '>=2.27.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature::test_telemetry_event_not_propagated: missing_feature # Created by easy win activation script diff --git a/tests/parametric/test_config_consistency.py b/tests/parametric/test_config_consistency.py index 96d7c562558..3599cdd4432 100644 --- a/tests/parametric/test_config_consistency.py +++ b/tests/parametric/test_config_consistency.py @@ -394,7 +394,7 @@ def test_dogstatsd_custom_port(self, test_library: APMLibrary): "dd_data_streams_enabled": "false" if context.library != "dotnet" else "true", # Data streams is now enabled by default in non-serverless environments in dotnet - "dd_logs_injection": { + "dd_logs_injection": { # type: ignore[dict-item] "dotnet": "true", "ruby": "true", "java": "true", diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index d9d6632f161..8b12613c3ad 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -648,7 +648,144 @@ def test_telemetry_otel_env_invalid(self, test_agent: TestAgentAPI, test_library @features.stable_configuration_support @rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") class Test_Stable_Configuration_Origin(StableConfigWriter): - """Clients should report origin of configurations set by stable configuration faithfully""" + """Clients should report origin of configurations set by stable configuration faithfully. + + Uses universally supported configs (DD_TRACE_ENABLED, DD_VERSION) so this runs for all + languages including C++. Product-specific origin tests are in + Test_Stable_Configuration_Origin_Product_Enablement. + """ + + @pytest.mark.parametrize( + ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), + [ + ( + {"DD_VERSION": "local-1.0"}, + { + "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", + }, + {"DD_TRACE_ENABLED": True}, + { + "trace_enabled": "fleet_stable_config", + "application_version": "local_stable_config", + }, + ) + ], + ) + def test_stable_configuration_origin( + self, + local_cfg: dict[str, bool | str], + fleet_cfg: dict[str, bool | str], + test_agent: TestAgentAPI, + test_library: APMLibrary, + expected_origins: dict[str, str], + ): + with test_library: + self.write_stable_config( + {"apm_configuration_default": local_cfg}, + "/etc/datadog-agent/application_monitoring.yaml", + test_library, + ) + self.write_stable_config( + {"apm_configuration_default": fleet_cfg}, + "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", + test_library, + ) + time.sleep(1) + test_library.container_restart() + test_library.dd_start_span("test") + configuration_by_name = test_agent.wait_for_telemetry_configurations() + for cfg_name, expected_origin in expected_origins.items(): + apm_telemetry_names = _mapped_telemetry_name(cfg_name) + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, expected_origin + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin '{expected_origin}'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == expected_origin, f"wrong origin for {telemetry_item}" + assert telemetry_item["value"] + + @pytest.mark.parametrize( + ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), + [ + ( + {"DD_VERSION": "local-1.0"}, + {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, + {"DD_TRACE_ENABLED": True}, + "1231231231231", + ) + ], + ) + def test_stable_configuration_config_id( + self, + local_cfg: dict[str, bool | str], + fleet_cfg: dict[str, bool | str], + test_agent: TestAgentAPI, + test_library: APMLibrary, + fleet_config_id: str, + ): + with test_library: + self.write_stable_config( + {"apm_configuration_default": local_cfg}, + "/etc/datadog-agent/application_monitoring.yaml", + test_library, + ) + self.write_stable_config( + {"apm_configuration_default": fleet_cfg, "config_id": fleet_config_id}, + "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", + test_library, + ) + time.sleep(1) + test_library.container_restart() + test_library.dd_start_span("test") + configuration_by_name = test_agent.wait_for_telemetry_configurations() + # Fleet config should have the config_id set + apm_telemetry_names = _mapped_telemetry_name("trace_enabled") + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, "fleet_stable_config" + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == "fleet_stable_config" + assert telemetry_item["config_id"] == fleet_config_id + + # Local config should not have the config_id set + apm_telemetry_names = _mapped_telemetry_name("application_version") + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, "local_stable_config" + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'local_stable_config'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == "local_stable_config" + assert "config_id" not in telemetry_item or telemetry_item["config_id"] is None + + +@scenarios.parametric +@features.stable_configuration_support +@rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") +class Test_Stable_Configuration_Origin_Product_Enablement(StableConfigWriter): + """Clients should report origin of product enablement configurations set by stable configuration. + + Uses product-specific configs (logs injection, dynamic instrumentation, etc.) that are not + supported by all languages. See Test_Stable_Configuration_Origin for universal origin tests. + """ @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), From 5a699903c95c9598f4267d901eb05c6660880532 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 15:06:41 -0400 Subject: [PATCH 05/10] fix: simplify universal telemetry origin tests to fleet-only The universal Test_Stable_Configuration_Origin tests only check fleet stable config origin using DD_TRACE_ENABLED, which all tracers report in telemetry. Removed DD_VERSION/application_version checks since not all tracers report that with stable config origin. Local-only origin testing remains in Test_Stable_Configuration_Origin_Product_Enablement. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- tests/parametric/test_telemetry.py | 80 ++++++++---------------------- 1 file changed, 20 insertions(+), 60 deletions(-) diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index 8b12613c3ad..c728bdadc50 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -650,41 +650,26 @@ def test_telemetry_otel_env_invalid(self, test_agent: TestAgentAPI, test_library class Test_Stable_Configuration_Origin(StableConfigWriter): """Clients should report origin of configurations set by stable configuration faithfully. - Uses universally supported configs (DD_TRACE_ENABLED, DD_VERSION) so this runs for all - languages including C++. Product-specific origin tests are in - Test_Stable_Configuration_Origin_Product_Enablement. + Uses DD_TRACE_ENABLED (universally supported) so this runs for all languages including C++. + Product-specific origin tests are in Test_Stable_Configuration_Origin_Product_Enablement. """ @pytest.mark.parametrize( - ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), + ("library_env", "fleet_cfg"), [ ( - {"DD_VERSION": "local-1.0"}, - { - "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", - }, + {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, {"DD_TRACE_ENABLED": True}, - { - "trace_enabled": "fleet_stable_config", - "application_version": "local_stable_config", - }, ) ], ) def test_stable_configuration_origin( self, - local_cfg: dict[str, bool | str], - fleet_cfg: dict[str, bool | str], + fleet_cfg: dict[str, bool], test_agent: TestAgentAPI, test_library: APMLibrary, - expected_origins: dict[str, str], ): with test_library: - self.write_stable_config( - {"apm_configuration_default": local_cfg}, - "/etc/datadog-agent/application_monitoring.yaml", - test_library, - ) self.write_stable_config( {"apm_configuration_default": fleet_cfg}, "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", @@ -694,27 +679,25 @@ def test_stable_configuration_origin( test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - for cfg_name, expected_origin in expected_origins.items(): - apm_telemetry_names = _mapped_telemetry_name(cfg_name) - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, expected_origin - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin '{expected_origin}'" + apm_telemetry_names = _mapped_telemetry_name("trace_enabled") + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, "fleet_stable_config" ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == expected_origin, f"wrong origin for {telemetry_item}" - assert telemetry_item["value"] + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == "fleet_stable_config" + assert telemetry_item["value"] @pytest.mark.parametrize( - ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), + ("library_env", "fleet_cfg", "fleet_config_id"), [ ( - {"DD_VERSION": "local-1.0"}, {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, {"DD_TRACE_ENABLED": True}, "1231231231231", @@ -723,18 +706,12 @@ def test_stable_configuration_origin( ) def test_stable_configuration_config_id( self, - local_cfg: dict[str, bool | str], - fleet_cfg: dict[str, bool | str], + fleet_cfg: dict[str, bool], test_agent: TestAgentAPI, test_library: APMLibrary, fleet_config_id: str, ): with test_library: - self.write_stable_config( - {"apm_configuration_default": local_cfg}, - "/etc/datadog-agent/application_monitoring.yaml", - test_library, - ) self.write_stable_config( {"apm_configuration_default": fleet_cfg, "config_id": fleet_config_id}, "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", @@ -744,7 +721,6 @@ def test_stable_configuration_config_id( test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - # Fleet config should have the config_id set apm_telemetry_names = _mapped_telemetry_name("trace_enabled") telemetry_item = None for apm_name in apm_telemetry_names: @@ -760,22 +736,6 @@ def test_stable_configuration_config_id( assert telemetry_item["origin"] == "fleet_stable_config" assert telemetry_item["config_id"] == fleet_config_id - # Local config should not have the config_id set - apm_telemetry_names = _mapped_telemetry_name("application_version") - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, "local_stable_config" - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'local_stable_config'" - ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == "local_stable_config" - assert "config_id" not in telemetry_item or telemetry_item["config_id"] is None - @scenarios.parametric @features.stable_configuration_support From 98fd5661f693df123bcac3ad16f36022d89e74fc Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 15:17:43 -0400 Subject: [PATCH 06/10] fix: remove stale cpp entries from telemetry_name_mapping dd-trace-cpp does not emit non-native config keys (DD_LOGS_INJECTION, DD_PROFILING_ENABLED, etc.) in telemetry. These mappings were left over from a removed AdditionalConfigEntry mechanism. Only native configs (trace_enabled, env, service, etc.) are reported, and those use standard names that don't need remapping. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- tests/parametric/test_telemetry.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index c728bdadc50..00a0a521c5e 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -47,7 +47,6 @@ "ruby": "DD_LOGS_INJECTION", "golang": ["DD_LOGS_INJECTION", "trace.logs_enabled"], "java": "DD_LOGS_INJECTION_ENABLED", - "cpp": "DD_LOGS_INJECTION", }, "trace_header_tags": { "dotnet": "DD_TRACE_HEADER_TAGS", @@ -80,7 +79,6 @@ "ruby": "DD_PROFILING_ENABLED", "golang": ["DD_PROFILING_ENABLED", "profiling_enabled"], "java": "DD_PROFILING_ENABLED", - "cpp": "DD_PROFILING_ENABLED", }, "appsec_enabled": { "dotnet": "DD_APPSEC_ENABLED", @@ -97,7 +95,6 @@ "java": "DD_DATA_STREAMS_ENABLED", "golang": ["DD_DATA_STREAMS_ENABLED", "data_streams_enabled"], "ruby": "DD_DATA_STREAMS_ENABLED", - "cpp": "DD_DATA_STREAMS_ENABLED", }, "runtime_metrics_enabled": { "java": "DD_RUNTIME_METRICS_ENABLED", @@ -106,7 +103,6 @@ "python": "DD_RUNTIME_METRICS_ENABLED", "ruby": "DD_RUNTIME_METRICS_ENABLED", "golang": ["DD_RUNTIME_METRICS_ENABLED", "runtime_metrics_enabled"], - "cpp": "DD_RUNTIME_METRICS_ENABLED", }, "dynamic_instrumentation_enabled": { "java": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", @@ -116,7 +112,6 @@ "php": "dynamic_instrumentation.enabled", "ruby": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", "golang": ["DD_DYNAMIC_INSTRUMENTATION_ENABLED", "dynamic_instrumentation_enabled"], - "cpp": "DD_DYNAMIC_INSTRUMENTATION_ENABLED", }, "trace_debug_enabled": { "php": "trace.debug", @@ -124,7 +119,6 @@ "ruby": "DD_TRACE_DEBUG", "python": "DD_TRACE_DEBUG", "golang": ["trace_debug_enabled", "DD_TRACE_DEBUG"], - "cpp": "DD_TRACE_DEBUG", }, "tags": { "java": "DD_TRACE_TAGS", @@ -133,7 +127,6 @@ "nodejs": "DD_TAGS", "golang": ["DD_TAGS", "trace_tags"], "ruby": "DD_TAGS", - "cpp": "DD_TAGS", }, "trace_propagation_style": { "java": "DD_TRACE_PROPAGATION_STYLE", @@ -141,7 +134,6 @@ "php": "trace.propagation_style", "golang": ["DD_TRACE_PROPAGATION_STYLE", "trace.propagation_style"], "ruby": "DD_TRACE_PROPAGATION_STYLE", - "cpp": "DD_TRACE_PROPAGATION_STYLE", }, } From 50ec5925cf6e742ffb696cdad44faea26254b549 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 15:23:07 -0400 Subject: [PATCH 07/10] refactor: improve readability of SDK_DEFAULT_STABLE_CONFIG and test params Replace deeply nested inline ternaries with a helper function and dict.get() lookups. The per-language defaults are now clearly documented in _build_sdk_default_stable_config() instead of being buried in unreadable conditional chains. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- tests/parametric/test_config_consistency.py | 102 +++++++++----------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/tests/parametric/test_config_consistency.py b/tests/parametric/test_config_consistency.py index 3599cdd4432..96a48070fc6 100644 --- a/tests/parametric/test_config_consistency.py +++ b/tests/parametric/test_config_consistency.py @@ -377,34 +377,38 @@ def test_dogstatsd_custom_port(self, test_library: APMLibrary): assert resp["dd_dogstatsd_port"] == "8150" -SDK_DEFAULT_STABLE_CONFIG = ( - { - # C++ natively reports trace_enabled but doesn't support product enablement - # flags like profiling, runtime_metrics, data_streams, or logs_injection. - "dd_trace_enabled": "true", +def _build_sdk_default_stable_config() -> dict: + """Build per-language default config values expected when stable config is active. + + C++ only reports trace_enabled (it doesn't support product enablement features). + Other languages report product defaults that vary by language. + """ + lang = context.library.name + + if context.library == "cpp": + return {"dd_trace_enabled": "true"} + + # Per-language product defaults + profiling_defaults: dict[str, str] = {"php": "1", "golang": "true"} + logs_injection_defaults: dict[str, str | None] = { # type: ignore[assignment] + "dotnet": "true", + "ruby": "true", + "java": "true", + "golang": None, + "python": "true", + "nodejs": "true", + "php": "true", } - if context.library == "cpp" - else { - "dd_runtime_metrics_enabled": "false" if context.library not in ("java", "dotnet") else "true", - "dd_profiling_enabled": "1" - if context.library == "php" - else "true" - if context.library == "golang" - else "false", # Profiling is enabled as "1" by default in PHP if loaded. As for Go, the profiler must be started manually, so it is enabled by default when started - "dd_data_streams_enabled": "false" - if context.library != "dotnet" - else "true", # Data streams is now enabled by default in non-serverless environments in dotnet - "dd_logs_injection": { # type: ignore[dict-item] - "dotnet": "true", - "ruby": "true", - "java": "true", - "golang": None, - "python": "true", - "nodejs": "true", - "php": "true", - }.get(context.library.name, "false"), # Enabled by default in ruby + + return { + "dd_runtime_metrics_enabled": "true" if lang in ("java", "dotnet") else "false", + "dd_profiling_enabled": profiling_defaults.get(lang, "false"), + "dd_data_streams_enabled": "true" if lang == "dotnet" else "false", + "dd_logs_injection": logs_injection_defaults.get(lang, "false"), } -) + + +SDK_DEFAULT_STABLE_CONFIG = _build_sdk_default_stable_config() class QuotedStr(str): @@ -442,40 +446,32 @@ class Test_Stable_Config_Default(StableConfigWriter): ), ( "runtime_metrics", - { - "DD_RUNTIME_METRICS_ENABLED": True, - }, + {"DD_RUNTIME_METRICS_ENABLED": True}, { **SDK_DEFAULT_STABLE_CONFIG, - "dd_runtime_metrics_enabled": "true" - if context.library != "php" - else "false", # PHP does not support runtime metrics + # PHP does not support runtime metrics + "dd_runtime_metrics_enabled": "false" if context.library == "php" else "true", }, ), ( "data_streams", - { - "DD_DATA_STREAMS_ENABLED": True, - }, + {"DD_DATA_STREAMS_ENABLED": True}, { **SDK_DEFAULT_STABLE_CONFIG, - "dd_data_streams_enabled": "true" - if context.library not in ("php", "ruby") - else "false", # PHP and Ruby do not support data streams + # PHP and Ruby do not support data streams + "dd_data_streams_enabled": "false" if context.library in ("php", "ruby") else "true", }, ), ( "logs_injection", - { - "DD_LOGS_INJECTION": context.library != "ruby", # Ruby defaults logs injection to true - }, + # Ruby defaults logs injection to true, so we set False to test the override + {"DD_LOGS_INJECTION": context.library != "ruby"}, { **SDK_DEFAULT_STABLE_CONFIG, - "dd_logs_injection": None - if context.library == "golang" - else "false" - if context.library == "ruby" - else "true", # Logs injection is not supported in dd-trace-go and enabled by default in ruby + "dd_logs_injection": { + "golang": None, # Go doesn't support logs injection + "ruby": "false", # Ruby defaults to true, so False override -> "false" + }.get(context.library.name, "true"), }, ), ], @@ -590,11 +586,10 @@ def test_extended_configs( }, "expected": { **SDK_DEFAULT_STABLE_CONFIG, - "dd_logs_injection": None - if context.library == "golang" - else "false" - if context.library == "ruby" - else "true", # Logs injection is not supported in dd-trace-go and enabled by default in ruby + "dd_logs_injection": { + "golang": None, + "ruby": "false", + }.get(context.library.name, "true"), }, }, ], @@ -669,9 +664,8 @@ def test_invalid_files(self, test_library: APMLibrary, path: str): {"DD_PROFILING_ENABLED": False}, { "dd_profiling_enabled": "false", - "dd_runtime_metrics_enabled": "true" - if context.library != "php" - else "false", # PHP does not support runtime metrics + # PHP does not support runtime metrics + "dd_runtime_metrics_enabled": "false" if context.library == "php" else "true", "dd_env": "abc", }, # expected ), From 502e39f9cd3b1d12a29a32b475a8289d8f0aceff Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 15:32:50 -0400 Subject: [PATCH 08/10] refactor: rename test classes and extract shared telemetry helpers - Rename Test_Stable_Configuration_Origin -> Test_Stable_Configuration_Origin (keep original name for the product-specific class) - Rename the universal class to Test_Stable_Configuration_Single_Config_Origin - Extract _find_telemetry_config() and _assert_telemetry_config_origin() shared helpers to eliminate repeated lookup+assert patterns - Revert manifest references back to original Test_Stable_Configuration_Origin Co-Authored-By: Claude Sonnet 4.6 (1M context) --- manifests/cpp.yml | 2 +- manifests/dotnet.yml | 2 +- manifests/golang.yml | 4 +- manifests/java.yml | 2 +- manifests/nodejs.yml | 4 +- manifests/php.yml | 2 +- manifests/python.yml | 2 +- manifests/ruby.yml | 2 +- tests/parametric/test_telemetry.py | 158 ++++++++++++++--------------- 9 files changed, 89 insertions(+), 89 deletions(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index cb75f8e236e..080da0bf795 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,7 +266,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Consistent_Configs: missing_feature tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) - tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement: missing_feature + tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: ">1.0.0" tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: '>=2.0.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar::test_telemetry_sca_enabled_propagated: missing_feature # Created by easy win activation script diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 7c481575c19..8d479cb0296 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -997,7 +997,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v3.28.0 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: missing_feature (Not implemented) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v2.45.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v2.50.0 diff --git a/manifests/golang.yml b/manifests/golang.yml index 21bc0b5c7ae..5edfebee32f 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1176,9 +1176,9 @@ manifest: tests/parametric/test_telemetry.py::Test_Defaults: missing_feature tests/parametric/test_telemetry.py::Test_Environment: missing_feature tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v2.1.0-dev.2 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case : missing_feature (extended configs are not supported) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case : missing_feature (extended configs are not supported) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: '>=2.5.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature::test_telemetry_event_not_propagated: missing_feature # Created by easy win activation script diff --git a/manifests/java.yml b/manifests/java.yml index 3e11458ef88..228d06d4589 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3718,7 +3718,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: 1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: 1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v1.27.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v1.61.0-SNAPSHOT # Normalization of telemetry keys updated in https://github.com/DataDog/dd-trace-java/pull/10823 diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 56c42f76fb0..362600a1d0c 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2090,9 +2090,9 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (does not collect otel_env.invalid metrics for otel_resource_attributes) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: *ref_5_41_0 tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_config_id: missing_feature (Not implemented) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1709) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case : - declaration: missing_feature (extended configs are not supported) component_version: <=5.75.0 tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: *ref_4_23_0 diff --git a/manifests/php.yml b/manifests/php.yml index 5f7015c1f77..a34ffdd4594 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -840,7 +840,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v1.9.0 - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_temporary_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case : irrelevant (temporary use case for python, ruby and nodejs) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: missing_feature tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index 43f72a98436..5c8cc4e7abe 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1772,7 +1772,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (OTEL Sampling config is mapped to a different datadog config) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (OTEL Sampling config is mapped to a different datadog config) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: v3.7.0.dev - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1630) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: v2.5.0 tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: v2.9.0 diff --git a/manifests/ruby.yml b/manifests/ruby.yml index f286e7cfe02..3ce450c1853 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -1535,7 +1535,7 @@ manifest: tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature (Temporarily disabled to move to environment variables as telemetry keys) - ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin_Product_Enablement::test_stable_configuration_origin_extended_configs_good_use_case + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case : bug (APMAPI-1631) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: '>=2.27.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature::test_telemetry_event_not_propagated: missing_feature # Created by easy win activation script diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index 00a0a521c5e..89efa523f89 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -149,6 +149,42 @@ def _mapped_telemetry_name(apm_telemetry_name: str) -> list[str]: return [apm_telemetry_name] +def _find_telemetry_config( + test_agent: TestAgentAPI, + configuration_by_name: dict[str, list[dict]], + apm_telemetry_name: str, + expected_origin: str, +) -> dict | None: + """Find a telemetry config entry by its standard name and origin. + + Handles per-language name remapping via _mapped_telemetry_name. + Returns the config dict if found, None otherwise. + """ + for apm_name in _mapped_telemetry_name(apm_telemetry_name): + item = test_agent.get_telemetry_config_by_origin(configuration_by_name, apm_name, expected_origin) + if item is not None: + assert isinstance(item, dict) + return item + return None + + +def _assert_telemetry_config_origin( + test_agent: TestAgentAPI, + configuration_by_name: dict[str, list[dict]], + apm_telemetry_name: str, + expected_origin: str, +) -> dict: + """Assert that a telemetry config entry exists with the expected origin and return it.""" + item = _find_telemetry_config(test_agent, configuration_by_name, apm_telemetry_name, expected_origin) + assert item is not None, ( + f"No configuration found for any of {' or '.join(_mapped_telemetry_name(apm_telemetry_name))}" + f" with origin '{expected_origin}'" + ) + assert isinstance(item, dict) + assert item["origin"] == expected_origin, f"wrong origin for {item}" + return item + + def _check_propagation_style_with_inject_and_extract( test_agent: TestAgentAPI, configuration_by_name: dict, expected_origin: str, library_name: str ) -> None: @@ -639,29 +675,39 @@ def test_telemetry_otel_env_invalid(self, test_agent: TestAgentAPI, test_library @scenarios.parametric @features.stable_configuration_support @rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") -class Test_Stable_Configuration_Origin(StableConfigWriter): - """Clients should report origin of configurations set by stable configuration faithfully. +class Test_Stable_Configuration_Single_Config_Origin(StableConfigWriter): + """Verify stable config origin using a single universally supported config (DD_TRACE_ENABLED). - Uses DD_TRACE_ENABLED (universally supported) so this runs for all languages including C++. - Product-specific origin tests are in Test_Stable_Configuration_Origin_Product_Enablement. + Uses the same test structure as Test_Stable_Configuration_Origin but with a single config + that all languages support (including C++). """ @pytest.mark.parametrize( - ("library_env", "fleet_cfg"), + ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), [ ( + {}, {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, {"DD_TRACE_ENABLED": True}, + {"trace_enabled": "fleet_stable_config"}, ) ], ) def test_stable_configuration_origin( self, + local_cfg: dict, fleet_cfg: dict[str, bool], test_agent: TestAgentAPI, test_library: APMLibrary, + expected_origins: dict[str, str], ): with test_library: + if local_cfg: + self.write_stable_config( + {"apm_configuration_default": local_cfg}, + "/etc/datadog-agent/application_monitoring.yaml", + test_library, + ) self.write_stable_config( {"apm_configuration_default": fleet_cfg}, "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", @@ -671,25 +717,15 @@ def test_stable_configuration_origin( test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - apm_telemetry_names = _mapped_telemetry_name("trace_enabled") - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, "fleet_stable_config" - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" - ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == "fleet_stable_config" - assert telemetry_item["value"] + for cfg_name, expected_origin in expected_origins.items(): + item = _assert_telemetry_config_origin(test_agent, configuration_by_name, cfg_name, expected_origin) + assert item["value"] @pytest.mark.parametrize( - ("library_env", "fleet_cfg", "fleet_config_id"), + ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), [ ( + {}, {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, {"DD_TRACE_ENABLED": True}, "1231231231231", @@ -698,12 +734,19 @@ def test_stable_configuration_origin( ) def test_stable_configuration_config_id( self, + local_cfg: dict, fleet_cfg: dict[str, bool], test_agent: TestAgentAPI, test_library: APMLibrary, fleet_config_id: str, ): with test_library: + if local_cfg: + self.write_stable_config( + {"apm_configuration_default": local_cfg}, + "/etc/datadog-agent/application_monitoring.yaml", + test_library, + ) self.write_stable_config( {"apm_configuration_default": fleet_cfg, "config_id": fleet_config_id}, "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", @@ -713,30 +756,20 @@ def test_stable_configuration_config_id( test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - apm_telemetry_names = _mapped_telemetry_name("trace_enabled") - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, "fleet_stable_config" - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" + fleet_item = _assert_telemetry_config_origin( + test_agent, configuration_by_name, "trace_enabled", "fleet_stable_config" ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == "fleet_stable_config" - assert telemetry_item["config_id"] == fleet_config_id + assert fleet_item["config_id"] == fleet_config_id @scenarios.parametric @features.stable_configuration_support @rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") -class Test_Stable_Configuration_Origin_Product_Enablement(StableConfigWriter): +class Test_Stable_Configuration_Origin(StableConfigWriter): """Clients should report origin of product enablement configurations set by stable configuration. Uses product-specific configs (logs injection, dynamic instrumentation, etc.) that are not - supported by all languages. See Test_Stable_Configuration_Origin for universal origin tests. + supported by all languages. See Test_Stable_Configuration_Single_Config_Origin for universal origin tests. """ @pytest.mark.parametrize( @@ -792,23 +825,10 @@ def test_stable_configuration_origin( test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() for cfg_name, expected_origin in expected_origins.items(): - # The Go tracer does not support logs injection. if context.library == "golang" and cfg_name == "logs_injection_enabled": continue - apm_telemetry_names = _mapped_telemetry_name(cfg_name) - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, expected_origin - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin '{expected_origin}'" - ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == expected_origin, f"wrong origin for {telemetry_item}" - assert telemetry_item["value"] + item = _assert_telemetry_config_origin(test_agent, configuration_by_name, cfg_name, expected_origin) + assert item["value"] @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), @@ -855,37 +875,17 @@ def test_stable_configuration_config_id( test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - # Configuration set via fleet config should have the config_id set - apm_telemetry_names = _mapped_telemetry_name("trace_debug_enabled") - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, "fleet_stable_config" - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" + # Fleet config should have the config_id set + fleet_item = _assert_telemetry_config_origin( + test_agent, configuration_by_name, "trace_debug_enabled", "fleet_stable_config" ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == "fleet_stable_config" - assert telemetry_item["config_id"] == fleet_config_id - - # Configuration set via local config should not have the config_id set - apm_telemetry_names = _mapped_telemetry_name("dynamic_instrumentation_enabled") - telemetry_item = None - for apm_name in apm_telemetry_names: - telemetry_item = test_agent.get_telemetry_config_by_origin( - configuration_by_name, apm_name, "local_stable_config" - ) - if telemetry_item is not None: - break - assert telemetry_item is not None, ( - f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'local_stable_config'" + assert fleet_item["config_id"] == fleet_config_id + + # Local config should not have the config_id set + local_item = _assert_telemetry_config_origin( + test_agent, configuration_by_name, "dynamic_instrumentation_enabled", "local_stable_config" ) - assert isinstance(telemetry_item, dict) - assert telemetry_item["origin"] == "local_stable_config" - assert "config_id" not in telemetry_item or telemetry_item["config_id"] is None + assert "config_id" not in local_item or local_item["config_id"] is None @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), From 30ed2e7c5e043c944a84b1c1c42d02692d21b9de Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 15:42:54 -0400 Subject: [PATCH 09/10] feat(cpp): enable stable config telemetry origin tests for C++ Keep a single Test_Stable_Configuration_Origin class with C++ carve-outs: - test_stable_configuration_origin: C++ uses DD_TRACE_ENABLED (the only config it reports in telemetry) instead of product-specific configs - test_stable_configuration_config_id: C++ tests fleet config_id with DD_TRACE_ENABLED; skips local config check (no product configs) - Extended config tests remain missing_feature for C++ Also refactors SDK_DEFAULT_STABLE_CONFIG into a readable helper function and simplifies inline ternary chains in test parametrizations. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- manifests/cpp.yml | 5 +- tests/parametric/test_telemetry.py | 228 +++++++++-------------------- 2 files changed, 76 insertions(+), 157 deletions(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 080da0bf795..18f2518b682 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,7 +266,10 @@ manifest: tests/parametric/test_telemetry.py::Test_Consistent_Configs: missing_feature tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) - tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case + : missing_feature (C++ does not report extended config origins) + ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case + : missing_feature (C++ does not report extended config origins) tests/parametric/test_telemetry.py::Test_TelemetryInstallSignature: ">1.0.0" tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar: '>=2.0.0' # Modified by easy win activation script tests/parametric/test_telemetry.py::Test_TelemetrySCAEnvVar::test_telemetry_sca_enabled_propagated: missing_feature # Created by easy win activation script diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index 89efa523f89..658a3568062 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -149,42 +149,6 @@ def _mapped_telemetry_name(apm_telemetry_name: str) -> list[str]: return [apm_telemetry_name] -def _find_telemetry_config( - test_agent: TestAgentAPI, - configuration_by_name: dict[str, list[dict]], - apm_telemetry_name: str, - expected_origin: str, -) -> dict | None: - """Find a telemetry config entry by its standard name and origin. - - Handles per-language name remapping via _mapped_telemetry_name. - Returns the config dict if found, None otherwise. - """ - for apm_name in _mapped_telemetry_name(apm_telemetry_name): - item = test_agent.get_telemetry_config_by_origin(configuration_by_name, apm_name, expected_origin) - if item is not None: - assert isinstance(item, dict) - return item - return None - - -def _assert_telemetry_config_origin( - test_agent: TestAgentAPI, - configuration_by_name: dict[str, list[dict]], - apm_telemetry_name: str, - expected_origin: str, -) -> dict: - """Assert that a telemetry config entry exists with the expected origin and return it.""" - item = _find_telemetry_config(test_agent, configuration_by_name, apm_telemetry_name, expected_origin) - assert item is not None, ( - f"No configuration found for any of {' or '.join(_mapped_telemetry_name(apm_telemetry_name))}" - f" with origin '{expected_origin}'" - ) - assert isinstance(item, dict) - assert item["origin"] == expected_origin, f"wrong origin for {item}" - return item - - def _check_propagation_style_with_inject_and_extract( test_agent: TestAgentAPI, configuration_by_name: dict, expected_origin: str, library_name: str ) -> None: @@ -675,121 +639,33 @@ def test_telemetry_otel_env_invalid(self, test_agent: TestAgentAPI, test_library @scenarios.parametric @features.stable_configuration_support @rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") -class Test_Stable_Configuration_Single_Config_Origin(StableConfigWriter): - """Verify stable config origin using a single universally supported config (DD_TRACE_ENABLED). - - Uses the same test structure as Test_Stable_Configuration_Origin but with a single config - that all languages support (including C++). - """ +class Test_Stable_Configuration_Origin(StableConfigWriter): + """Clients should report origin of configurations set by stable configuration faithfully""" @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), [ + # C++ only supports trace_enabled in telemetry, not product enablement configs ( {}, {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, {"DD_TRACE_ENABLED": True}, {"trace_enabled": "fleet_stable_config"}, ) - ], - ) - def test_stable_configuration_origin( - self, - local_cfg: dict, - fleet_cfg: dict[str, bool], - test_agent: TestAgentAPI, - test_library: APMLibrary, - expected_origins: dict[str, str], - ): - with test_library: - if local_cfg: - self.write_stable_config( - {"apm_configuration_default": local_cfg}, - "/etc/datadog-agent/application_monitoring.yaml", - test_library, - ) - self.write_stable_config( - {"apm_configuration_default": fleet_cfg}, - "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", - test_library, - ) - time.sleep(1) - test_library.container_restart() - test_library.dd_start_span("test") - configuration_by_name = test_agent.wait_for_telemetry_configurations() - for cfg_name, expected_origin in expected_origins.items(): - item = _assert_telemetry_config_origin(test_agent, configuration_by_name, cfg_name, expected_origin) - assert item["value"] - - @pytest.mark.parametrize( - ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), - [ - ( - {}, - {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, - {"DD_TRACE_ENABLED": True}, - "1231231231231", - ) - ], - ) - def test_stable_configuration_config_id( - self, - local_cfg: dict, - fleet_cfg: dict[str, bool], - test_agent: TestAgentAPI, - test_library: APMLibrary, - fleet_config_id: str, - ): - with test_library: - if local_cfg: - self.write_stable_config( - {"apm_configuration_default": local_cfg}, - "/etc/datadog-agent/application_monitoring.yaml", - test_library, - ) - self.write_stable_config( - {"apm_configuration_default": fleet_cfg, "config_id": fleet_config_id}, - "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", - test_library, - ) - time.sleep(1) - test_library.container_restart() - test_library.dd_start_span("test") - configuration_by_name = test_agent.wait_for_telemetry_configurations() - fleet_item = _assert_telemetry_config_origin( - test_agent, configuration_by_name, "trace_enabled", "fleet_stable_config" - ) - assert fleet_item["config_id"] == fleet_config_id - - -@scenarios.parametric -@features.stable_configuration_support -@rfc("https://docs.google.com/document/d/1MNI5d3g6R8uU3FEWf2e08aAsFcJDVhweCPMjQatEb0o") -class Test_Stable_Configuration_Origin(StableConfigWriter): - """Clients should report origin of product enablement configurations set by stable configuration. - - Uses product-specific configs (logs injection, dynamic instrumentation, etc.) that are not - supported by all languages. See Test_Stable_Configuration_Single_Config_Origin for universal origin tests. - """ - - @pytest.mark.parametrize( - ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), - [ - ( + if context.library == "cpp" + else ( { "DD_LOGS_INJECTION": True, "DD_RUNTIME_METRICS_ENABLED": True, "DD_DYNAMIC_INSTRUMENTATION_ENABLED": True, }, { - "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", # Decrease the heartbeat/poll intervals to speed up the tests + "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", "DD_RUNTIME_METRICS_ENABLED": True, }, {"DD_LOGS_INJECTION": True}, { "logs_injection_enabled": "fleet_stable_config", - # Reporting for other origins than stable config is not completely implemented - # "runtime_metrics_enabled": "env_var", "dynamic_instrumentation_enabled": "local_stable_config", }, ) @@ -825,27 +701,43 @@ def test_stable_configuration_origin( test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() for cfg_name, expected_origin in expected_origins.items(): + # The Go tracer does not support logs injection. if context.library == "golang" and cfg_name == "logs_injection_enabled": continue - item = _assert_telemetry_config_origin(test_agent, configuration_by_name, cfg_name, expected_origin) - assert item["value"] + apm_telemetry_names = _mapped_telemetry_name(cfg_name) + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, expected_origin + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin '{expected_origin}'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == expected_origin, f"wrong origin for {telemetry_item}" + assert telemetry_item["value"] @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "fleet_config_id"), [ + # C++ only supports trace_enabled in telemetry ( + {}, + {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, + {"DD_TRACE_ENABLED": True}, + "1231231231231", + ) + if context.library == "cpp" + else ( {"DD_DYNAMIC_INSTRUMENTATION_ENABLED": True}, - { - "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", # Decrease the heartbeat/poll intervals to speed up the tests - }, - { - "DD_TRACE_DEBUG": True, - }, + {"DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1"}, + {"DD_TRACE_DEBUG": True}, "1231231231231", ) ], ) - # This is the specific test that's currently failing, but any test that calls _mapped_telemetry_name for debug mode, for golang, would fail. def test_stable_configuration_config_id( self, local_cfg: dict[str, bool], @@ -855,13 +747,12 @@ def test_stable_configuration_config_id( fleet_config_id: str, ): with test_library: - self.write_stable_config( - { - "apm_configuration_default": local_cfg, - }, - "/etc/datadog-agent/application_monitoring.yaml", - test_library, - ) + if local_cfg: + self.write_stable_config( + {"apm_configuration_default": local_cfg}, + "/etc/datadog-agent/application_monitoring.yaml", + test_library, + ) self.write_stable_config( { "apm_configuration_default": fleet_cfg, @@ -870,22 +761,47 @@ def test_stable_configuration_config_id( "/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml", test_library, ) - # Sleep to ensure the telemetry events are sent with different timestamps time.sleep(1) test_library.container_restart() test_library.dd_start_span("test") configuration_by_name = test_agent.wait_for_telemetry_configurations() - # Fleet config should have the config_id set - fleet_item = _assert_telemetry_config_origin( - test_agent, configuration_by_name, "trace_debug_enabled", "fleet_stable_config" - ) - assert fleet_item["config_id"] == fleet_config_id - # Local config should not have the config_id set - local_item = _assert_telemetry_config_origin( - test_agent, configuration_by_name, "dynamic_instrumentation_enabled", "local_stable_config" + # Determine which config names to check based on what was configured + fleet_telemetry_name = "trace_enabled" if context.library == "cpp" else "trace_debug_enabled" + + # Configuration set via fleet config should have the config_id set + apm_telemetry_names = _mapped_telemetry_name(fleet_telemetry_name) + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, "fleet_stable_config" + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'fleet_stable_config'" ) - assert "config_id" not in local_item or local_item["config_id"] is None + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == "fleet_stable_config" + assert telemetry_item["config_id"] == fleet_config_id + + # Configuration set via local config should not have the config_id set + # (C++ doesn't have a local config in this test, so skip) + if local_cfg: + apm_telemetry_names = _mapped_telemetry_name("dynamic_instrumentation_enabled") + telemetry_item = None + for apm_name in apm_telemetry_names: + telemetry_item = test_agent.get_telemetry_config_by_origin( + configuration_by_name, apm_name, "local_stable_config" + ) + if telemetry_item is not None: + break + assert telemetry_item is not None, ( + f"No configuration found for any of {' or '.join(apm_telemetry_names)} with origin 'local_stable_config'" + ) + assert isinstance(telemetry_item, dict) + assert telemetry_item["origin"] == "local_stable_config" + assert "config_id" not in telemetry_item or telemetry_item["config_id"] is None @pytest.mark.parametrize( ("local_cfg", "library_env", "fleet_cfg", "expected_origins"), From 97a81e42b1fba1505f4281f76ef73da12ead83a4 Mon Sep 17 00:00:00 2001 From: bm1549 Date: Fri, 20 Mar 2026 16:14:34 -0400 Subject: [PATCH 10/10] fix: mark Test_Stable_Configuration_Origin as missing_feature for C++ The released C++ parametric image doesn't have stable config yet. Mark the entire class as missing_feature until dd-trace-cpp#294 is released. The origin + config_id tests will xpass once the image is updated; extended config tests stay missing_feature permanently. Also removed [cpp@branch] from PR title since system-tests CI applies the target branch globally to all languages, breaking non-cpp builds. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- manifests/cpp.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 18f2518b682..5c0479c5239 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,6 +266,9 @@ manifest: tests/parametric/test_telemetry.py::Test_Consistent_Configs: missing_feature tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_hiding: missing_feature (Not implemented) tests/parametric/test_telemetry.py::Test_Environment::test_telemetry_otel_env_invalid: missing_feature (Not implemented) + # Remove missing_feature for origin + config_id tests once dd-trace-cpp stable config is released. + # Extended config tests remain missing_feature permanently (C++ doesn't report those origins). + tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin: missing_feature ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_good_use_case : missing_feature (C++ does not report extended config origins) ? tests/parametric/test_telemetry.py::Test_Stable_Configuration_Origin::test_stable_configuration_origin_extended_configs_temporary_use_case