diff --git a/manifests/cpp.yml b/manifests/cpp.yml index f9bc4141c20..5c0479c5239 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -266,11 +266,13 @@ 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 (extended configs are not supported) + : 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 (extended configs are not supported) + : 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_config_consistency.py b/tests/parametric/test_config_consistency.py index 983fbaa4465..96a48070fc6 100644 --- a/tests/parametric/test_config_consistency.py +++ b/tests/parametric/test_config_consistency.py @@ -377,17 +377,20 @@ 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": { +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", @@ -395,8 +398,17 @@ def test_dogstatsd_custom_port(self, test_library: APMLibrary): "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): @@ -434,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"), }, ), ], @@ -582,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"), }, }, ], @@ -661,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 ), diff --git a/tests/parametric/test_telemetry.py b/tests/parametric/test_telemetry.py index 8c3537d997e..658a3568062 100644 --- a/tests/parametric/test_telemetry.py +++ b/tests/parametric/test_telemetry.py @@ -645,21 +645,27 @@ class Test_Stable_Configuration_Origin(StableConfigWriter): @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"}, + ) + 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", }, ) @@ -716,19 +722,22 @@ def test_stable_configuration_origin( @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], @@ -738,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, @@ -753,13 +761,16 @@ 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() + + # 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("trace_debug_enabled") + 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( @@ -775,20 +786,22 @@ def test_stable_configuration_config_id( 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" + # (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'" ) - 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 + 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"),