Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions manifests/cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
84 changes: 43 additions & 41 deletions tests/parametric/test_config_consistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,26 +377,38 @@ 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",
"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):
Expand Down Expand Up @@ -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"),
},
),
],
Expand Down Expand Up @@ -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"),
},
},
],
Expand Down Expand Up @@ -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
),
Expand Down
77 changes: 45 additions & 32 deletions tests/parametric/test_telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
)
Expand Down Expand Up @@ -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],
Expand All @@ -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,
Expand All @@ -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(
Expand All @@ -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"),
Expand Down
Loading