diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 6dced7aa71d..87bba3a702a 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -389,6 +389,9 @@ jobs: - name: Run TELEMETRY_ENHANCED_CONFIG_REPORTING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_ENHANCED_CONFIG_REPORTING"') run: ./run.sh TELEMETRY_ENHANCED_CONFIG_REPORTING + - name: Run TELEMETRY_EXTENDED_HEARTBEAT scenario + if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_EXTENDED_HEARTBEAT"') + run: ./run.sh TELEMETRY_EXTENDED_HEARTBEAT - name: Run TELEMETRY_LOG_GENERATION_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_LOG_GENERATION_DISABLED"') run: ./run.sh TELEMETRY_LOG_GENERATION_DISABLED diff --git a/manifests/cpp_httpd.yml b/manifests/cpp_httpd.yml index d49cf2a0941..374c8d4aa01 100644 --- a/manifests/cpp_httpd.yml +++ b/manifests/cpp_httpd.yml @@ -185,6 +185,7 @@ manifest: tests/test_smoke.py::Test_Library::test_receive_request_trace: missing_feature (For some reason, span type is server i/o web) tests/test_span_events.py: incomplete_test_app (Weblog `/add_event` not implemented) tests/test_standard_tags.py: irrelevant + tests/test_telemetry.py::Test_ExtendedHeartbeat: missing_feature (httpd-datadog has not received an update of its dd-trace-cpp since app-extended-heartbeat was implemented) tests/test_telemetry.py::Test_Log_Generation: '>=1.0.3' # Modified by easy win activation script tests/test_telemetry.py::Test_Log_Generation::test_log_generation_enabled: missing_feature # Created by easy win activation script tests/test_telemetry.py::Test_MessageBatch: '>=1.0.3' # Modified by easy win activation script diff --git a/manifests/cpp_nginx.yml b/manifests/cpp_nginx.yml index 08f067b8722..6e96e4cbf53 100644 --- a/manifests/cpp_nginx.yml +++ b/manifests/cpp_nginx.yml @@ -425,6 +425,7 @@ manifest: tests/test_standard_tags.py: irrelevant tests/test_telemetry.py::Test_APMOnboardingInstallID: '>=1.12.0' # Modified by easy win activation script tests/test_telemetry.py::Test_DependencyEnable: '>=1.12.0' # Modified by easy win activation script + tests/test_telemetry.py::Test_ExtendedHeartbeat: missing_feature (nginx-datadog has not received an update of its dd-trace-cpp since app-extended-heartbeat was implemented) tests/test_telemetry.py::Test_Log_Generation: '>=1.12.0' # Modified by easy win activation script tests/test_telemetry.py::Test_Log_Generation::test_log_generation_enabled: missing_feature # Created by easy win activation script tests/test_telemetry.py::Test_MessageBatch: '>=1.12.0' # Modified by easy win activation script diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 207d6d06f29..5bc1e1b2661 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -1189,6 +1189,7 @@ manifest: component_version: '>=2.41' tests/test_standard_tags.py::Test_StandardTagsUserAgent: v2.13.0 tests/test_telemetry.py::Test_DependencyEnable: v2.35.0 + tests/test_telemetry.py::Test_ExtendedHeartbeat: missing_feature (extended-heartbeat payload contains configs missing the required `value` field, failing schema validation) tests/test_telemetry.py::Test_Log_Generation: # Modified by easy win activation script - weblog_declaration: '*': missing_feature diff --git a/manifests/golang.yml b/manifests/golang.yml index 2ca38deab19..75b4f3c4d29 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1444,6 +1444,7 @@ manifest: tests/test_standard_tags.py::Test_StandardTagsUrl::test_url_with_sensitive_query_string: missing_feature (tracer did not yet implemented the new version of query parameters obfuscation regex) tests/test_standard_tags.py::Test_StandardTagsUserAgent: v1.39.0 tests/test_telemetry.py::Test_DependencyEnable: v1.73.0-dev + tests/test_telemetry.py::Test_ExtendedHeartbeat: missing_feature (extended-heartbeat only includes app-started configs, not app-client-configuration-change configs) tests/test_telemetry.py::Test_Log_Generation: v1.73.0-dev tests/test_telemetry.py::Test_MessageBatch: v1.73.0-dev tests/test_telemetry.py::Test_Metric_Generation_Disabled: v1.73.0-dev diff --git a/manifests/java.yml b/manifests/java.yml index 97093384bdb..e190db960ad 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -4329,6 +4329,10 @@ manifest: component_version: '>=1.21.0' tests/test_standard_tags.py::Test_StandardTagsUserAgent: v0.107.1 tests/test_telemetry.py::Test_DependencyEnable: v1.7.0 + tests/test_telemetry.py::Test_ExtendedHeartbeat: + - weblog_declaration: + '*': v1.23.0 + spring-boot-3-native: missing_feature (no app-started telemetry event captured in native image) tests/test_telemetry.py::Test_Log_Generation: # Modified by easy win activation script - weblog_declaration: '*': missing_feature diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index cb81ab8a21e..7764a3cb606 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -87,6 +87,8 @@ refs: - &ref_5_88_0 '>=5.88.0' - &ref_5_89_0 '>=5.89.0' - &ref_5_90_0 '>=5.90.0' + - &ref_5_94_0 '>=5.94.0' + - &ref_5_97_0 '>=5.97.0' - &ref_5_98_0 '>=5.98.0' - &ref_5_99_0 '>=5.99.0' - &ref_6_0_0 '>=6.0.0-pre' @@ -2386,6 +2388,7 @@ manifest: tests/test_standard_tags.py::Test_StandardTagsUrl::test_url_with_sensitive_query_string: missing_feature (tracer did not yet implemented the new version of query parameters obfuscation regex) tests/test_standard_tags.py::Test_StandardTagsUserAgent: v2.9.0 tests/test_telemetry.py::Test_DependencyEnable: missing_feature + tests/test_telemetry.py::Test_ExtendedHeartbeat: *ref_5_97_0 tests/test_telemetry.py::Test_Log_Generation: # TODO: a lower version might be supported - weblog_declaration: '*': missing_feature diff --git a/manifests/php.yml b/manifests/php.yml index 408b1cf8855..49a237fcaa6 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -1090,6 +1090,7 @@ manifest: component_version: '>=0.93.0' tests/test_standard_tags.py::Test_StandardTagsUserAgent: v0.75.0 tests/test_telemetry.py::Test_DependencyEnable: missing_feature + tests/test_telemetry.py::Test_ExtendedHeartbeat: missing_feature (PHP telemetry runs via a sidecar process which does not emit app-extended-heartbeat events yet) tests/test_telemetry.py::Test_Log_Generation: # TODO: a lower version might be supported - weblog_declaration: '*': missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index b1c1b6405b4..e2d8ef9b128 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -2223,6 +2223,7 @@ manifest: component_version: '>=1.18.0-rc1' tests/test_standard_tags.py::Test_StandardTagsUserAgent: v1.5.0-rc1 tests/test_telemetry.py::Test_DependencyEnable: v2.8.0 + tests/test_telemetry.py::Test_ExtendedHeartbeat: v4.6.5 tests/test_telemetry.py::Test_Log_Generation: # Modified by easy win activation script - weblog_declaration: '*': missing_feature diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 47506646760..e6b46155734 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -2111,6 +2111,7 @@ manifest: uds-sinatra: missing_feature tests/test_standard_tags.py::Test_StandardTagsUserAgent: v1.8.0 tests/test_telemetry.py::Test_DependencyEnable: v1.4.0 + tests/test_telemetry.py::Test_ExtendedHeartbeat: ">2.30.0" tests/test_telemetry.py::Test_Log_Generation: # Modified by easy win activation script - weblog_declaration: '*': missing_feature diff --git a/tests/test_telemetry.py b/tests/test_telemetry.py index bf68e5d98ec..ebed087b288 100644 --- a/tests/test_telemetry.py +++ b/tests/test_telemetry.py @@ -1069,3 +1069,53 @@ def test_telemetry_sca_propagated(self): f"No telemetry found for {target_service_name} on {target_request_type} with configuration in " f"{' or '.join(dd_appsec_sca_enabled_names)}" ) + + +@scenarios.telemetry_extended_heartbeat +@features.app_extended_heartbeat_event +class Test_ExtendedHeartbeat: + """Test app-extended-heartbeat telemetry event in end-to-end scenario""" + + def setup_extended_heartbeat_config_matches(self): + weblog.get("/") + + def test_extended_heartbeat_config_matches(self): + """Test that every config reported in app-started or app-client-configuration-change + was eventually reported by at least one app-extended-heartbeat event. + """ + telemetry_data = list(interfaces.library.get_telemetry_data()) + + # Collect all config names reported in app-started and config-change events + expected_config_names: set[str] = set() + found_app_started = False + + for data in telemetry_data: + request_type = get_request_type(data) + if request_type in ("app-started", "app-client-configuration-change"): + if request_type == "app-started": + found_app_started = True + for c in get_configurations(data) or []: + expected_config_names.add(c["name"]) + + assert found_app_started, "app-started event not found" + + # Collect all config names ever reported across all extended heartbeats + heartbeat_config_names: set[str] = set() + found_extended_hb = False + + for data in telemetry_data: + if get_request_type(data) == "app-extended-heartbeat": + found_extended_hb = True + for c in get_configurations(data) or []: + heartbeat_config_names.add(c["name"]) + + assert found_extended_hb, "app-extended-heartbeat event not found" + + # For each expected config, verify it was reported by at least one extended heartbeat. + # Configs may appear in heartbeats before or after they are (re-)reported in + # config-change events (e.g. remote config updates re-report existing configs). + missing = sorted(expected_config_names - heartbeat_config_names) + assert not missing, ( + f"{len(missing)} config(s) reported in app-started or config-change but never " + f"included in any app-extended-heartbeat event: {missing}" + ) diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index a6b36e86b2a..86853f09c40 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -186,6 +186,16 @@ class _Scenarios: doc="Test env var `DD_TELEMETRY_METRICS_ENABLED=false`", scenario_groups=[scenario_groups.telemetry], ) + telemetry_extended_heartbeat = EndToEndScenario( + "TELEMETRY_EXTENDED_HEARTBEAT", + weblog_env={ + "DD_TELEMETRY_HEARTBEAT_INTERVAL": "1", + "DD_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL": "2", + "_DD_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL": "2", + }, + doc="Test app-extended-heartbeat telemetry event with a shortened interval", + scenario_groups=[scenario_groups.telemetry], + ) # ASM scenarios appsec_missing_rules = EndToEndScenario(