diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 59f64830f54..3367b9e8ec3 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -57,6 +57,7 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: missing_feature tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: missing_feature tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: ">1.0.0" tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids::test_b3single_128_bit_generation_disabled: missing_feature (propagation style not supported) diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 8ef3ae246d7..e8ab103a3f4 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -864,6 +864,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v3.37.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: v3.37.0 tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_default_matches_specification: missing_feature (defaults to disabled) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_stable_values: missing_feature (false is ignored) diff --git a/manifests/golang.yml b/manifests/golang.yml index 98da343e45b..f98ee03715e 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1561,6 +1561,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v2.5.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: missing_feature tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: v1.50.0 tests/parametric/test_config_consistency.py::Test_Config_Dogstatsd: v1.72.0-dev diff --git a/manifests/java.yml b/manifests/java.yml index a28c1470345..85bb1e9252e 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3811,6 +3811,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v1.56.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: v1.54.0 tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_default_matches_specification: missing_feature (defaults to disabled) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_stable_values: 'missing_feature (Currently DD_TRACE_OTEL_ENABLED=true is required for OTEL_SDK_DISABLED to be parsed. Revisit when the OpenTelemetry integration is enabled by default.)' diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 4655409ffb4..2e989f41d68 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2251,6 +2251,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v5.83.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: v5.83.0 tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_datadog_configuration_takes_precedence: incomplete_test_app (config is not exposed) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_default_matches_specification: missing_feature (defaults to true) diff --git a/manifests/php.yml b/manifests/php.yml index 70263c86924..3b1df5a21c8 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -1379,6 +1379,7 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v1.23.0 tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: missing_feature tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: v0.84.0 tests/parametric/test_config_consistency.py::Test_Config_Dogstatsd: v1.9.0 diff --git a/manifests/python.yml b/manifests/python.yml index 97e0a36eff5..7eb21989fbd 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1906,6 +1906,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v4.11.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: v4.11.0 tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED::test_default_matches_specification: missing_feature (defaults to disabled) tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: v2.6.0 diff --git a/manifests/ruby.yml b/manifests/ruby.yml index b2f28eb11f4..e8b3adbc4fe 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -2272,6 +2272,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v2.23.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: missing_feature tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: v1.17.0 tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids::test_b3single_128_bit_generation_disabled: irrelevant (Supports the value `b3` instead of the deprecated `B3 single header`) diff --git a/manifests/rust.yml b/manifests/rust.yml index bbe1a08b8e3..ea8fa1b4a36 100644 --- a/manifests/rust.yml +++ b/manifests/rust.yml @@ -68,6 +68,9 @@ manifest: tests/otel_tracing_e2e/test_e2e.py::Test_OTelLogE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelMetricE2E: irrelevant tests/otel_tracing_e2e/test_e2e.py::Test_OTelTracingE2E: irrelevant + tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v0.3.0 + ? tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_default_matches_specification + : irrelevant (Datadog intentionally defaults to 7500 ms) tests/parametric/otel_env_vars/test_otel_sdk_disabled.py::Test_OTEL_SDK_DISABLED: missing_feature tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids: v0.0.1 tests/parametric/test_128_bit_traceids.py::Test_128_Bit_Traceids::test_b3multi_128_bit_generation_disabled: missing_feature (propagation style not supported) diff --git a/tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py b/tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py new file mode 100644 index 00000000000..94da5761f80 --- /dev/null +++ b/tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py @@ -0,0 +1,105 @@ +import pytest + +from tests.parametric.conftest import APMLibrary +from utils import features, scenarios +from utils.docker_fixtures import TestAgentAPI + + +DEFAULT_ENVIRONMENT = { + # Enable the OTel metrics pipeline in tracers where it is not enabled by default. + "DD_METRICS_OTEL_ENABLED": "true", + # Prevent unrelated runtime metrics from satisfying the OTLP metrics wait. + "DD_RUNTIME_METRICS_ENABLED": "false", + # Deliver configuration telemetry promptly instead of waiting for the normal heartbeat. + "DD_TELEMETRY_HEARTBEAT_INTERVAL": "0.1", + # Avoid periodic exports so the test observes only the metric it explicitly flushes. + "OTEL_METRIC_EXPORT_INTERVAL": "60000", +} + +STABLE_VALUES = [ + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "0"}, 0, id="zero-unlimited"), + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "1"}, 1, id="minimum-finite"), + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "12000"}, 12000, id="twelve-seconds"), + pytest.param( + {**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "2147483647"}, + 2147483647, + id="int32-max", + ), +] + +INVALID_VALUES = [ + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "-1"}, id="negative"), + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": "not-a-timeout"}, id="not-an-integer"), +] + +UNSET_AND_EMPTY_VALUES = [ + pytest.param(DEFAULT_ENVIRONMENT, id="unset"), + pytest.param({**DEFAULT_ENVIRONMENT, "OTEL_METRIC_EXPORT_TIMEOUT": ""}, id="empty"), +] + + +def _metric_export_timeout_configuration( + test_agent: TestAgentAPI, + test_library: APMLibrary, +) -> dict[str, object]: + meter_name = "otel-metric-export-timeout" + instrument_name = "otel.metric.export.timeout" + + with test_library as library: + library.otel_get_meter(meter_name, "1.0.0", "", {}) + library.otel_create_counter(meter_name, instrument_name, "1", "Metric SDK initialization") + library.otel_counter_add(meter_name, instrument_name, "1", "Metric SDK initialization", 1, {}) + library.otel_metrics_force_flush() + + test_agent.wait_for_num_otlp_metrics(num=1) + configurations = test_agent.wait_for_telemetry_configurations() + config = test_agent.get_telemetry_config_by_origin( + configurations, + "OTEL_METRIC_EXPORT_TIMEOUT", + "env_var", + fallback_to_first=True, + ) + assert isinstance(config, dict), "No telemetry configuration found for 'OTEL_METRIC_EXPORT_TIMEOUT'" + + return config + + +def _metric_export_timeout(config: dict[str, object]) -> int: + value = config.get("value") + assert value is not None, f"OTEL_METRIC_EXPORT_TIMEOUT value is missing from configuration: {config}" + return int(str(value)) + + +@scenarios.parametric +@features.otel_metric_export_timeout +class Test_OTEL_METRIC_EXPORT_TIMEOUT: + @pytest.mark.parametrize(("library_env", "expected"), STABLE_VALUES) + def test_stable_values( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected: int, + ) -> None: + config = _metric_export_timeout_configuration(test_agent, test_library) + assert config.get("origin") == "env_var" + assert _metric_export_timeout(config) == expected + + @pytest.mark.parametrize("library_env", INVALID_VALUES) + def test_invalid_values_use_default(self, test_agent: TestAgentAPI, test_library: APMLibrary) -> None: + config = _metric_export_timeout_configuration(test_agent, test_library) + assert config.get("origin") == "default" + assert _metric_export_timeout(config) >= 0 + + @pytest.mark.parametrize("library_env", UNSET_AND_EMPTY_VALUES) + def test_unset_and_empty_use_default(self, test_agent: TestAgentAPI, test_library: APMLibrary) -> None: + config = _metric_export_timeout_configuration(test_agent, test_library) + assert config.get("origin") == "default" + assert _metric_export_timeout(config) >= 0 + + # All DD SDKs but PHP intentionally default to 7500 ms, + # which is not the OTel specification default of 30000 ms. This test is irrelevant for them. + @pytest.mark.parametrize("library_env", [pytest.param(DEFAULT_ENVIRONMENT, id="unset")]) + def test_default_matches_specification(self, test_agent: TestAgentAPI, test_library: APMLibrary) -> None: + config = _metric_export_timeout_configuration(test_agent, test_library) + assert _metric_export_timeout(config) == 30000