Skip to content

Commit b6c2bf0

Browse files
watsonrochdev
authored andcommitted
[Code Origin for Spans] Allow code origin to be disabled (#5635)
Due to a bug in how the tracer configuration was parsed, older versions of the tracer would always have Code Origin for entry spans enabled, no matter if it was disabled in config (which it was supposed to be by default). This bug only applied to Code Origin for entry spans on Fastify, whereas Code Origin for exit spans correctly adhered to the config. This bug has been precent in the tracer since Code Origin for Spans was added in v5.24.0 on October 17th 2024 and there has not been any reports of issues related to this. Based on that, Code Origin for Spans will now be enabled by default. The main functional difference with this commit, is that the feature can now actually be turned off using the config. Code Origin for exit spans are still experimental: Since Code Origin for exit spans was never affected by this bug, we have decided to leave this feature as opt-in, which means it's going to be off by default. A new experimental config option has been introduced to allow users to enable/disable Code Origin for exit spans independently, either via an environment variable: DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED=true Or via inline config: tracer.init({ codeOriginForSpans: { experimental: { exit_spans: { enabled: true } } } })
1 parent f72dded commit b6c2bf0

File tree

8 files changed

+249
-179
lines changed

8 files changed

+249
-179
lines changed

index.d.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,18 @@ declare namespace tracer {
717717
*/
718718
maxDepth?: number,
719719
}
720-
};
720+
}
721+
722+
/**
723+
* Configuration for Code Origin for Spans.
724+
*/
725+
codeOriginForSpans?: {
726+
/**
727+
* Whether to enable Code Origin for Spans.
728+
* @default true
729+
*/
730+
enabled?: boolean
731+
}
721732

