dd-trace 1.6.0 → 1.7.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/NOTICE +4 -0
- package/ci/init.js +5 -1
- package/ci/jest/env.js +5 -1
- package/index.d.ts +1 -1
- package/package.json +2 -1
- package/packages/datadog-plugin-cucumber/src/index.js +4 -4
- package/packages/datadog-plugin-cypress/src/plugin.js +12 -2
- package/packages/datadog-plugin-cypress/src/support.js +21 -6
- package/packages/datadog-plugin-jest/src/jest-environment.js +4 -4
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +3 -2
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/constants.js +6 -1
- package/packages/dd-trace/src/format.js +12 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +34 -0
- package/packages/dd-trace/src/opentracing/span_context.js +2 -1
- package/packages/dd-trace/src/plugins/.DS_Store +0 -0
- package/packages/dd-trace/src/plugins/util/test.js +8 -2
- package/packages/dd-trace/src/priority_sampler.js +52 -5
- package/packages/dd-trace/src/profiling/exporters/agent.js +33 -32
package/NOTICE
ADDED
package/ci/init.js
CHANGED
package/ci/jest/env.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
const tracer = require('../../packages/dd-trace')
|
|
2
|
+
const { ORIGIN_KEY } = require('../../packages/dd-trace/src/constants')
|
|
2
3
|
|
|
3
4
|
tracer.init({
|
|
4
5
|
startupLogs: false,
|
|
5
|
-
flushInterval: 400000
|
|
6
|
+
flushInterval: 400000,
|
|
7
|
+
tags: {
|
|
8
|
+
[ORIGIN_KEY]: 'ciapp-test'
|
|
9
|
+
}
|
|
6
10
|
})
|
|
7
11
|
|
|
8
12
|
tracer.use('fs', false)
|
package/index.d.ts
CHANGED
|
@@ -792,7 +792,7 @@ declare namespace plugins {
|
|
|
792
792
|
* This plugin automatically instruments the
|
|
793
793
|
* [cucumber](https://www.npmjs.com/package/@cucumber/cucumber) module.
|
|
794
794
|
*/
|
|
795
|
-
interface cucumber extends
|
|
795
|
+
interface cucumber extends Integration {}
|
|
796
796
|
|
|
797
797
|
/**
|
|
798
798
|
* This plugin automatically instruments the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"bench": "node benchmark",
|
|
11
11
|
"bench:profiler": "node benchmark/profiler",
|
|
12
12
|
"bench:e2e": "SERVICES=mongo yarn services && cd benchmark/e2e && node benchmark-run.js --duration=30",
|
|
13
|
+
"bench:e2e:ci-visibility": "node benchmark/e2e-ci/benchmark-run.js",
|
|
13
14
|
"type:doc": "cd docs && yarn && yarn build",
|
|
14
15
|
"type:test": "cd docs && yarn && yarn test",
|
|
15
16
|
"lint": "node scripts/check_licenses.js && eslint . && yarn audit --groups dependencies",
|
|
@@ -103,8 +103,8 @@ module.exports = [
|
|
|
103
103
|
name: '@cucumber/cucumber',
|
|
104
104
|
versions: ['7.0.0 - 7.2.1'],
|
|
105
105
|
file: 'lib/runtime/pickle_runner.js',
|
|
106
|
-
patch (PickleRunner, tracer) {
|
|
107
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber')
|
|
106
|
+
patch (PickleRunner, tracer, config) {
|
|
107
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
|
|
108
108
|
const sourceRoot = process.cwd()
|
|
109
109
|
const pl = PickleRunner.default
|
|
110
110
|
this.wrap(
|
|
@@ -127,8 +127,8 @@ module.exports = [
|
|
|
127
127
|
name: '@cucumber/cucumber',
|
|
128
128
|
versions: ['>=7.3.0'],
|
|
129
129
|
file: 'lib/runtime/test_case_runner.js',
|
|
130
|
-
patch (TestCaseRunner, tracer) {
|
|
131
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber')
|
|
130
|
+
patch (TestCaseRunner, tracer, config) {
|
|
131
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
|
|
132
132
|
const sourceRoot = process.cwd()
|
|
133
133
|
const pl = TestCaseRunner.default
|
|
134
134
|
this.wrap(
|
|
@@ -4,6 +4,7 @@ const {
|
|
|
4
4
|
TEST_SUITE,
|
|
5
5
|
TEST_STATUS,
|
|
6
6
|
TEST_FRAMEWORK_VERSION,
|
|
7
|
+
TEST_IS_RUM_ACTIVE,
|
|
7
8
|
getTestEnvironmentMetadata,
|
|
8
9
|
CI_APP_ORIGIN,
|
|
9
10
|
getTestParentSpan
|
|
@@ -66,19 +67,28 @@ module.exports = (on, config) => {
|
|
|
66
67
|
}
|
|
67
68
|
})
|
|
68
69
|
}
|
|
69
|
-
return null
|
|
70
|
+
return activeSpan ? activeSpan._spanContext._traceId.toString(10) : null
|
|
70
71
|
},
|
|
71
72
|
'dd:afterEach': (test) => {
|
|
72
|
-
const { state, error } = test
|
|
73
|
+
const { state, error, isRUMActive } = test
|
|
73
74
|
if (activeSpan) {
|
|
74
75
|
activeSpan.setTag(TEST_STATUS, CYPRESS_STATUS_TO_TEST_STATUS[state])
|
|
75
76
|
if (error) {
|
|
76
77
|
activeSpan.setTag('error', error)
|
|
77
78
|
}
|
|
79
|
+
if (isRUMActive) {
|
|
80
|
+
activeSpan.setTag(TEST_IS_RUM_ACTIVE, true)
|
|
81
|
+
}
|
|
78
82
|
activeSpan.finish()
|
|
79
83
|
}
|
|
80
84
|
activeSpan = null
|
|
81
85
|
return null
|
|
86
|
+
},
|
|
87
|
+
'dd:addTags': (tags) => {
|
|
88
|
+
if (activeSpan) {
|
|
89
|
+
activeSpan.addTags(tags)
|
|
90
|
+
}
|
|
91
|
+
return null
|
|
82
92
|
}
|
|
83
93
|
})
|
|
84
94
|
}
|
|
@@ -3,15 +3,30 @@ beforeEach(() => {
|
|
|
3
3
|
cy.task('dd:beforeEach', {
|
|
4
4
|
testName: Cypress.mocha.getRunner().suite.ctx.currentTest.fullTitle(),
|
|
5
5
|
testSuite: Cypress.mocha.getRootSuite().file
|
|
6
|
+
}).then(traceId => {
|
|
7
|
+
Cypress.env('traceId', traceId)
|
|
6
8
|
})
|
|
7
9
|
})
|
|
8
10
|
|
|
11
|
+
after(() => {
|
|
12
|
+
cy.window().then(win => {
|
|
13
|
+
win.dispatchEvent(new Event('beforeunload'))
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
|
|
9
18
|
afterEach(() => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
cy.window().then(win => {
|
|
20
|
+
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
|
|
21
|
+
const testInfo = {
|
|
22
|
+
testName: currentTest.fullTitle(),
|
|
23
|
+
testSuite: Cypress.mocha.getRootSuite().file,
|
|
24
|
+
state: currentTest.state,
|
|
25
|
+
error: currentTest.err,
|
|
26
|
+
}
|
|
27
|
+
if (win.DD_RUM) {
|
|
28
|
+
testInfo.isRUMActive = true
|
|
29
|
+
}
|
|
30
|
+
cy.task('dd:afterEach', testInfo)
|
|
16
31
|
})
|
|
17
32
|
})
|
|
@@ -238,8 +238,8 @@ module.exports = [
|
|
|
238
238
|
{
|
|
239
239
|
name: 'jest-environment-node',
|
|
240
240
|
versions: ['>=24.8.0'],
|
|
241
|
-
patch: function (NodeEnvironment, tracer) {
|
|
242
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest')
|
|
241
|
+
patch: function (NodeEnvironment, tracer, config) {
|
|
242
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest', config)
|
|
243
243
|
|
|
244
244
|
this.wrap(NodeEnvironment.prototype, 'teardown', createWrapTeardown(tracer, this))
|
|
245
245
|
|
|
@@ -257,8 +257,8 @@ module.exports = [
|
|
|
257
257
|
{
|
|
258
258
|
name: 'jest-environment-jsdom',
|
|
259
259
|
versions: ['>=24.8.0'],
|
|
260
|
-
patch: function (JsdomEnvironment, tracer) {
|
|
261
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest')
|
|
260
|
+
patch: function (JsdomEnvironment, tracer, config) {
|
|
261
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest', config)
|
|
262
262
|
|
|
263
263
|
this.wrap(JsdomEnvironment.prototype, 'teardown', createWrapTeardown(tracer, this))
|
|
264
264
|
|
|
@@ -169,8 +169,8 @@ module.exports = [
|
|
|
169
169
|
name: 'jest-jasmine2',
|
|
170
170
|
versions: ['>=24.8.0'],
|
|
171
171
|
file: 'build/jasmineAsyncInstall.js',
|
|
172
|
-
patch: function (jasmineAsyncInstallExport, tracer) {
|
|
173
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest')
|
|
172
|
+
patch: function (jasmineAsyncInstallExport, tracer, config) {
|
|
173
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('jest', config)
|
|
174
174
|
return this.wrapExport(
|
|
175
175
|
jasmineAsyncInstallExport.default,
|
|
176
176
|
createWrapJasmineAsyncInstall(tracer, this, testEnvironmentMetadata)(jasmineAsyncInstallExport.default)
|
|
@@ -122,6 +122,7 @@ function getAllTestsInSuite (root) {
|
|
|
122
122
|
function createWrapRunTests (tracer, testEnvironmentMetadata, sourceRoot) {
|
|
123
123
|
return function wrapRunTests (runTests) {
|
|
124
124
|
return function runTestsWithTrace () {
|
|
125
|
+
this.once('end', () => tracer._exporter._writer.flush())
|
|
125
126
|
runTests.apply(this, arguments)
|
|
126
127
|
const suite = arguments[0]
|
|
127
128
|
const tests = getAllTestsInSuite(suite)
|
|
@@ -239,8 +240,8 @@ module.exports = [
|
|
|
239
240
|
name: 'mocha',
|
|
240
241
|
versions: ['>=5.2.0'],
|
|
241
242
|
file: 'lib/runner.js',
|
|
242
|
-
patch (Runner, tracer) {
|
|
243
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('mocha')
|
|
243
|
+
patch (Runner, tracer, config) {
|
|
244
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('mocha', config)
|
|
244
245
|
const sourceRoot = process.cwd()
|
|
245
246
|
this.wrap(Runner.prototype, 'runTests', createWrapRunTests(tracer, testEnvironmentMetadata, sourceRoot))
|
|
246
247
|
this.wrap(Runner.prototype, 'runTest', createWrapRunTest(tracer, testEnvironmentMetadata, sourceRoot))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '1.
|
|
1
|
+
module.exports = '1.7.0'
|
|
@@ -10,5 +10,10 @@ module.exports = {
|
|
|
10
10
|
SAMPLING_RULE_DECISION: '_dd.rule_psr',
|
|
11
11
|
SAMPLING_LIMIT_DECISION: '_dd.limit_psr',
|
|
12
12
|
SAMPLING_AGENT_DECISION: '_dd.agent_psr',
|
|
13
|
-
|
|
13
|
+
SAMPLING_MECHANISM_DEFAULT: 0,
|
|
14
|
+
SAMPLING_MECHANISM_AGENT: 1,
|
|
15
|
+
SAMPLING_MECHANISM_RULE: 3,
|
|
16
|
+
SAMPLING_MECHANISM_MANUAL: 4,
|
|
17
|
+
DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent',
|
|
18
|
+
UPSTREAM_SERVICES_KEY: '_dd.p.upstream_services'
|
|
14
19
|
}
|
|
@@ -25,6 +25,7 @@ function format (span) {
|
|
|
25
25
|
|
|
26
26
|
extractError(formatted, span)
|
|
27
27
|
extractRootTags(formatted, span)
|
|
28
|
+
extractChunkTags(formatted, span)
|
|
28
29
|
extractTags(formatted, span)
|
|
29
30
|
|
|
30
31
|
return formatted
|
|
@@ -112,6 +113,17 @@ function extractRootTags (trace, span) {
|
|
|
112
113
|
addTag({}, trace.metrics, SAMPLING_AGENT_DECISION, context._trace[SAMPLING_AGENT_DECISION])
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
function extractChunkTags (trace, span) {
|
|
117
|
+
const context = span.context()
|
|
118
|
+
const isLocalRoot = span === context._trace.started[0]
|
|
119
|
+
|
|
120
|
+
if (!isLocalRoot) return
|
|
121
|
+
|
|
122
|
+
for (const key in context._trace.tags) {
|
|
123
|
+
addTag(trace.meta, trace.metrics, key, context._trace.tags[key])
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
115
127
|
function extractError (trace, span) {
|
|
116
128
|
const error = span.context()._tags['error']
|
|
117
129
|
if (isError(error)) {
|
|
@@ -11,6 +11,7 @@ const spanKey = 'x-datadog-parent-id'
|
|
|
11
11
|
const originKey = 'x-datadog-origin'
|
|
12
12
|
const samplingKey = 'x-datadog-sampling-priority'
|
|
13
13
|
const sampleKey = 'x-datadog-sampled'
|
|
14
|
+
const tagsKey = 'x-datadog-tags'
|
|
14
15
|
const baggagePrefix = 'ot-baggage-'
|
|
15
16
|
const b3TraceKey = 'x-b3-traceid'
|
|
16
17
|
const b3TraceExpr = /^([0-9a-f]{16}){1,2}$/i
|
|
@@ -41,6 +42,7 @@ class TextMapPropagator {
|
|
|
41
42
|
this._injectSamplingPriority(spanContext, carrier)
|
|
42
43
|
this._injectBaggageItems(spanContext, carrier)
|
|
43
44
|
this._injectB3(spanContext, carrier)
|
|
45
|
+
this._injectTags(spanContext, carrier)
|
|
44
46
|
|
|
45
47
|
log.debug(() => `Inject into carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
46
48
|
}
|
|
@@ -53,6 +55,7 @@ class TextMapPropagator {
|
|
|
53
55
|
this._extractOrigin(carrier, spanContext)
|
|
54
56
|
this._extractBaggageItems(carrier, spanContext)
|
|
55
57
|
this._extractSamplingPriority(carrier, spanContext)
|
|
58
|
+
this._extractTags(carrier, spanContext)
|
|
56
59
|
|
|
57
60
|
log.debug(() => `Extract from carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
58
61
|
|
|
@@ -81,6 +84,25 @@ class TextMapPropagator {
|
|
|
81
84
|
})
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
_injectTags (spanContext, carrier) {
|
|
88
|
+
const trace = spanContext._trace
|
|
89
|
+
const tags = []
|
|
90
|
+
|
|
91
|
+
for (const key in trace.tags) {
|
|
92
|
+
if (!key.startsWith('_dd.p.')) continue
|
|
93
|
+
|
|
94
|
+
tags.push(`${key}=${trace.tags[key]}`)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const header = tags.join(',')
|
|
98
|
+
|
|
99
|
+
if (header.length <= 512) {
|
|
100
|
+
carrier[tagsKey] = header
|
|
101
|
+
} else {
|
|
102
|
+
trace.tags['_dd.propagation_error:max_size'] = 1
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
84
106
|
_injectB3 (spanContext, carrier) {
|
|
85
107
|
if (!this._config.experimental.b3) return
|
|
86
108
|
|
|
@@ -241,6 +263,18 @@ class TextMapPropagator {
|
|
|
241
263
|
}
|
|
242
264
|
}
|
|
243
265
|
|
|
266
|
+
_extractTags (carrier, spanContext) {
|
|
267
|
+
if (!carrier[tagsKey]) return
|
|
268
|
+
|
|
269
|
+
const pairs = carrier[tagsKey].split(',')
|
|
270
|
+
|
|
271
|
+
for (const pair of pairs) {
|
|
272
|
+
const [key, value] = pair.split('=')
|
|
273
|
+
|
|
274
|
+
spanContext._trace.tags[key] = value
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
244
278
|
_isSampled (sampled, debug) {
|
|
245
279
|
if (debug || sampled === '1') {
|
|
246
280
|
return true
|
|
Binary file
|
|
@@ -24,6 +24,7 @@ const TEST_SUITE = 'test.suite'
|
|
|
24
24
|
const TEST_STATUS = 'test.status'
|
|
25
25
|
const TEST_PARAMETERS = 'test.parameters'
|
|
26
26
|
const TEST_SKIP_REASON = 'test.skip_reason'
|
|
27
|
+
const TEST_IS_RUM_ACTIVE = 'test.is_rum_active'
|
|
27
28
|
|
|
28
29
|
const ERROR_TYPE = 'error.type'
|
|
29
30
|
const ERROR_MESSAGE = 'error.msg'
|
|
@@ -43,6 +44,7 @@ module.exports = {
|
|
|
43
44
|
TEST_STATUS,
|
|
44
45
|
TEST_PARAMETERS,
|
|
45
46
|
TEST_SKIP_REASON,
|
|
47
|
+
TEST_IS_RUM_ACTIVE,
|
|
46
48
|
ERROR_TYPE,
|
|
47
49
|
ERROR_MESSAGE,
|
|
48
50
|
ERROR_STACK,
|
|
@@ -54,7 +56,7 @@ module.exports = {
|
|
|
54
56
|
getTestSuitePath
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
function getTestEnvironmentMetadata (testFramework) {
|
|
59
|
+
function getTestEnvironmentMetadata (testFramework, config) {
|
|
58
60
|
// TODO: eventually these will come from the tracer (generally available)
|
|
59
61
|
const ciMetadata = getCIMetadata()
|
|
60
62
|
const {
|
|
@@ -83,13 +85,17 @@ function getTestEnvironmentMetadata (testFramework) {
|
|
|
83
85
|
|
|
84
86
|
const runtimeAndOSMetadata = getRuntimeAndOSMetadata()
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
const metadata = {
|
|
87
89
|
[TEST_FRAMEWORK]: testFramework,
|
|
88
90
|
...gitMetadata,
|
|
89
91
|
...ciMetadata,
|
|
90
92
|
...userProvidedGitMetadata,
|
|
91
93
|
...runtimeAndOSMetadata
|
|
92
94
|
}
|
|
95
|
+
if (config && config.service) {
|
|
96
|
+
metadata['service.name'] = config.service
|
|
97
|
+
}
|
|
98
|
+
return metadata
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
function getTestParametersString (parametersByTestName, testName) {
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const coalesce = require('koalas')
|
|
3
4
|
const RateLimiter = require('./rate_limiter')
|
|
4
5
|
const Sampler = require('./sampler')
|
|
5
6
|
const ext = require('../../../ext')
|
|
6
7
|
const { setSamplingRules } = require('./startup-log')
|
|
7
8
|
|
|
8
9
|
const {
|
|
10
|
+
SAMPLING_MECHANISM_DEFAULT,
|
|
11
|
+
SAMPLING_MECHANISM_AGENT,
|
|
12
|
+
SAMPLING_MECHANISM_RULE,
|
|
13
|
+
SAMPLING_MECHANISM_MANUAL,
|
|
9
14
|
SAMPLING_RULE_DECISION,
|
|
10
15
|
SAMPLING_LIMIT_DECISION,
|
|
11
|
-
SAMPLING_AGENT_DECISION
|
|
16
|
+
SAMPLING_AGENT_DECISION,
|
|
17
|
+
UPSTREAM_SERVICES_KEY
|
|
12
18
|
} = require('./constants')
|
|
13
19
|
|
|
14
20
|
const SERVICE_NAME = ext.tags.SERVICE_NAME
|
|
@@ -21,6 +27,9 @@ const AUTO_KEEP = ext.priority.AUTO_KEEP
|
|
|
21
27
|
const USER_KEEP = ext.priority.USER_KEEP
|
|
22
28
|
const DEFAULT_KEY = 'service:,env:'
|
|
23
29
|
|
|
30
|
+
const defaultSampler = new Sampler(AUTO_KEEP)
|
|
31
|
+
const serviceNames = new Map()
|
|
32
|
+
|
|
24
33
|
class PrioritySampler {
|
|
25
34
|
constructor (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
|
|
26
35
|
this._env = env
|
|
@@ -50,12 +59,14 @@ class PrioritySampler {
|
|
|
50
59
|
|
|
51
60
|
if (this.validate(tag)) {
|
|
52
61
|
context._sampling.priority = tag
|
|
62
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_MANUAL
|
|
63
|
+
} else if (auto) {
|
|
64
|
+
context._sampling.priority = this._getPriorityFromAuto(root)
|
|
65
|
+
} else {
|
|
53
66
|
return
|
|
54
67
|
}
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
context._sampling.priority = this._getPriorityFromAuto(root)
|
|
58
|
-
}
|
|
69
|
+
this._addUpstreamService(root)
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
update (rates) {
|
|
@@ -68,7 +79,7 @@ class PrioritySampler {
|
|
|
68
79
|
samplers[key] = sampler
|
|
69
80
|
}
|
|
70
81
|
|
|
71
|
-
samplers[DEFAULT_KEY] = samplers[DEFAULT_KEY] ||
|
|
82
|
+
samplers[DEFAULT_KEY] = samplers[DEFAULT_KEY] || defaultSampler
|
|
72
83
|
|
|
73
84
|
this._samplers = samplers
|
|
74
85
|
}
|
|
@@ -116,6 +127,7 @@ class PrioritySampler {
|
|
|
116
127
|
|
|
117
128
|
_getPriorityByRule (context, rule) {
|
|
118
129
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
130
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
119
131
|
|
|
120
132
|
return rule.sampler.isSampled(context) && this._isSampledByRateLimit(context) ? USER_KEEP : USER_REJECT
|
|
121
133
|
}
|
|
@@ -134,9 +146,44 @@ class PrioritySampler {
|
|
|
134
146
|
|
|
135
147
|
context._trace[SAMPLING_AGENT_DECISION] = sampler.rate()
|
|
136
148
|
|
|
149
|
+
if (sampler === defaultSampler) {
|
|
150
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_DEFAULT
|
|
151
|
+
} else {
|
|
152
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_AGENT
|
|
153
|
+
}
|
|
154
|
+
|
|
137
155
|
return sampler.isSampled(context) ? AUTO_KEEP : AUTO_REJECT
|
|
138
156
|
}
|
|
139
157
|
|
|
158
|
+
_addUpstreamService (span) {
|
|
159
|
+
const context = span.context()
|
|
160
|
+
const trace = context._trace
|
|
161
|
+
const service = this._toBase64(context._tags['service.name'])
|
|
162
|
+
const priority = context._sampling.priority
|
|
163
|
+
const mechanism = context._sampling.mechanism
|
|
164
|
+
const rate = Math.ceil(coalesce(
|
|
165
|
+
context._trace[SAMPLING_RULE_DECISION],
|
|
166
|
+
context._trace[SAMPLING_AGENT_DECISION]
|
|
167
|
+
) * 10000) / 10000
|
|
168
|
+
const group = `${service}|${priority}|${mechanism}|${rate}`
|
|
169
|
+
const groups = trace.tags[UPSTREAM_SERVICES_KEY]
|
|
170
|
+
? `${trace.tags[UPSTREAM_SERVICES_KEY]};${group}`
|
|
171
|
+
: group
|
|
172
|
+
|
|
173
|
+
trace.tags[UPSTREAM_SERVICES_KEY] = groups
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_toBase64 (serviceName) {
|
|
177
|
+
let encoded = serviceNames.get(serviceName)
|
|
178
|
+
|
|
179
|
+
if (!encoded) {
|
|
180
|
+
encoded = Buffer.from(serviceName).toString('base64')
|
|
181
|
+
serviceNames.set(serviceName, encoded)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return encoded
|
|
185
|
+
}
|
|
186
|
+
|
|
140
187
|
_normalizeRules (rules, sampleRate) {
|
|
141
188
|
return rules
|
|
142
189
|
.concat({ sampleRate })
|
|
@@ -55,7 +55,6 @@ class AgentExporter {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export ({ profiles, start, end, tags }) {
|
|
58
|
-
const form = new FormData()
|
|
59
58
|
const types = Object.keys(profiles)
|
|
60
59
|
|
|
61
60
|
const fields = [
|
|
@@ -75,10 +74,6 @@ class AgentExporter {
|
|
|
75
74
|
...Object.entries(tags).map(([key, value]) => ['tags[]', `${key}:${value}`])
|
|
76
75
|
]
|
|
77
76
|
|
|
78
|
-
for (const [key, value] of fields) {
|
|
79
|
-
form.append(key, value)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
77
|
this._logger.debug(() => {
|
|
83
78
|
const body = fields.map(([key, value]) => ` ${key}: ${value}`).join('\n')
|
|
84
79
|
return `Building agent export report: ${'\n' + body}`
|
|
@@ -93,36 +88,14 @@ class AgentExporter {
|
|
|
93
88
|
return `Adding ${type} profile to agent export: ` + bytes
|
|
94
89
|
})
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
fields.push([`types[${index}]`, type])
|
|
92
|
+
fields.push([`data[${index}]`, buffer, {
|
|
98
93
|
filename: `${type}.pb.gz`,
|
|
99
94
|
contentType: 'application/octet-stream',
|
|
100
95
|
knownLength: buffer.length
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const options = {
|
|
105
|
-
method: 'POST',
|
|
106
|
-
path: '/profiling/v1/input',
|
|
107
|
-
headers: form.getHeaders()
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (containerId) {
|
|
111
|
-
options.headers['Datadog-Container-ID'] = containerId
|
|
96
|
+
}])
|
|
112
97
|
}
|
|
113
98
|
|
|
114
|
-
if (this._url.protocol === 'unix:') {
|
|
115
|
-
options.socketPath = this._url.pathname
|
|
116
|
-
} else {
|
|
117
|
-
options.protocol = this._url.protocol
|
|
118
|
-
options.hostname = this._url.hostname
|
|
119
|
-
options.port = this._url.port
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this._logger.debug(() => {
|
|
123
|
-
return `Submitting agent report to: ${JSON.stringify(options)}`
|
|
124
|
-
})
|
|
125
|
-
|
|
126
99
|
return new Promise((resolve, reject) => {
|
|
127
100
|
const operation = retry.operation({
|
|
128
101
|
randomize: true,
|
|
@@ -131,8 +104,36 @@ class AgentExporter {
|
|
|
131
104
|
})
|
|
132
105
|
|
|
133
106
|
operation.attempt((attempt) => {
|
|
134
|
-
const
|
|
135
|
-
|
|
107
|
+
const form = new FormData()
|
|
108
|
+
|
|
109
|
+
for (const [key, value, options] of fields) {
|
|
110
|
+
form.append(key, value, options)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const options = {
|
|
114
|
+
method: 'POST',
|
|
115
|
+
path: '/profiling/v1/input',
|
|
116
|
+
headers: form.getHeaders(),
|
|
117
|
+
timeout: this._backoffTime * Math.pow(2, attempt)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (containerId) {
|
|
121
|
+
options.headers['Datadog-Container-ID'] = containerId
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this._url.protocol === 'unix:') {
|
|
125
|
+
options.socketPath = this._url.pathname
|
|
126
|
+
} else {
|
|
127
|
+
options.protocol = this._url.protocol
|
|
128
|
+
options.hostname = this._url.hostname
|
|
129
|
+
options.port = this._url.port
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this._logger.debug(() => {
|
|
133
|
+
return `Submitting profiler agent report attempt #${attempt} to: ${JSON.stringify(options)}`
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
sendRequest(options, form, (err, response) => {
|
|
136
137
|
if (operation.retry(err)) {
|
|
137
138
|
this._logger.error(`Error from the agent: ${err.message}`)
|
|
138
139
|
return
|