From 008f14f4d928f33210b9fe74c3c8d597847476af Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Thu, 21 May 2026 12:01:16 +0200 Subject: [PATCH 1/3] Add coverage for DBM dynamic_service mode --- manifests/cpp.yml | 1 + manifests/cpp_nginx.yml | 1 + manifests/dotnet.yml | 1 + manifests/golang.yml | 1 + manifests/java.yml | 4 ++ manifests/java_otel.yml | 1 + manifests/nodejs.yml | 1 + manifests/nodejs_otel.yml | 1 + manifests/php.yml | 1 + manifests/python.yml | 1 + manifests/python_otel.yml | 1 + manifests/ruby.yml | 7 +++ manifests/rust.yml | 1 + tests/integrations/test_dbm.py | 72 +++++++++++++++++++++++ utils/_context/_scenarios/__init__.py | 8 ++- utils/_context/_scenarios/integrations.py | 16 +++++ utils/_features.py | 8 +++ 17 files changed, 125 insertions(+), 1 deletion(-) diff --git a/manifests/cpp.yml b/manifests/cpp.yml index a0f378a14f7..39338231aef 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -43,6 +43,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmKafka::test_dsm_kafka_without_cluster_id: irrelevant tests/integrations/test_dsm.py::Test_DsmRabbitmq::test_dsm_rabbitmq_dotnet_legacy: irrelevant (legacy dotnet behavior) tests/integrations/test_mongo.py::Test_Mongo: missing_feature (Endpoint is not implemented on weblog) diff --git a/manifests/cpp_nginx.yml b/manifests/cpp_nginx.yml index 2246b6cf6ca..5c7e33eda1f 100644 --- a/manifests/cpp_nginx.yml +++ b/manifests/cpp_nginx.yml @@ -301,6 +301,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Injection_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmHttp: missing_feature diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 3e109f4b37f..cd11e7ba714 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -743,6 +743,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Injection_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmHttp: missing_feature diff --git a/manifests/golang.yml b/manifests/golang.yml index 81ec8610fcd..3f6b3a87124 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -961,6 +961,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: - weblog_declaration: "*": irrelevant diff --git a/manifests/java.yml b/manifests/java.yml index 4a1e700884e..fec2eae0a0e 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3503,6 +3503,10 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: + - weblog_declaration: + "*": irrelevant + spring-boot: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: - weblog_declaration: "*": irrelevant diff --git a/manifests/java_otel.yml b/manifests/java_otel.yml index f4e03e32c5e..b014c502b09 100644 --- a/manifests/java_otel.yml +++ b/manifests/java_otel.yml @@ -34,6 +34,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmKafka::test_dsm_kafka_without_cluster_id: irrelevant tests/integrations/test_dsm.py::Test_DsmRabbitmq::test_dsm_rabbitmq_dotnet_legacy: irrelevant (legacy dotnet behavior) tests/integrations/test_mongo.py::Test_Mongo: missing_feature (Endpoint is not implemented on weblog) diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 5e578714b46..fffd861e8da 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -1823,6 +1823,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: - weblog_declaration: "*": irrelevant diff --git a/manifests/nodejs_otel.yml b/manifests/nodejs_otel.yml index 26e410cf65b..b5dbe83d6f8 100644 --- a/manifests/nodejs_otel.yml +++ b/manifests/nodejs_otel.yml @@ -33,6 +33,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmKafka::test_dsm_kafka_without_cluster_id: irrelevant tests/integrations/test_dsm.py::Test_DsmRabbitmq::test_dsm_rabbitmq_dotnet_legacy: irrelevant (legacy dotnet behavior) tests/integrations/test_mongo.py::Test_Mongo: missing_feature (Endpoint is not implemented on weblog) diff --git a/manifests/php.yml b/manifests/php.yml index 28e9cb330d2..7a4bd029293 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -661,6 +661,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Injection_Base64: missing_feature tests/integrations/test_dsm.py::Test_DsmHttp: missing_feature diff --git a/manifests/python.yml b/manifests/python.yml index 25361344c72..ad92b85c1e2 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1605,6 +1605,7 @@ manifest: - weblog_declaration: flask-poc: bug (APMAPI-1058) uds-flask: bug (APMAPI-1058) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: missing_feature tests/integrations/test_dbm.py::_BaseDbmComment::test_dbm_comment: - weblog_declaration: flask-poc: bug (APMAPI-1058) diff --git a/manifests/python_otel.yml b/manifests/python_otel.yml index 1313e12a87b..21e602d0de3 100644 --- a/manifests/python_otel.yml +++ b/manifests/python_otel.yml @@ -33,6 +33,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmKafka::test_dsm_kafka_without_cluster_id: irrelevant tests/integrations/test_dsm.py::Test_DsmRabbitmq::test_dsm_rabbitmq_dotnet_legacy: irrelevant (legacy dotnet behavior) tests/integrations/test_mongo.py::Test_Mongo: missing_feature (Endpoint is not implemented on weblog) diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 5ae4dcd028a..8b089ac6a8e 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -1899,6 +1899,13 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: + - weblog_declaration: + "*": irrelevant + sinatra14: missing_feature + sinatra22: missing_feature + sinatra32: missing_feature + sinatra41: missing_feature tests/integrations/test_dsm.py::Test_DsmContext_Extraction_Base64: - weblog_declaration: "*": irrelevant diff --git a/manifests/rust.yml b/manifests/rust.yml index ed73b0abbda..af214aebe8b 100644 --- a/manifests/rust.yml +++ b/manifests/rust.yml @@ -46,6 +46,7 @@ manifest: tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Mysqldb: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Psycopg: irrelevant (These are python only tests.) tests/integrations/test_dbm.py::Test_Dbm_Comment_Python_Pymysql: irrelevant (These are python only tests.) + tests/integrations/test_dbm.py::Test_Dbm_DynamicService_Postgres: irrelevant tests/integrations/test_dsm.py::Test_DsmKafka::test_dsm_kafka_without_cluster_id: irrelevant tests/integrations/test_dsm.py::Test_DsmRabbitmq::test_dsm_rabbitmq_dotnet_legacy: irrelevant (legacy dotnet behavior) tests/integrations/test_mongo.py::Test_Mongo: missing_feature (Endpoint is not implemented on weblog) diff --git a/tests/integrations/test_dbm.py b/tests/integrations/test_dbm.py index 1c3c4f2f69f..c1144ee1636 100644 --- a/tests/integrations/test_dbm.py +++ b/tests/integrations/test_dbm.py @@ -398,3 +398,75 @@ def integration(self): @property def dddbs(self): return self._LIBRARY_CONFIG.get(context.library.name, (None, None))[1] + + +class _BaseDbmDynamicService: + """Verify DD_DBM_PROPAGATION_MODE=dynamic_service: + - injects ddsh='' into the SQL comment + - sets _dd.propagated_hash= on the SQL span + """ + + operation: str = "execute" + + @property + def integration(self): + return None + + def setup_dbm_dynamic_service(self): + self.r = weblog.get("/stub_dbm", params={"integration": self.integration, "operation": self.operation}) + + def test_dbm_dynamic_service(self): + assert self.r.status_code == 200, f"Request: {self.r.request.url} wasn't successful." + + try: + data = json.loads(self.r.text) + except json.decoder.JSONDecodeError as e: + raise ValueError(f"Response from {self.r.request.url} should have been JSON") from e + + assert data.get("status") == "ok" + comment = data.get("dbm_comment", "") + assert comment, "dbm_comment is empty" + + # ddsh field is present and non-empty in the SQL comment + match = re.search(r"ddsh='([^']*)'", comment) + assert match, f"ddsh field not found in SQL comment: {comment}" + ddsh_value = match.group(1) + assert ddsh_value, "ddsh value is empty" + + # SQL span carries _dd.propagated_hash equal to ddsh + sql_spans = [ + span + for _, trace in interfaces.library.get_traces(request=self.r) + for span in trace + if span.get("type") == "sql" + ] + assert sql_spans, "No SQL span found for the /stub_dbm request" + + for span in sql_spans: + propagated_hash = span.get("meta", {}).get("_dd.propagated_hash") + if propagated_hash is not None: + assert propagated_hash == ddsh_value, f"_dd.propagated_hash '{propagated_hash}' != ddsh '{ddsh_value}'" + return + + raise AssertionError( + f"_dd.propagated_hash not found in any SQL span. " + f"Span meta keys: {[list(s.get('meta', {}).keys()) for s in sql_spans]}" + ) + + +@features.database_monitoring_dynamic_service +@scenarios.dbm_dynamic_service +class Test_Dbm_DynamicService_Postgres(_BaseDbmDynamicService): + """DBM dynamic_service mode — PostgreSQL integration across all languages.""" + + _LIBRARY_CONFIG = { + "python": "psycopg", + "nodejs": "pg", + "java": "postgresql", + "ruby": "pg", + "php": "pdo-pgsql", + } + + @property + def integration(self): + return self._LIBRARY_CONFIG.get(context.library.name) diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index 7087e15c626..63794d90be5 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -8,7 +8,12 @@ from .core import Scenario, scenario_groups from .default import DefaultScenario from .endtoend import DockerScenario, EndToEndScenario -from .integrations import CrossedTracingLibraryScenario, IntegrationsScenario, AWSIntegrationsScenario +from .integrations import ( + CrossedTracingLibraryScenario, + DbmDynamicServiceScenario, + IntegrationsScenario, + AWSIntegrationsScenario, +) from .open_telemetry import OpenTelemetryScenario from .otel_collector import OtelCollectorScenario from .parametric import ParametricScenario @@ -55,6 +60,7 @@ class _Scenarios: ) integrations = IntegrationsScenario() integrations_aws = AWSIntegrationsScenario("INTEGRATIONS_AWS") + dbm_dynamic_service = DbmDynamicServiceScenario() crossed_tracing_libraries = CrossedTracingLibraryScenario() otel_integrations = OpenTelemetryScenario( diff --git a/utils/_context/_scenarios/integrations.py b/utils/_context/_scenarios/integrations.py index fd18ca2aa59..8369dc045aa 100644 --- a/utils/_context/_scenarios/integrations.py +++ b/utils/_context/_scenarios/integrations.py @@ -75,6 +75,22 @@ def configure(self, config: pytest.Config): self.unique_id = _get_unique_id(self.host_log_folder, replay=self.replay) +class DbmDynamicServiceScenario(EndToEndScenario): + def __init__(self) -> None: + super().__init__( + "DBM_DYNAMIC_SERVICE", + weblog_env={ + "DD_DBM_PROPAGATION_MODE": "dynamic_service", + }, + other_weblog_containers=(PostgresContainer,), + doc=( + "Verifies DD_DBM_PROPAGATION_MODE=dynamic_service injects ddsh into SQL comments " + "and sets _dd.propagated_hash on SQL spans with the same value." + ), + scenario_groups=[scenario_groups.integrations], + ) + + class AWSIntegrationsScenario(EndToEndScenario): unique_id: str = "" diff --git a/utils/_features.py b/utils/_features.py index e2507ba2d29..acfb16e5408 100644 --- a/utils/_features.py +++ b/utils/_features.py @@ -1920,6 +1920,14 @@ def database_monitoring_support(test_object): test_object, feature_id=296, owner=_Owner.idm ) # tracing/context-propagation, apm/dbm, idm-sugar + @staticmethod + def database_monitoring_dynamic_service(test_object): + """DBM: dynamic_service propagation mode — injects ddsh into SQL comments and _dd.propagated_hash onto spans + + https://docs.google.com/document/d/1v-NuhF_0LNCY3zkSQlL6nPxrvlKfvm9LDkeZlEOyO3w/edit?tab=t.0 + """ + return _mark_test_object(test_object, feature_id=558, owner=_Owner.idm) + @staticmethod def rasp_stack_trace(test_object): """Appsec RASP: Stack Trace From 3b044121cdac444386e561fad3045ac48d9b0e27 Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Thu, 21 May 2026 12:19:03 +0200 Subject: [PATCH 2/3] Add feature parity link in the docstring --- utils/_features.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/_features.py b/utils/_features.py index acfb16e5408..87c96dd6f0b 100644 --- a/utils/_features.py +++ b/utils/_features.py @@ -1924,6 +1924,7 @@ def database_monitoring_support(test_object): def database_monitoring_dynamic_service(test_object): """DBM: dynamic_service propagation mode — injects ddsh into SQL comments and _dd.propagated_hash onto spans + https://feature-parity.us1.prod.dog/#/?feature=558 https://docs.google.com/document/d/1v-NuhF_0LNCY3zkSQlL6nPxrvlKfvm9LDkeZlEOyO3w/edit?tab=t.0 """ return _mark_test_object(test_object, feature_id=558, owner=_Owner.idm) From 68153e0c13d196ce05c85ff0fd1b3a7e971dd85d Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Fri, 22 May 2026 09:57:43 +0200 Subject: [PATCH 3/3] Add to end-to-end --- .github/workflows/run-end-to-end.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 928551f0f2f..5b6292bbbdb 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -226,6 +226,9 @@ jobs: - name: Run INTEGRATIONS_AWS scenario if: steps.build.outcome == 'success' && !cancelled() && contains(inputs.scenarios, '"INTEGRATIONS_AWS"') run: ./run.sh INTEGRATIONS_AWS + - name: Run DBM_DYNAMIC_SERVICE scenario + if: steps.build.outcome == 'success' && !cancelled() && contains(inputs.scenarios, '"DBM_DYNAMIC_SERVICE"') + run: ./run.sh DBM_DYNAMIC_SERVICE - name: Run APM_TRACING_E2E_OTEL scenario if: steps.build.outcome == 'success' && !cancelled() && contains(inputs.scenarios, '"APM_TRACING_E2E_OTEL"') run: |