722733
/**
723734
* Configuration of the IAST. Can be a boolean as an alias to `iast.enabled`.

packages/datadog-plugin-fastify/test/code_origin.spec.js

Lines changed: 149 additions & 145 deletions
Large diffs are not rendered by default.

packages/datadog-plugin-http/test/code_origin.spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ describe('Plugin', () => {
1313
})
1414

1515
beforeEach(async () => {
16-
return agent.load('http', { server: false }, { codeOriginForSpans: { enabled: true } })
16+
return agent.load(
17+
'http',
18+
{ server: false },
19+
{ codeOriginForSpans: { experimental: { exit_spans: { enabled: true } } } }
20+
)
1721
})
1822

1923
afterEach(() => {

packages/dd-trace/src/config.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ class Config {
481481
this._setValue(defaults, 'clientIpEnabled', false)
482482
this._setValue(defaults, 'clientIpHeader', null)
483483
this._setValue(defaults, 'crashtracking.enabled', true)
484-
this._setValue(defaults, 'codeOriginForSpans.enabled', false)
484+
this._setValue(defaults, 'codeOriginForSpans.enabled', true)
485+
this._setValue(defaults, 'codeOriginForSpans.experimental.exit_spans.enabled', false)
485486
this._setValue(defaults, 'dbmPropagationMode', 'disabled')
486487
this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
487488
this._setValue(defaults, 'dogstatsd.port', '8125')
@@ -660,6 +661,7 @@ class Config {
660661
DD_APPSEC_WAF_TIMEOUT,
661662
DD_CRASHTRACKING_ENABLED,
662663
DD_CODE_ORIGIN_FOR_SPANS_ENABLED,
664+
DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED,
663665
DD_DATA_STREAMS_ENABLED,
664666
DD_DBM_PROPAGATION_MODE,
665667
DD_DOGSTATSD_HOSTNAME,
@@ -825,6 +827,11 @@ class Config {
825827
!this._isInServerlessEnvironment()
826828
))
827829
this._setBoolean(env, 'codeOriginForSpans.enabled', DD_CODE_ORIGIN_FOR_SPANS_ENABLED)
830+
this._setBoolean(
831+
env,
832+
'codeOriginForSpans.experimental.exit_spans.enabled',
833+
DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED
834+
)
828835
this._setString(env, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
829836
this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOST || DD_DOGSTATSD_HOSTNAME)
830837
this._setString(env, 'dogstatsd.port', DD_DOGSTATSD_PORT)
@@ -1029,6 +1036,11 @@ class Config {
10291036
this._setValue(opts, 'baggageMaxBytes', options.baggageMaxBytes)
10301037
this._setValue(opts, 'baggageMaxItems', options.baggageMaxItems)
10311038
this._setBoolean(opts, 'codeOriginForSpans.enabled', options.codeOriginForSpans?.enabled)
1039+
this._setBoolean(
1040+
opts,
1041+
'codeOriginForSpans.experimental.exit_spans.enabled',
1042+
options.codeOriginForSpans?.experimental?.exit_spans?.enabled
1043+
)
10321044
this._setString(opts, 'dbmPropagationMode', options.dbmPropagationMode)
10331045
if (options.dogstatsd) {
10341046
this._setString(opts, 'dogstatsd.hostname', options.dogstatsd.hostname)

packages/dd-trace/src/plugin_manager.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ module.exports = class PluginManager {
130130
site,
131131
url,
132132
headerTags,
133+
codeOriginForSpans,
133134
dbmPropagationMode,
134135
dsmEnabled,
135136
clientIpEnabled,
@@ -143,6 +144,7 @@ module.exports = class PluginManager {
143144
} = this._tracerConfig
144145

145146
const sharedConfig = {
147+
codeOriginForSpans,
146148
dbmPropagationMode,
147149
dsmEnabled,
148150
memcachedCommandEnabled,

packages/dd-trace/src/plugins/outbound.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ class OutboundPlugin extends TracingPlugin {
2828

2929
startSpan (...args) {
3030
const span = super.startSpan(...args)
31-
if (this._tracerConfig.codeOriginForSpans.enabled) {
31+
if (
32+
this._tracerConfig.codeOriginForSpans.enabled &&
33+
this._tracerConfig.codeOriginForSpans.experimental.exit_spans.enabled
34+
) {
3235
span.addTags(exitTags(this.startSpan))
3336
}
3437
return span

packages/dd-trace/test/config.spec.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ describe('Config', () => {
223223
expect(config).to.have.property('reportHostname', false)
224224
expect(config).to.have.property('scope', undefined)
225225
expect(config).to.have.property('logLevel', 'debug')
226-
expect(config).to.have.nested.property('codeOriginForSpans.enabled', false)
226+
expect(config).to.have.nested.property('codeOriginForSpans.enabled', true)
227+
expect(config).to.have.nested.property('codeOriginForSpans.experimental.exit_spans.enabled', false)
227228
expect(config).to.have.nested.property('dynamicInstrumentation.enabled', false)
228229
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactedIdentifiers', [])
229230
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactionExcludedIdentifiers', [])
@@ -305,7 +306,8 @@ describe('Config', () => {
305306
{ name: 'appsec.wafTimeout', value: 5e3, origin: 'default' },
306307
{ name: 'clientIpEnabled', value: false, origin: 'default' },
307308
{ name: 'clientIpHeader', value: null, origin: 'default' },
308-
{ name: 'codeOriginForSpans.enabled', value: false, origin: 'default' },
309+
{ name: 'codeOriginForSpans.enabled', value: true, origin: 'default' },
310+
{ name: 'codeOriginForSpans.experimental.exit_spans.enabled', value: false, origin: 'default' },
309311
{ name: 'dbmPropagationMode', value: 'disabled', origin: 'default' },
310312
{ name: 'dogstatsd.hostname', value: '127.0.0.1', origin: 'calculated' },
311313
{ name: 'dogstatsd.port', value: '8125', origin: 'default' },
@@ -440,7 +442,8 @@ describe('Config', () => {
440442
})
441443

442444
it('should initialize from environment variables', () => {
443-
process.env.DD_CODE_ORIGIN_FOR_SPANS_ENABLED = 'true'
445+
process.env.DD_CODE_ORIGIN_FOR_SPANS_ENABLED = 'false'
446+
process.env.DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED = 'true'
444447
process.env.DD_TRACE_AGENT_HOSTNAME = 'agent'
445448
process.env.DD_TRACE_AGENT_PORT = '6218'
446449
process.env.DD_DOGSTATSD_HOSTNAME = 'dsd-agent'
@@ -561,7 +564,8 @@ describe('Config', () => {
561564
expect(config).to.have.property('middlewareTracingEnabled', false)
562565
expect(config).to.have.property('runtimeMetrics', true)
563566
expect(config).to.have.property('reportHostname', true)
564-
expect(config).to.have.nested.property('codeOriginForSpans.enabled', true)
567+
expect(config).to.have.nested.property('codeOriginForSpans.enabled', false)
568+
expect(config).to.have.nested.property('codeOriginForSpans.experimental.exit_spans.enabled', true)
565569
expect(config).to.have.nested.property('dynamicInstrumentation.enabled', true)
566570
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactedIdentifiers', ['foo', 'bar'])
567571
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactionExcludedIdentifiers', ['a', 'b', 'c'])
@@ -668,7 +672,8 @@ describe('Config', () => {
668672
{ name: 'clientIpEnabled', value: true, origin: 'env_var' },
669673
{ name: 'clientIpHeader', value: 'x-true-client-ip', origin: 'env_var' },
670674
{ name: 'crashtracking.enabled', value: false, origin: 'env_var' },
671-
{ name: 'codeOriginForSpans.enabled', value: true, origin: 'env_var' },
675+
{ name: 'codeOriginForSpans.enabled', value: false, origin: 'env_var' },
676+
{ name: 'codeOriginForSpans.experimental.exit_spans.enabled', value: true, origin: 'env_var' },
672677
{ name: 'dogstatsd.hostname', value: 'dsd-agent', origin: 'env_var' },
673678
{ name: 'dogstatsd.port', value: '5218', origin: 'env_var' },
674679
{ name: 'dynamicInstrumentation.enabled', value: true, origin: 'env_var' },
@@ -886,7 +891,12 @@ describe('Config', () => {
886891
clientIpEnabled: true,
887892
clientIpHeader: 'x-true-client-ip',
888893
codeOriginForSpans: {
889-
enabled: false
894+
enabled: false,
895+
experimental: {
896+
exit_spans: {
897+
enabled: true
898+
}
899+
}
890900
},
891901
sampleRate: 0.5,
892902
rateLimit: 1000,
@@ -989,6 +999,7 @@ describe('Config', () => {
989999
expect(config).to.have.property('plugins', false)
9901000
expect(config).to.have.property('logLevel', logLevel)
9911001
expect(config).to.have.nested.property('codeOriginForSpans.enabled', false)
1002+
expect(config).to.have.nested.property('codeOriginForSpans.experimental.exit_spans.enabled', true)
9921003
expect(config).to.have.property('traceId128BitGenerationEnabled', true)
9931004
expect(config).to.have.property('traceId128BitLoggingEnabled', true)
9941005
expect(config).to.have.property('spanRemoveIntegrationFromService', true)
@@ -1048,6 +1059,7 @@ describe('Config', () => {
10481059
{ name: 'clientIpEnabled', value: true, origin: 'code' },
10491060
{ name: 'clientIpHeader', value: 'x-true-client-ip', origin: 'code' },
10501061
{ name: 'codeOriginForSpans.enabled', value: false, origin: 'code' },
1062+
{ name: 'codeOriginForSpans.experimental.exit_spans.enabled', value: true, origin: 'code' },
10511063
{ name: 'dogstatsd.hostname', value: 'agent-dsd', origin: 'code' },
10521064
{ name: 'dogstatsd.port', value: '5218', origin: 'code' },
10531065
{ name: 'dynamicInstrumentation.enabled', value: true, origin: 'code' },
@@ -1259,6 +1271,8 @@ describe('Config', () => {
12591271
process.env.DD_RUNTIME_METRICS_ENABLED = 'true'
12601272
process.env.DD_TRACE_REPORT_HOSTNAME = 'true'
12611273
process.env.DD_ENV = 'test'
1274+
process.env.DD_CODE_ORIGIN_FOR_SPANS_ENABLED = 'false'
1275+
process.env.DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED = 'true'
12621276
process.env.DD_DYNAMIC_INSTRUMENTATION_ENABLED = 'true'
12631277
process.env.DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS = 'foo,bar'
12641278
process.env.DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS = 'a,b,c'
@@ -1394,7 +1408,12 @@ describe('Config', () => {
13941408
pollInterval: 42
13951409
},
13961410
codeOriginForSpans: {
1397-
enabled: false
1411+
enabled: true,
1412+
experimental: {
1413+
exit_spans: {
1414+
enabled: false
1415+
}
1416+
}
13981417
},
13991418
traceId128BitGenerationEnabled: false,
14001419
traceId128BitLoggingEnabled: false,
@@ -1417,7 +1436,8 @@ describe('Config', () => {
14171436
expect(config).to.have.property('flushMinSpans', 500)
14181437
expect(config).to.have.property('service', 'test')
14191438
expect(config).to.have.property('version', '1.0.0')
1420-
expect(config).to.have.nested.property('codeOriginForSpans.enabled', false)
1439+
expect(config).to.have.nested.property('codeOriginForSpans.enabled', true)
1440+
expect(config).to.have.nested.property('codeOriginForSpans.experimental.exit_spans.enabled', false)
14211441
expect(config).to.have.nested.property('dynamicInstrumentation.enabled', false)
14221442
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactedIdentifiers', ['foo2', 'bar2'])
14231443
expect(config).to.have.nested.deep.property('dynamicInstrumentation.redactionExcludedIdentifiers', ['a2', 'b2'])

packages/dd-trace/test/plugins/outbound.spec.js

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -174,35 +174,49 @@ describe('OuboundPlugin', () => {
174174
instance = new OutboundPlugin(tracerStub)
175175
})
176176

177-
it('should not add exit tags to span if codeOriginForSpans.enabled is false', () => {
178-
sinon.stub(instance, '_tracerConfig').value({ codeOriginForSpans: { enabled: false } })
179-
const span = instance.startSpan('test')
180-
expect(span.addTags).to.not.have.been.called
177+
describe('disabled', () => {
178+
const configs = [
179+
{ codeOriginForSpans: { enabled: false, experimental: { exit_spans: { enabled: false } } } },
180+
{ codeOriginForSpans: { enabled: false, experimental: { exit_spans: { enabled: true } } } },
181+
{ codeOriginForSpans: { enabled: true, experimental: { exit_spans: { enabled: false } } } }
182+
]
183+
184+
for (const config of configs) {
185+
it(`should not add exit tags to span if ${JSON.stringify(config)}`, () => {
186+
sinon.stub(instance, '_tracerConfig').value(config)
187+
const span = instance.startSpan('test')
188+
expect(span.addTags).to.not.have.been.called
189+
})
190+
}
181191
})
182192

183-
it('should add exit tags to span if codeOriginForSpans.enabled is true', () => {
184-
sinon.stub(instance, '_tracerConfig').value({ codeOriginForSpans: { enabled: true } })
193+
describe('enabled', () => {
194+
const config = { codeOriginForSpans: { enabled: true, experimental: { exit_spans: { enabled: true } } } }
185195

186-
const lineNumber = String(getNextLineNumber())
187-
const span = instance.startSpan('test')
196+
it(`should add exit tags to span if ${JSON.stringify(config)}`, () => {
197+
sinon.stub(instance, '_tracerConfig').value(config)
188198

189-
expect(span.addTags).to.have.been.calledOnce
190-
const args = span.addTags.args[0]
191-
expect(args).to.have.property('length', 1)
192-
const tags = parseTags(args[0])
199+
const lineNumber = String(getNextLineNumber())
200+
const span = instance.startSpan('test')
193201

194-
expect(tags).to.nested.include({ '_dd.code_origin.type': 'exit' })
195-
expect(tags._dd.code_origin).to.have.property('frames').to.be.an('array').with.length.above(0)
202+
expect(span.addTags).to.have.been.calledOnce
203+
const args = span.addTags.args[0]
204+
expect(args).to.have.property('length', 1)
205+
const tags = parseTags(args[0])
196206

197-
for (const frame of tags._dd.code_origin.frames) {
198-
expect(frame).to.have.property('file', __filename)
199-
expect(frame).to.have.property('line').to.match(/^\d+$/)
200-
expect(frame).to.have.property('column').to.match(/^\d+$/)
201-
expect(frame).to.have.property('type').to.a('string')
202-
}
207+
expect(tags).to.nested.include({ '_dd.code_origin.type': 'exit' })
208+
expect(tags._dd.code_origin).to.have.property('frames').to.be.an('array').with.length.above(0)
203209

204-
const topFrame = tags._dd.code_origin.frames[0]
205-
expect(topFrame).to.have.property('line', lineNumber)
210+
for (const frame of tags._dd.code_origin.frames) {
211+
expect(frame).to.have.property('file', __filename)
212+
expect(frame).to.have.property('line').to.match(/^\d+$/)
213+
expect(frame).to.have.property('column').to.match(/^\d+$/)
214+
expect(frame).to.have.property('type').to.a('string')
215+
}
216+
217+
const topFrame = tags._dd.code_origin.frames[0]
218+
expect(topFrame).to.have.property('line', lineNumber)
219+
})
206220
})
207221
})
208222
})

0 commit comments

Comments
 (0)