dd-trace 5.41.1 → 5.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +1 -0
- package/index.d.ts +8 -1
- package/package.json +6 -3
- package/packages/datadog-esbuild/index.js +3 -1
- package/packages/datadog-instrumentations/src/cucumber.js +37 -29
- package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +102 -0
- package/packages/datadog-instrumentations/src/{check_require_cache.js → helpers/check-require-cache.js} +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +4 -1
- package/packages/datadog-instrumentations/src/jest.js +72 -49
- package/packages/datadog-instrumentations/src/langchain.js +29 -10
- package/packages/datadog-instrumentations/src/mocha/main.js +53 -34
- package/packages/datadog-instrumentations/src/mocha/utils.js +34 -24
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -8
- package/packages/datadog-instrumentations/src/openai.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +37 -30
- package/packages/datadog-instrumentations/src/vitest.js +64 -29
- package/packages/datadog-plugin-cucumber/src/index.js +13 -4
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +41 -35
- package/packages/datadog-plugin-cypress/src/plugin.js +10 -0
- package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +195 -0
- package/packages/datadog-plugin-jest/src/index.js +18 -6
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +4 -1
- package/packages/datadog-plugin-mocha/src/index.js +13 -4
- package/packages/datadog-plugin-playwright/src/index.js +19 -5
- package/packages/datadog-plugin-vitest/src/index.js +41 -17
- package/packages/dd-trace/src/appsec/api_security_sampler.js +7 -3
- package/packages/dd-trace/src/appsec/blocking.js +23 -16
- package/packages/dd-trace/src/appsec/graphql.js +13 -6
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -1
- package/packages/dd-trace/src/appsec/reporter.js +35 -0
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -3
- package/packages/dd-trace/src/appsec/telemetry/index.js +5 -1
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -1
- package/packages/dd-trace/src/appsec/telemetry/waf.js +16 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +43 -13
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -14
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +1 -2
- package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -1
- package/packages/dd-trace/src/ci-visibility/{quarantined-tests/get-quarantined-tests.js → test-management/get-test-management-tests.js} +5 -5
- package/packages/dd-trace/src/config.js +11 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -2
- package/packages/dd-trace/src/lambda/runtime/patch.js +5 -3
- package/packages/dd-trace/src/lambda/runtime/ritm.js +13 -18
- package/packages/dd-trace/src/llmobs/plugins/openai.js +27 -2
- package/packages/dd-trace/src/opentracing/span.js +3 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +38 -10
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/git.js +7 -3
- package/packages/dd-trace/src/plugins/util/test.js +10 -0
- package/packages/dd-trace/src/plugins/util/web.js +5 -2
- package/packages/dd-trace/src/priority_sampler.js +116 -15
- package/packages/dd-trace/src/sampler.js +9 -0
- package/packages/dd-trace/src/standalone/product.js +6 -2
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/telemetry/metrics.js +0 -8
- package/packages/dd-trace/src/tracer.js +1 -1
- /package/packages/datadog-instrumentations/src/{utils/src → helpers}/extract-package-and-module-path.js +0 -0
|
@@ -27,7 +27,10 @@ const {
|
|
|
27
27
|
DI_DEBUG_ERROR_PREFIX,
|
|
28
28
|
DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX,
|
|
29
29
|
DI_DEBUG_ERROR_FILE_SUFFIX,
|
|
30
|
-
DI_DEBUG_ERROR_LINE_SUFFIX
|
|
30
|
+
DI_DEBUG_ERROR_LINE_SUFFIX,
|
|
31
|
+
DD_CAPABILITIES_EARLY_FLAKE_DETECTION,
|
|
32
|
+
DD_CAPABILITIES_AUTO_TEST_RETRIES,
|
|
33
|
+
DD_CAPABILITIES_TEST_IMPACT_ANALYSIS
|
|
31
34
|
} = require('./util/test')
|
|
32
35
|
const Plugin = require('./plugin')
|
|
33
36
|
const { COMPONENT } = require('../constants')
|
|
@@ -42,6 +45,19 @@ const { CI_PROVIDER_NAME, GIT_REPOSITORY_URL, GIT_COMMIT_SHA, GIT_BRANCH, CI_WOR
|
|
|
42
45
|
const { OS_VERSION, OS_PLATFORM, OS_ARCHITECTURE, RUNTIME_NAME, RUNTIME_VERSION } = require('./util/env')
|
|
43
46
|
const getDiClient = require('../ci-visibility/dynamic-instrumentation')
|
|
44
47
|
|
|
48
|
+
const UNSUPPORTED_TIA_FRAMEWORKS = ['playwright', 'vitest']
|
|
49
|
+
const UNSUPPORTED_TIA_FRAMEWORKS_PARALLEL_MODE = ['cucumber', 'mocha']
|
|
50
|
+
|
|
51
|
+
function isTiaSupported (testFramework, isParallel) {
|
|
52
|
+
if (UNSUPPORTED_TIA_FRAMEWORKS.includes(testFramework)) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
if (isParallel && UNSUPPORTED_TIA_FRAMEWORKS_PARALLEL_MODE.includes(testFramework)) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
45
61
|
module.exports = class CiPlugin extends Plugin {
|
|
46
62
|
constructor (...args) {
|
|
47
63
|
super(...args)
|
|
@@ -49,7 +65,7 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
49
65
|
this.fileLineToProbeId = new Map()
|
|
50
66
|
this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
|
|
51
67
|
|
|
52
|
-
this.addSub(`ci:${this.constructor.id}:library-configuration`, ({ onDone }) => {
|
|
68
|
+
this.addSub(`ci:${this.constructor.id}:library-configuration`, ({ onDone, isParallel }) => {
|
|
53
69
|
if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
|
|
54
70
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
55
71
|
}
|
|
@@ -59,6 +75,18 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
59
75
|
} else {
|
|
60
76
|
this.libraryConfig = libraryConfig
|
|
61
77
|
}
|
|
78
|
+
const { isItrEnabled, isEarlyFlakeDetectionEnabled, isFlakyTestRetriesEnabled } = this.libraryConfig || {}
|
|
79
|
+
const metadataTags = {
|
|
80
|
+
test: {
|
|
81
|
+
[DD_CAPABILITIES_TEST_IMPACT_ANALYSIS]: isItrEnabled ? 'true' : 'false',
|
|
82
|
+
[DD_CAPABILITIES_EARLY_FLAKE_DETECTION]: isEarlyFlakeDetectionEnabled ? 'true' : 'false',
|
|
83
|
+
[DD_CAPABILITIES_AUTO_TEST_RETRIES]: isFlakyTestRetriesEnabled ? 'true' : 'false'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!isTiaSupported(this.constructor.id, isParallel)) {
|
|
87
|
+
metadataTags.test[DD_CAPABILITIES_TEST_IMPACT_ANALYSIS] = undefined
|
|
88
|
+
}
|
|
89
|
+
this.tracer._exporter.addMetadataTags(metadataTags)
|
|
62
90
|
onDone({ err, libraryConfig })
|
|
63
91
|
})
|
|
64
92
|
})
|
|
@@ -96,8 +124,8 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
96
124
|
}
|
|
97
125
|
}
|
|
98
126
|
// tracer might not be initialized correctly
|
|
99
|
-
if (this.tracer._exporter.
|
|
100
|
-
this.tracer._exporter.
|
|
127
|
+
if (this.tracer._exporter.addMetadataTags) {
|
|
128
|
+
this.tracer._exporter.addMetadataTags(metadataTags)
|
|
101
129
|
}
|
|
102
130
|
|
|
103
131
|
this.testSessionSpan = this.tracer.startSpan(`${this.constructor.id}.test_session`, {
|
|
@@ -166,16 +194,16 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
166
194
|
})
|
|
167
195
|
})
|
|
168
196
|
|
|
169
|
-
this.addSub(`ci:${this.constructor.id}:
|
|
170
|
-
if (!this.tracer._exporter?.
|
|
197
|
+
this.addSub(`ci:${this.constructor.id}:test-management-tests`, ({ onDone }) => {
|
|
198
|
+
if (!this.tracer._exporter?.getTestManagementTests) {
|
|
171
199
|
return onDone({ err: new Error('Test optimization was not initialized correctly') })
|
|
172
200
|
}
|
|
173
|
-
this.tracer._exporter.
|
|
201
|
+
this.tracer._exporter.getTestManagementTests(this.testConfiguration, (err, testManagementTests) => {
|
|
174
202
|
if (err) {
|
|
175
|
-
log.error('
|
|
176
|
-
this.libraryConfig.
|
|
203
|
+
log.error('Test management tests could not be fetched. %s', err.message)
|
|
204
|
+
this.libraryConfig.isTestManagementEnabled = false
|
|
177
205
|
}
|
|
178
|
-
onDone({ err,
|
|
206
|
+
onDone({ err, testManagementTests })
|
|
179
207
|
})
|
|
180
208
|
})
|
|
181
209
|
}
|
|
@@ -9,6 +9,7 @@ module.exports = {
|
|
|
9
9
|
get '@elastic/elasticsearch' () { return require('../../../datadog-plugin-elasticsearch/src') },
|
|
10
10
|
get '@elastic/transport' () { return require('../../../datadog-plugin-elasticsearch/src') },
|
|
11
11
|
get '@google-cloud/pubsub' () { return require('../../../datadog-plugin-google-cloud-pubsub/src') },
|
|
12
|
+
get '@google-cloud/vertexai' () { return require('../../../datadog-plugin-google-cloud-vertexai/src') },
|
|
12
13
|
get '@grpc/grpc-js' () { return require('../../../datadog-plugin-grpc/src') },
|
|
13
14
|
get '@hapi/hapi' () { return require('../../../datadog-plugin-hapi/src') },
|
|
14
15
|
get '@jest/core' () { return require('../../../datadog-plugin-jest/src') },
|
|
@@ -35,7 +35,8 @@ function sanitizedExec (
|
|
|
35
35
|
flags,
|
|
36
36
|
operationMetric,
|
|
37
37
|
durationMetric,
|
|
38
|
-
errorMetric
|
|
38
|
+
errorMetric,
|
|
39
|
+
shouldTrim = true
|
|
39
40
|
) {
|
|
40
41
|
const store = storage('legacy').getStore()
|
|
41
42
|
storage('legacy').enterWith({ noop: true })
|
|
@@ -48,7 +49,10 @@ function sanitizedExec (
|
|
|
48
49
|
startTime = Date.now()
|
|
49
50
|
}
|
|
50
51
|
try {
|
|
51
|
-
|
|
52
|
+
let result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString()
|
|
53
|
+
if (shouldTrim) {
|
|
54
|
+
result = result.replace(/(\r\n|\n|\r)/gm, '')
|
|
55
|
+
}
|
|
52
56
|
if (durationMetric) {
|
|
53
57
|
distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
|
|
54
58
|
}
|
|
@@ -330,7 +334,7 @@ function getGitMetadata (ciMetadata) {
|
|
|
330
334
|
|
|
331
335
|
const tags = {
|
|
332
336
|
[GIT_COMMIT_MESSAGE]:
|
|
333
|
-
commitMessage || sanitizedExec('git', ['show', '-s', '--format=%
|
|
337
|
+
commitMessage || sanitizedExec('git', ['show', '-s', '--format=%B'], null, null, null, false),
|
|
334
338
|
[GIT_BRANCH]: branch || sanitizedExec('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
|
|
335
339
|
[GIT_COMMIT_SHA]: commitSHA || sanitizedExec('git', ['rev-parse', 'HEAD']),
|
|
336
340
|
[CI_WORKSPACE_PATH]: ciWorkspacePath || sanitizedExec('git', ['rev-parse', '--show-toplevel'])
|
|
@@ -99,6 +99,11 @@ const MOCHA_WORKER_TRACE_PAYLOAD_CODE = 80
|
|
|
99
99
|
const EFD_STRING = "Retried by Datadog's Early Flake Detection"
|
|
100
100
|
const EFD_TEST_NAME_REGEX = new RegExp(EFD_STRING + ' \\(#\\d+\\): ', 'g')
|
|
101
101
|
|
|
102
|
+
// Library Capabilities Tagging
|
|
103
|
+
const DD_CAPABILITIES_TEST_IMPACT_ANALYSIS = '_dd.library_capabilities.test_impact_analysis'
|
|
104
|
+
const DD_CAPABILITIES_EARLY_FLAKE_DETECTION = '_dd.library_capabilities.early_flake_detection'
|
|
105
|
+
const DD_CAPABILITIES_AUTO_TEST_RETRIES = '_dd.library_capabilities.auto_test_retries'
|
|
106
|
+
|
|
102
107
|
const TEST_LEVEL_EVENT_TYPES = [
|
|
103
108
|
'test',
|
|
104
109
|
'test_suite_end',
|
|
@@ -115,6 +120,7 @@ const DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX = 'snapshot_id'
|
|
|
115
120
|
const DI_DEBUG_ERROR_FILE_SUFFIX = 'file'
|
|
116
121
|
const DI_DEBUG_ERROR_LINE_SUFFIX = 'line'
|
|
117
122
|
|
|
123
|
+
const TEST_MANAGEMENT_IS_DISABLED = 'test.test_management.is_test_disabled'
|
|
118
124
|
const TEST_MANAGEMENT_IS_QUARANTINED = 'test.test_management.is_quarantined'
|
|
119
125
|
const TEST_MANAGEMENT_ENABLED = 'test.test_management.enabled'
|
|
120
126
|
|
|
@@ -193,6 +199,9 @@ module.exports = {
|
|
|
193
199
|
TEST_BROWSER_NAME,
|
|
194
200
|
TEST_BROWSER_VERSION,
|
|
195
201
|
getTestSessionName,
|
|
202
|
+
DD_CAPABILITIES_TEST_IMPACT_ANALYSIS,
|
|
203
|
+
DD_CAPABILITIES_EARLY_FLAKE_DETECTION,
|
|
204
|
+
DD_CAPABILITIES_AUTO_TEST_RETRIES,
|
|
196
205
|
TEST_LEVEL_EVENT_TYPES,
|
|
197
206
|
getNumFromKnownTests,
|
|
198
207
|
getFileAndLineNumberFromError,
|
|
@@ -203,6 +212,7 @@ module.exports = {
|
|
|
203
212
|
DI_DEBUG_ERROR_LINE_SUFFIX,
|
|
204
213
|
getFormattedError,
|
|
205
214
|
DD_TEST_IS_USER_PROVIDED_SERVICE,
|
|
215
|
+
TEST_MANAGEMENT_IS_DISABLED,
|
|
206
216
|
TEST_MANAGEMENT_IS_QUARANTINED,
|
|
207
217
|
TEST_MANAGEMENT_ENABLED
|
|
208
218
|
}
|
|
@@ -8,10 +8,11 @@ const tags = require('../../../../../ext/tags')
|
|
|
8
8
|
const types = require('../../../../../ext/types')
|
|
9
9
|
const kinds = require('../../../../../ext/kinds')
|
|
10
10
|
const urlFilter = require('./urlfilter')
|
|
11
|
-
const { extractIp } = require('./ip_extractor')
|
|
12
11
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
|
|
13
12
|
const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
|
|
14
13
|
|
|
14
|
+
let extractIp
|
|
15
|
+
|
|
15
16
|
const WEB = types.WEB
|
|
16
17
|
const SERVER = kinds.SERVER
|
|
17
18
|
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
@@ -48,6 +49,8 @@ const web = {
|
|
|
48
49
|
const middleware = getMiddlewareSetting(config)
|
|
49
50
|
const queryStringObfuscation = getQsObfuscator(config)
|
|
50
51
|
|
|
52
|
+
extractIp = config.clientIpEnabled && require('./ip_extractor').extractIp
|
|
53
|
+
|
|
51
54
|
return {
|
|
52
55
|
...config,
|
|
53
56
|
headers,
|
|
@@ -460,7 +463,7 @@ function addRequestTags (context, spanType) {
|
|
|
460
463
|
})
|
|
461
464
|
|
|
462
465
|
// if client ip has already been set by appsec, no need to run it again
|
|
463
|
-
if (
|
|
466
|
+
if (extractIp && !span.context()._tags.hasOwnProperty(HTTP_CLIENT_IP)) {
|
|
464
467
|
const clientIp = extractIp(config, req)
|
|
465
468
|
|
|
466
469
|
if (clientIp) {
|
|
@@ -39,28 +39,54 @@ const DEFAULT_KEY = 'service:,env:'
|
|
|
39
39
|
|
|
40
40
|
const defaultSampler = new Sampler(AUTO_KEEP)
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* from config.js
|
|
44
|
+
* @typedef { sampleRate: number, provenance: string, rateLimit: number, rules: SamplingRule[] } SamplingConfig
|
|
45
|
+
*
|
|
46
|
+
* empirically defined
|
|
47
|
+
* @typedef {2|-1|1|0} SamplingPriority
|
|
48
|
+
*/
|
|
42
49
|
class PrioritySampler {
|
|
50
|
+
/**
|
|
51
|
+
* @param env {string}
|
|
52
|
+
* @param config {SamplingConfig}
|
|
53
|
+
*/
|
|
43
54
|
constructor (env, config) {
|
|
44
55
|
this.configure(env, config)
|
|
45
56
|
this.update({})
|
|
46
57
|
}
|
|
47
58
|
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param env {string}
|
|
62
|
+
* @param opts {SamplingConfig}
|
|
63
|
+
*/
|
|
48
64
|
configure (env, opts = {}) {
|
|
49
65
|
const { sampleRate, provenance = undefined, rateLimit = 100, rules = [] } = opts
|
|
50
66
|
this._env = env
|
|
51
|
-
this._rules = this
|
|
67
|
+
this._rules = this.#_normalizeRules(rules, sampleRate, rateLimit, provenance)
|
|
52
68
|
this._limiter = new RateLimiter(rateLimit)
|
|
53
69
|
|
|
54
70
|
log.trace(env, opts)
|
|
55
71
|
setSamplingRules(this._rules)
|
|
56
72
|
}
|
|
57
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param span {DatadogSpan}
|
|
76
|
+
* @returns {boolean}
|
|
77
|
+
*/
|
|
58
78
|
isSampled (span) {
|
|
59
79
|
const priority = this._getPriorityFromAuto(span)
|
|
60
80
|
log.trace(span)
|
|
61
81
|
return priority === USER_KEEP || priority === AUTO_KEEP
|
|
62
82
|
}
|
|
63
83
|
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
* @param span {DatadogSpan}
|
|
87
|
+
* @param auto {boolean}
|
|
88
|
+
* @returns {void}
|
|
89
|
+
*/
|
|
64
90
|
sample (span, auto = true) {
|
|
65
91
|
if (!span) return
|
|
66
92
|
|
|
@@ -84,17 +110,20 @@ class PrioritySampler {
|
|
|
84
110
|
return
|
|
85
111
|
}
|
|
86
112
|
|
|
87
|
-
this
|
|
113
|
+
this.#_addDecisionMaker(root)
|
|
88
114
|
}
|
|
89
115
|
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param rates {Record<string, number>}
|
|
119
|
+
* @returns {void}
|
|
120
|
+
*/
|
|
90
121
|
update (rates) {
|
|
91
122
|
const samplers = {}
|
|
92
123
|
|
|
93
124
|
for (const key in rates) {
|
|
94
125
|
const rate = rates[key]
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
samplers[key] = sampler
|
|
126
|
+
samplers[key] = new Sampler(rate)
|
|
98
127
|
}
|
|
99
128
|
|
|
100
129
|
samplers[DEFAULT_KEY] = samplers[DEFAULT_KEY] || defaultSampler
|
|
@@ -104,6 +133,11 @@ class PrioritySampler {
|
|
|
104
133
|
log.trace(rates)
|
|
105
134
|
}
|
|
106
135
|
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param samplingPriority {SamplingPriority}
|
|
139
|
+
* @returns {boolean}
|
|
140
|
+
*/
|
|
107
141
|
validate (samplingPriority) {
|
|
108
142
|
switch (samplingPriority) {
|
|
109
143
|
case USER_REJECT:
|
|
@@ -116,6 +150,12 @@ class PrioritySampler {
|
|
|
116
150
|
}
|
|
117
151
|
}
|
|
118
152
|
|
|
153
|
+
/**
|
|
154
|
+
*
|
|
155
|
+
* @param span {DatadogSpan}
|
|
156
|
+
* @param samplingPriority {SamplingPriority}
|
|
157
|
+
* @param product {import('./standalone/product').PRODUCTS}
|
|
158
|
+
*/
|
|
119
159
|
setPriority (span, samplingPriority, product) {
|
|
120
160
|
if (!span || !this.validate(samplingPriority)) return
|
|
121
161
|
|
|
@@ -134,23 +174,40 @@ class PrioritySampler {
|
|
|
134
174
|
|
|
135
175
|
log.trace(span, samplingPriority, mechanism)
|
|
136
176
|
|
|
137
|
-
this
|
|
177
|
+
this.#_addDecisionMaker(root)
|
|
138
178
|
}
|
|
139
179
|
|
|
180
|
+
/**
|
|
181
|
+
*
|
|
182
|
+
* @param span {DatadogSpan}
|
|
183
|
+
* @returns {DatadogSpanContext}
|
|
184
|
+
*/
|
|
140
185
|
_getContext (span) {
|
|
141
186
|
return typeof span.context === 'function' ? span.context() : span
|
|
142
187
|
}
|
|
143
188
|
|
|
189
|
+
/**
|
|
190
|
+
*
|
|
191
|
+
* @param span {DatadogSpan}
|
|
192
|
+
* @returns {SamplingPriority}
|
|
193
|
+
*/
|
|
144
194
|
_getPriorityFromAuto (span) {
|
|
145
195
|
const context = this._getContext(span)
|
|
146
|
-
const rule = this
|
|
196
|
+
const rule = this.#_findRule(span)
|
|
147
197
|
|
|
148
198
|
return rule
|
|
149
|
-
? this
|
|
150
|
-
: this
|
|
199
|
+
? this.#_getPriorityByRule(context, rule)
|
|
200
|
+
: this.#_getPriorityByAgent(context)
|
|
151
201
|
}
|
|
152
202
|
|
|
153
|
-
|
|
203
|
+
/**
|
|
204
|
+
*
|
|
205
|
+
* @param tags {Record<string, symbol | unknown>}
|
|
206
|
+
* Included for compatibility with {@link import('./standalone/tracesource_priority_sampler')._getPriorityFromTags}
|
|
207
|
+
* @param _context {DatadogSpanContext}
|
|
208
|
+
* @returns {SamplingPriority}
|
|
209
|
+
*/
|
|
210
|
+
_getPriorityFromTags (tags, _context) {
|
|
154
211
|
if (hasOwn(tags, MANUAL_KEEP) && tags[MANUAL_KEEP] !== false) {
|
|
155
212
|
return USER_KEEP
|
|
156
213
|
} else if (hasOwn(tags, MANUAL_DROP) && tags[MANUAL_DROP] !== false) {
|
|
@@ -166,7 +223,13 @@ class PrioritySampler {
|
|
|
166
223
|
}
|
|
167
224
|
}
|
|
168
225
|
|
|
169
|
-
|
|
226
|
+
/**
|
|
227
|
+
*
|
|
228
|
+
* @param context {DatadogSpanContext}
|
|
229
|
+
* @param rule {SamplingRule}
|
|
230
|
+
* @returns {SamplingPriority}
|
|
231
|
+
*/
|
|
232
|
+
#_getPriorityByRule (context, rule) {
|
|
170
233
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
171
234
|
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
172
235
|
if (rule.provenance === 'customer') context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_USER
|
|
@@ -177,6 +240,12 @@ class PrioritySampler {
|
|
|
177
240
|
: USER_REJECT
|
|
178
241
|
}
|
|
179
242
|
|
|
243
|
+
/**
|
|
244
|
+
*
|
|
245
|
+
* @param context {DatadogSpanContext}
|
|
246
|
+
* @returns {boolean}
|
|
247
|
+
* @private
|
|
248
|
+
*/
|
|
180
249
|
_isSampledByRateLimit (context) {
|
|
181
250
|
const allowed = this._limiter.isAllowed()
|
|
182
251
|
|
|
@@ -185,7 +254,13 @@ class PrioritySampler {
|
|
|
185
254
|
return allowed
|
|
186
255
|
}
|
|
187
256
|
|
|
188
|
-
|
|
257
|
+
/**
|
|
258
|
+
*
|
|
259
|
+
* @param context {DatadogSpanContext}
|
|
260
|
+
* @returns {SamplingPriority}
|
|
261
|
+
* @private
|
|
262
|
+
*/
|
|
263
|
+
#_getPriorityByAgent (context) {
|
|
189
264
|
const key = `service:${context._tags[SERVICE_NAME]},env:${this._env}`
|
|
190
265
|
const sampler = this._samplers[key] || this._samplers[DEFAULT_KEY]
|
|
191
266
|
|
|
@@ -200,7 +275,13 @@ class PrioritySampler {
|
|
|
200
275
|
return sampler.isSampled(context) ? AUTO_KEEP : AUTO_REJECT
|
|
201
276
|
}
|
|
202
277
|
|
|
203
|
-
|
|
278
|
+
/**
|
|
279
|
+
*
|
|
280
|
+
* @param span {DatadogSpan}
|
|
281
|
+
* @private
|
|
282
|
+
* @returns {void}
|
|
283
|
+
*/
|
|
284
|
+
#_addDecisionMaker (span) {
|
|
204
285
|
const context = span.context()
|
|
205
286
|
const trace = context._trace
|
|
206
287
|
const priority = context._sampling.priority
|
|
@@ -215,7 +296,16 @@ class PrioritySampler {
|
|
|
215
296
|
}
|
|
216
297
|
}
|
|
217
298
|
|
|
218
|
-
|
|
299
|
+
/**
|
|
300
|
+
*
|
|
301
|
+
* @param rules {SamplingRule[]}
|
|
302
|
+
* @param sampleRate {number}
|
|
303
|
+
* @param rateLimit {number}
|
|
304
|
+
* @param provenance {string}
|
|
305
|
+
* @returns {SamplingRule[]}
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
308
|
+
#_normalizeRules (rules, sampleRate, rateLimit, provenance) {
|
|
219
309
|
rules = [].concat(rules || [])
|
|
220
310
|
|
|
221
311
|
return rules
|
|
@@ -225,12 +315,23 @@ class PrioritySampler {
|
|
|
225
315
|
.map(SamplingRule.from)
|
|
226
316
|
}
|
|
227
317
|
|
|
228
|
-
|
|
318
|
+
/**
|
|
319
|
+
*
|
|
320
|
+
* @param span {DatadogSpan}
|
|
321
|
+
* @returns {SamplingRule}
|
|
322
|
+
* @private
|
|
323
|
+
*/
|
|
324
|
+
#_findRule (span) {
|
|
229
325
|
for (const rule of this._rules) {
|
|
230
326
|
if (rule.match(span)) return rule
|
|
231
327
|
}
|
|
232
328
|
}
|
|
233
329
|
|
|
330
|
+
/**
|
|
331
|
+
*
|
|
332
|
+
* @param span {DatadogSpan}
|
|
333
|
+
* @param product {import('./standalone/product').PRODUCTS}
|
|
334
|
+
*/
|
|
234
335
|
static keepTrace (span, product) {
|
|
235
336
|
span?._prioritySampler?.setPriority(span, USER_KEEP, product)
|
|
236
337
|
}
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
class Sampler {
|
|
4
|
+
/**
|
|
5
|
+
* @param rate {number}
|
|
6
|
+
*/
|
|
4
7
|
constructor (rate) {
|
|
5
8
|
this._rate = rate
|
|
6
9
|
}
|
|
7
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @returns {number}
|
|
13
|
+
*/
|
|
8
14
|
rate () {
|
|
9
15
|
return this._rate
|
|
10
16
|
}
|
|
11
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
12
21
|
isSampled () {
|
|
13
22
|
return this._rate === 1 || Math.random() < this._rate
|
|
14
23
|
}
|
|
@@ -13,12 +13,16 @@ function getProductRateLimiter (config) {
|
|
|
13
13
|
return dropAll
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const PRODUCTS = {
|
|
17
17
|
APM: { id: 1 << 0 },
|
|
18
18
|
ASM: { id: 1 << 1, mechanism: SAMPLING_MECHANISM_APPSEC },
|
|
19
19
|
DSM: { id: 1 << 2 },
|
|
20
20
|
DJM: { id: 1 << 3 },
|
|
21
|
-
DBM: { id: 1 << 4 }
|
|
21
|
+
DBM: { id: 1 << 4 }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
...PRODUCTS,
|
|
22
26
|
|
|
23
27
|
getProductRateLimiter
|
|
24
28
|
}
|
|
@@ -86,7 +86,8 @@ function tracerInfo () {
|
|
|
86
86
|
|
|
87
87
|
out.log_injection_enabled = !!config.logInjection
|
|
88
88
|
out.runtime_metrics_enabled = !!config.runtimeMetrics
|
|
89
|
-
|
|
89
|
+
const profilingEnabled = config.profiling?.enabled
|
|
90
|
+
out.profiling_enabled = profilingEnabled === 'true' || profilingEnabled === 'auto'
|
|
90
91
|
Object.assign(out, getIntegrationsAndAnalytics())
|
|
91
92
|
|
|
92
93
|
out.appsec_enabled = !!config.appsec.enabled
|
|
@@ -27,19 +27,11 @@ function hasPoints (metric) {
|
|
|
27
27
|
return metric.points.length > 0
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
let versionTag
|
|
31
|
-
|
|
32
30
|
class Metric {
|
|
33
31
|
constructor (namespace, metric, common, tags) {
|
|
34
32
|
this.namespace = namespace.toString()
|
|
35
33
|
this.metric = common ? metric : `nodejs.${metric}`
|
|
36
34
|
this.tags = tagArray(tags)
|
|
37
|
-
if (common) {
|
|
38
|
-
if (versionTag === undefined) {
|
|
39
|
-
versionTag = `version:${process.version}`
|
|
40
|
-
}
|
|
41
|
-
this.tags.push(versionTag)
|
|
42
|
-
}
|
|
43
35
|
this.common = common
|
|
44
36
|
|
|
45
37
|
this.points = []
|
|
@@ -7,7 +7,7 @@ const { isError } = require('./util')
|
|
|
7
7
|
const { setStartupLogConfig } = require('./startup-log')
|
|
8
8
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
9
9
|
const { DataStreamsCheckpointer, DataStreamsManager, DataStreamsProcessor } = require('./datastreams')
|
|
10
|
-
const { flushStartupLogs } = require('../../datadog-instrumentations/src/
|
|
10
|
+
const { flushStartupLogs } = require('../../datadog-instrumentations/src/helpers/check-require-cache')
|
|
11
11
|
const log = require('./log/writer')
|
|
12
12
|
|
|
13
13
|
const SPAN_TYPE = tags.SPAN_TYPE
|
|
File without changes
|