Skip to content

Commit 05f56ab

Browse files
rochdevwatson
andcommitted
add experimental flag on plugins to disable them by default (#5985)
* add experimental flag on plugins to disable them by default * fix support for environment variable * change ordering to prioritize programmatic config * remove experimental flag from prisma plugin * remove old implementation * Update packages/datadog-instrumentations/src/helpers/register.js Co-authored-by: Thomas Watson <[email protected]> * remove remaining plugin to instrumentation mapping code --------- Co-authored-by: Thomas Watson <[email protected]>
1 parent 7486f7a commit 05f56ab

File tree

4 files changed

+42
-76
lines changed

4 files changed

+42
-76
lines changed

packages/datadog-instrumentations/src/helpers/register.js

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const log = require('../../../dd-trace/src/log')
99
const checkRequireCache = require('./check-require-cache')
1010
const telemetry = require('../../../dd-trace/src/guardrails/telemetry')
1111
const { isInServerlessEnvironment } = require('../../../dd-trace/src/serverless')
12-
const { isFalse, isTrue, normalizePluginEnvName } = require('../../../dd-trace/src/util')
1312
const { getEnvironmentVariables } = require('../../../dd-trace/src/config-helper')
1413

1514
const envs = getEnvironmentVariables()
@@ -25,22 +24,8 @@ const names = Object.keys(hooks)
2524
const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
2625

2726
const disabledInstrumentations = new Set(
28-
DD_TRACE_DISABLED_INSTRUMENTATIONS?.split(',').map(name => normalizePluginEnvName(name, true)) ?? []
27+
DD_TRACE_DISABLED_INSTRUMENTATIONS?.split(',')
2928
)
30-
const reenabledInstrumentations = new Set()
31-
32-
// Check for DD_TRACE_<INTEGRATION>_ENABLED environment variables
33-
for (const [key, value] of Object.entries(envs)) {
34-
const match = key.match(/^DD_TRACE_(.+)_ENABLED$/)
35-
if (match && value) {
36-
const integration = normalizePluginEnvName(match[1], true)
37-
if (isFalse(value)) {
38-
disabledInstrumentations.add(integration)
39-
} else if (isTrue(value)) {
40-
reenabledInstrumentations.add(integration)
41-
}
42-
}
43-
}
4429

4530
const loadChannel = channel('dd-trace:instrumentation:load')
4631

@@ -65,8 +50,7 @@ const allInstrumentations = {}
6550

6651
// TODO: make this more efficient
6752
for (const packageName of names) {
68-
const normalizedPackageName = normalizePluginEnvName(packageName, true)
69-
if (disabledInstrumentations.has(normalizedPackageName)) continue
53+
if (disabledInstrumentations.has(packageName)) continue
7054

7155
const hookOptions = {}
7256

@@ -75,10 +59,6 @@ for (const packageName of names) {
7559
if (hook !== null && typeof hook === 'object') {
7660
if (hook.serverless === false && isInServerlessEnvironment()) continue
7761

78-
// some integrations are disabled by default, but can be enabled by setting
79-
// the DD_TRACE_<INTEGRATION>_ENABLED environment variable to true
80-
if (hook.disabled && !reenabledInstrumentations.has(normalizedPackageName)) continue
81-
8262
hookOptions.internals = hook.esmFirst
8363
hook = hook.fn
8464
}

packages/datadog-instrumentations/test/helpers/register.spec.js

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ describe('register', () => {
2020

2121
hooksMock = {
2222
'@confluentinc/kafka-javascript': {
23-
disabled: true,
2423
fn: sinon.stub().returns('hooked')
2524
},
2625
'mongodb-core': {
@@ -72,54 +71,6 @@ describe('register', () => {
7271
}
7372
}
7473

75-
it('should skip hooks that are disabled by default and process enabled hooks', () => {
76-
loadRegisterWithEnv()
77-
78-
expect(HookMock.callCount).to.equal(1)
79-
expect(HookMock.args[0]).to.deep.include(['mongodb-core'], { internals: undefined })
80-
81-
runHookCallbacks(HookMock)
82-
83-
expect(hooksMock['@confluentinc/kafka-javascript'].fn).to.not.have.been.called
84-
expect(hooksMock['mongodb-core'].fn).to.have.been.called
85-
})
86-
87-
it('should enable disabled hooks when DD_TRACE_[pkg]_ENABLED is true', () => {
88-
loadRegisterWithEnv({ DD_TRACE_CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED: 'true' })
89-
90-
expect(HookMock.callCount).to.equal(2)
91-
expect(HookMock.args[0]).to.deep.include(['@confluentinc/kafka-javascript'], { internals: undefined })
92-
expect(HookMock.args[1]).to.deep.include(['mongodb-core'], { internals: undefined })
93-
94-
runHookCallbacks(HookMock)
95-
96-
expect(hooksMock['@confluentinc/kafka-javascript'].fn).to.have.been.called
97-
expect(hooksMock['mongodb-core'].fn).to.have.been.called
98-
})
99-
100-
it('should not enable disabled hooks when DD_TRACE_[pkg]_ENABLED is false', () => {
101-
loadRegisterWithEnv({ DD_TRACE_CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED: 'false' })
102-
103-
expect(HookMock.callCount).to.equal(1)
104-
expect(HookMock.args[0]).to.deep.include(['mongodb-core'], { internals: undefined })
105-
106-
runHookCallbacks(HookMock)
107-
108-
expect(hooksMock['@confluentinc/kafka-javascript'].fn).to.not.have.been.called
109-
expect(hooksMock['mongodb-core'].fn).to.have.been.called
110-
})
111-
112-
it('should disable hooks that are disabled by DD_TRACE_[pkg]_ENABLED=false', () => {
113-
loadRegisterWithEnv({ DD_TRACE_MONGODB_CORE_ENABLED: 'false' })
114-
115-
expect(HookMock.callCount).to.equal(0)
116-
117-
runHookCallbacks(HookMock)
118-
119-
expect(hooksMock['@confluentinc/kafka-javascript'].fn).to.not.have.been.called
120-
expect(hooksMock['mongodb-core'].fn).to.not.have.been.called
121-
})
122-
12374
it('should disable hooks that are disabled by DD_TRACE_DISABLED_INSTRUMENTATIONS', () => {
12475
loadRegisterWithEnv({ DD_TRACE_DISABLED_INSTRUMENTATIONS: 'mongodb-core,@confluentinc/kafka-javascript' })
12576

packages/dd-trace/src/plugin_manager.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const { channel } = require('dc-polyfill')
4-
const { isFalse, normalizePluginEnvName } = require('./util')
4+
const { isFalse, isTrue, normalizePluginEnvName } = require('./util')
55
const plugins = require('./plugins')
66
const log = require('./log')
77
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
@@ -32,8 +32,7 @@ loadChannel.subscribe(({ name }) => {
3232
function maybeEnable (Plugin) {
3333
if (!Plugin || typeof Plugin !== 'function') return
3434
if (!pluginClasses[Plugin.id]) {
35-
const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
36-
const enabled = getEnvironmentVariable(normalizePluginEnvName(envName))
35+
const enabled = getEnvEnabled(Plugin)
3736

3837
// TODO: remove the need to load the plugin class in order to disable the plugin
3938
if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
@@ -46,6 +45,11 @@ function maybeEnable (Plugin) {
4645
}
4746
}
4847

48+
function getEnvEnabled (Plugin) {
49+
const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
50+
return getEnvironmentVariable(normalizePluginEnvName(envName))
51+
}
52+
4953
// TODO this must always be a singleton.
5054
module.exports = class PluginManager {
5155
constructor (tracer) {
@@ -74,7 +78,7 @@ module.exports = class PluginManager {
7478
this._pluginsByName[name] = new Plugin(this._tracer, this._tracerConfig)
7579
}
7680
const pluginConfig = this._configsByName[name] || {
77-
enabled: this._tracerConfig.plugins !== false
81+
enabled: this._tracerConfig.plugins !== false && (!Plugin.experimental || isTrue(getEnvEnabled(Plugin)))
7882
}
7983

8084
// extracts predetermined configuration from tracer and combines it with plugin-specific config

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('Plugin Manager', () => {
1616
let Four
1717
let Five
1818
let Six
19+
let Eight
1920
let pm
2021

2122
beforeEach(() => {
@@ -45,7 +46,11 @@ describe('Plugin Manager', () => {
4546
six: class Six extends FakePlugin {
4647
static id = 'six'
4748
},
48-
seven: {}
49+
seven: {},
50+
eight: class Eight extends FakePlugin {
51+
static experimental = true
52+
static id = 'eight'
53+
}
4954
}
5055

5156
Two = plugins.two
@@ -59,6 +64,9 @@ describe('Plugin Manager', () => {
5964
Six = plugins.six
6065
Six.prototype.configure = sinon.spy()
6166

67+
Eight = plugins.eight
68+
Eight.prototype.configure = sinon.spy()
69+
6270
process.env.DD_TRACE_DISABLED_PLUGINS = 'five,six,seven'
6371

6472
PluginManager = proxyquire.noPreserveCache()('../src/plugin_manager', {
@@ -75,6 +83,7 @@ describe('Plugin Manager', () => {
7583

7684
afterEach(() => {
7785
delete process.env.DD_TRACE_DISABLED_PLUGINS
86+
delete process.env.DD_TRACE_EIGHT_ENABLED
7887
pm.destroy()
7988
})
8089

@@ -265,6 +274,28 @@ describe('Plugin Manager', () => {
265274
})
266275
})
267276

277+
describe('with an experimental plugin', () => {
278+
it('should disable the plugin by default', () => {
279+
pm.configure()
280+
loadChannel.publish({ name: 'eight' })
281+
expect(Eight.prototype.configure).to.have.been.calledWithMatch({ enabled: false })
282+
})
283+
284+
it('should enable the plugin when configured programmatically', () => {
285+
pm.configure()
286+
pm.configurePlugin('eight')
287+
loadChannel.publish({ name: 'eight' })
288+
expect(Eight.prototype.configure).to.have.been.calledWithMatch({ enabled: true })
289+
})
290+
291+
it('should enable the plugin when configured with an environment variable', () => {
292+
process.env.DD_TRACE_EIGHT_ENABLED = 'true'
293+
pm.configure()
294+
loadChannel.publish({ name: 'eight' })
295+
expect(Eight.prototype.configure).to.have.been.calledWithMatch({ enabled: true })
296+
})
297+
})
298+
268299
it('instantiates plugin classes', () => {
269300
pm.configure()
270301
loadChannel.publish({ name: 'two' })

0 commit comments

Comments
 (0)