diff --git a/index.d.ts b/index.d.ts index 42723767eb..1f95c68dab 100644 --- a/index.d.ts +++ b/index.d.ts @@ -842,11 +842,20 @@ declare namespace tracer { /** * Enables DBM to APM link using tag injection. + * + * - `disabled`: No SQL comment is injected (default). + * - `service`: Injects a SQL comment with service-level tags (database name, service, environment, + * host, tracer service, tracer version). Enables DBM–APM correlation without full trace linking. + * - `full`: Same as `service`, plus a W3C `traceparent` for full distributed trace correlation. + * - `dynamic_service`: Same as `service`, but also automatically injects the propagation hash + * (`ddsh`) when process tags are enabled (`DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=true`). + * This is a convenience shorthand for `service` + `DD_DBM_INJECT_SQL_BASEHASH=true`. + * * @default 'disabled' * @env DD_DBM_PROPAGATION_MODE * Programmatic configuration takes precedence over the environment variables listed above. */ - dbmPropagationMode?: 'disabled' | 'service' | 'full' + dbmPropagationMode?: 'disabled' | 'service' | 'full' | 'dynamic_service' /** * Whether to enable Data Streams Monitoring. diff --git a/index.d.v5.ts b/index.d.v5.ts index b122c66ae7..9d50093fbd 100644 --- a/index.d.v5.ts +++ b/index.d.v5.ts @@ -908,11 +908,20 @@ declare namespace tracer { /** * Enables DBM to APM link using tag injection. + * + * - `disabled`: No SQL comment is injected (default). + * - `service`: Injects a SQL comment with service-level tags (database name, service, environment, + * host, tracer service, tracer version). Enables DBM–APM correlation without full trace linking. + * - `full`: Same as `service`, plus a W3C `traceparent` for full distributed trace correlation. + * - `dynamic_service`: Same as `service`, but also automatically injects the propagation hash + * (`ddsh`) when process tags are enabled (`DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=true`). + * This is a convenience shorthand for `service` + `DD_DBM_INJECT_SQL_BASEHASH=true`. + * * @default 'disabled' * @env DD_DBM_PROPAGATION_MODE * Programmatic configuration takes precedence over the environment variables listed above. */ - dbmPropagationMode?: 'disabled' | 'service' | 'full' + dbmPropagationMode?: 'disabled' | 'service' | 'full' | 'dynamic_service' /** * Whether to enable Data Streams Monitoring. diff --git a/packages/dd-trace/src/config/generated-config-types.d.ts b/packages/dd-trace/src/config/generated-config-types.d.ts index 172393ba7a..1457c62d2d 100644 --- a/packages/dd-trace/src/config/generated-config-types.d.ts +++ b/packages/dd-trace/src/config/generated-config-types.d.ts @@ -65,7 +65,7 @@ export interface GeneratedConfig { dbm: { injectSqlBaseHash: boolean; }; - dbmPropagationMode: string; + dbmPropagationMode: "disabled" | "service" | "full" | "dynamic_service"; DD_ACTION_EXECUTION_ID: string | undefined; DD_AGENTLESS_LOG_SUBMISSION_ENABLED: boolean; DD_AGENTLESS_LOG_SUBMISSION_URL: string | undefined; diff --git a/packages/dd-trace/src/config/supported-configurations.json b/packages/dd-trace/src/config/supported-configurations.json index 772223c808..e9485b13fe 100644 --- a/packages/dd-trace/src/config/supported-configurations.json +++ b/packages/dd-trace/src/config/supported-configurations.json @@ -640,7 +640,9 @@ "configurationNames": [ "dbmPropagationMode" ], - "default": "disabled" + "default": "disabled", + "allowed": "disabled|service|full|dynamic_service", + "transform": "toLowerCase" } ], "DD_DOGSTATSD_HOST": [ diff --git a/packages/dd-trace/src/plugins/database.js b/packages/dd-trace/src/plugins/database.js index 3ee4555d10..986bf197d6 100644 --- a/packages/dd-trace/src/plugins/database.js +++ b/packages/dd-trace/src/plugins/database.js @@ -97,8 +97,9 @@ class DatabasePlugin extends StoragePlugin { let dbmComment = servicePropagation - // Add propagation hash if both process tags and SQL base hash injection are enabled - if (propagationHash.isEnabled() && this.config['dbm.injectSqlBaseHash']) { + // Add propagation hash if process tags are enabled and either SQL base hash injection is enabled + // or dynamic_service mode implicitly enables it + if (propagationHash.isEnabled() && (this.config['dbm.injectSqlBaseHash'] || mode === 'dynamic_service')) { const hashBase64 = propagationHash.getHashBase64() if (hashBase64) { dbmComment += `,ddsh='${hashBase64}'` @@ -107,7 +108,7 @@ class DatabasePlugin extends StoragePlugin { } } - if (disableFullMode || mode === 'service') { + if (disableFullMode || mode === 'service' || mode === 'dynamic_service') { return dbmComment } else if (mode === 'full') { span.setTag('_dd.dbm_trace_injected', 'true') diff --git a/packages/dd-trace/test/plugins/database-dbm-hash.spec.js b/packages/dd-trace/test/plugins/database-dbm-hash.spec.js index 4036217e5c..57f8a29956 100644 --- a/packages/dd-trace/test/plugins/database-dbm-hash.spec.js +++ b/packages/dd-trace/test/plugins/database-dbm-hash.spec.js @@ -164,6 +164,54 @@ describe('DatabasePlugin DBM Hash', () => { }) }) + describe('dynamic_service mode', () => { + beforeEach(() => { + plugin.config.dbmPropagationMode = 'dynamic_service' + }) + + it('should inject hash even when dbm.injectSqlBaseHash is false', () => { + plugin.config['dbm.injectSqlBaseHash'] = false + + const comment = plugin.createDbmComment(span, 'test-service') + + assert.ok(comment, 'Comment should be created') + assert.ok(comment.includes("ddsh='AQIDBAUG'"), + 'dynamic_service should inject hash regardless of injectSqlBaseHash') + }) + + it('should not inject traceparent', () => { + const comment = plugin.createDbmComment(span, 'test-service') + + assert.ok(comment, 'Comment should be created') + assert.ok(!comment.includes('traceparent='), 'dynamic_service should not inject traceparent') + }) + + it('should behave identically to service + injectSqlBaseHash=true', () => { + plugin.config['dbm.injectSqlBaseHash'] = false + + const dynamicComment = plugin.createDbmComment(span, 'test-service') + + // Reset span tags and compare with service + injectSqlBaseHash=true + span._tags = {} + plugin.config.dbmPropagationMode = 'service' + plugin.config['dbm.injectSqlBaseHash'] = true + + const serviceComment = plugin.createDbmComment(span, 'test-service') + + assert.strictEqual(dynamicComment, serviceComment, + 'dynamic_service should produce identical output to service + injectSqlBaseHash=true') + }) + + it('should not inject hash when propagation hash is disabled', () => { + propagationHash.isEnabled = () => false + + const comment = plugin.createDbmComment(span, 'test-service') + + assert.ok(comment, 'Comment should still be created') + assert.ok(!comment.includes('ddsh='), 'Should not inject hash when propagation hash is disabled') + }) + }) + describe('control matrix for process tags and SQL base hash', () => { it('should inject hash when both propagateProcessTags and injectSqlBaseHash are enabled', () => { // DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=true + DD_DBM_INJECT_SQL_BASEHASH=true