dd-trace 2.2.1 → 2.3.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/index.d.ts +6 -0
- package/package.json +1 -1
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/cucumber.js +116 -0
- package/packages/datadog-instrumentations/src/elasticsearch.js +9 -4
- package/packages/datadog-instrumentations/src/ioredis.js +8 -5
- package/packages/datadog-instrumentations/src/redis.js +8 -8
- package/packages/datadog-plugin-cucumber/src/index.js +83 -128
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/config.js +7 -1
- package/packages/dd-trace/src/opentracing/tracer.js +1 -1
- package/packages/dd-trace/src/plugins/log_plugin.js +10 -5
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/span_processor.js +22 -7
package/index.d.ts
CHANGED
|
@@ -266,6 +266,12 @@ export declare interface TracerOptions {
|
|
|
266
266
|
*/
|
|
267
267
|
flushInterval?: number;
|
|
268
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Number of spans before partially exporting a trace. This prevents keeping all the spans in memory for very large traces.
|
|
271
|
+
* @default 1000
|
|
272
|
+
*/
|
|
273
|
+
flushMinSpans?: number;
|
|
274
|
+
|
|
269
275
|
/**
|
|
270
276
|
* Whether to enable runtime metrics.
|
|
271
277
|
* @default false
|
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { addHook, channel } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
|
|
6
|
+
const runStartCh = channel('ci:cucumber:run:start')
|
|
7
|
+
const runEndCh = channel('ci:cucumber:run:end')
|
|
8
|
+
const runAsyncEndCh = channel('ci:cucumber:run:async-end')
|
|
9
|
+
const runStepStartCh = channel('ci:cucumber:run-step:start')
|
|
10
|
+
const runStepEndCh = channel('ci:cucumber:run-step:end')
|
|
11
|
+
const errorCh = channel('ci:cucumber:error')
|
|
12
|
+
|
|
13
|
+
function getStatusFromResult (result) {
|
|
14
|
+
if (result.status === 1) {
|
|
15
|
+
return { status: 'pass' }
|
|
16
|
+
}
|
|
17
|
+
if (result.status === 2) {
|
|
18
|
+
return { status: 'skip' }
|
|
19
|
+
}
|
|
20
|
+
if (result.status === 4) {
|
|
21
|
+
return { status: 'skip', skipReason: 'not implemented' }
|
|
22
|
+
}
|
|
23
|
+
return { status: 'fail', errorMessage: result.message }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getStatusFromResultLatest (result) {
|
|
27
|
+
if (result.status === 'PASSED') {
|
|
28
|
+
return { status: 'pass' }
|
|
29
|
+
}
|
|
30
|
+
if (result.status === 'SKIPPED' || result.status === 'PENDING') {
|
|
31
|
+
return { status: 'skip' }
|
|
32
|
+
}
|
|
33
|
+
if (result.status === 'UNDEFINED') {
|
|
34
|
+
return { status: 'skip', skipReason: 'not implemented' }
|
|
35
|
+
}
|
|
36
|
+
return { status: 'fail', errorMessage: result.message }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function wrapRun (pl, isLatestVersion) {
|
|
40
|
+
shimmer.wrap(pl.prototype, 'run', run => function () {
|
|
41
|
+
if (!runStartCh.hasSubscribers) {
|
|
42
|
+
return run.apply(this, arguments)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
runStartCh.publish({ pickleName: this.pickle.name, pickleUri: this.pickle.uri })
|
|
46
|
+
try {
|
|
47
|
+
const promise = run.apply(this, arguments)
|
|
48
|
+
promise.finally(() => {
|
|
49
|
+
const result = this.getWorstStepResult()
|
|
50
|
+
const { status, skipReason, errorMessage } = isLatestVersion
|
|
51
|
+
? getStatusFromResultLatest(result) : getStatusFromResult(result)
|
|
52
|
+
|
|
53
|
+
runAsyncEndCh.publish({ status, skipReason, errorMessage })
|
|
54
|
+
})
|
|
55
|
+
return promise
|
|
56
|
+
} catch (err) {
|
|
57
|
+
errorCh.publish(err)
|
|
58
|
+
} finally {
|
|
59
|
+
runEndCh.publish(undefined)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
shimmer.wrap(pl.prototype, 'runStep', runStep => function () {
|
|
63
|
+
if (!runStepStartCh.hasSubscribers) {
|
|
64
|
+
return runStep.apply(this, arguments)
|
|
65
|
+
}
|
|
66
|
+
const testStep = arguments[0]
|
|
67
|
+
let resource
|
|
68
|
+
|
|
69
|
+
if (isLatestVersion) {
|
|
70
|
+
resource = testStep.text
|
|
71
|
+
} else {
|
|
72
|
+
resource = testStep.isHook ? 'hook' : testStep.pickleStep.text
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
runStepStartCh.publish({ resource })
|
|
76
|
+
try {
|
|
77
|
+
const promise = runStep.apply(this, arguments)
|
|
78
|
+
|
|
79
|
+
promise.then((result) => {
|
|
80
|
+
const { status, skipReason, errorMessage } = isLatestVersion
|
|
81
|
+
? getStatusFromResultLatest(result) : getStatusFromResult(result)
|
|
82
|
+
|
|
83
|
+
runAsyncEndCh.publish({ isStep: true, status, skipReason, errorMessage })
|
|
84
|
+
})
|
|
85
|
+
return promise
|
|
86
|
+
} catch (err) {
|
|
87
|
+
errorCh.publish(err)
|
|
88
|
+
} finally {
|
|
89
|
+
runStepEndCh.publish(undefined)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
addHook({
|
|
95
|
+
name: '@cucumber/cucumber',
|
|
96
|
+
versions: ['7.0.0 - 7.2.1'],
|
|
97
|
+
file: 'lib/runtime/pickle_runner.js'
|
|
98
|
+
}, (PickleRunner) => {
|
|
99
|
+
const pl = PickleRunner.default
|
|
100
|
+
|
|
101
|
+
wrapRun(pl, false)
|
|
102
|
+
|
|
103
|
+
return PickleRunner
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
addHook({
|
|
107
|
+
name: '@cucumber/cucumber',
|
|
108
|
+
versions: ['>=7.3.0'],
|
|
109
|
+
file: 'lib/runtime/test_case_runner.js'
|
|
110
|
+
}, (TestCaseRunner) => {
|
|
111
|
+
const pl = TestCaseRunner.default
|
|
112
|
+
|
|
113
|
+
wrapRun(pl, true)
|
|
114
|
+
|
|
115
|
+
return TestCaseRunner
|
|
116
|
+
})
|
|
@@ -35,18 +35,20 @@ function wrapRequest (request) {
|
|
|
35
35
|
|
|
36
36
|
if (!params) return request.apply(this, arguments)
|
|
37
37
|
|
|
38
|
-
const
|
|
38
|
+
const parentResource = new AsyncResource('bound-anonymous-fn')
|
|
39
39
|
|
|
40
40
|
startCh.publish({ params })
|
|
41
41
|
|
|
42
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
43
|
+
|
|
42
44
|
try {
|
|
43
45
|
const lastIndex = arguments.length - 1
|
|
44
46
|
cb = arguments[lastIndex]
|
|
45
47
|
|
|
46
48
|
if (typeof cb === 'function') {
|
|
47
|
-
cb =
|
|
49
|
+
cb = parentResource.bind(cb)
|
|
48
50
|
|
|
49
|
-
arguments[lastIndex] =
|
|
51
|
+
arguments[lastIndex] = asyncResource.bind(function (error) {
|
|
50
52
|
finish(params, error)
|
|
51
53
|
return cb.apply(null, arguments)
|
|
52
54
|
})
|
|
@@ -54,7 +56,10 @@ function wrapRequest (request) {
|
|
|
54
56
|
} else {
|
|
55
57
|
const promise = request.apply(this, arguments)
|
|
56
58
|
if (promise && typeof promise.then === 'function') {
|
|
57
|
-
|
|
59
|
+
const onResolve = asyncResource.bind(() => finish(params))
|
|
60
|
+
const onReject = asyncResource.bind(e => finish(params, e))
|
|
61
|
+
|
|
62
|
+
promise.then(onResolve, onReject)
|
|
58
63
|
} else {
|
|
59
64
|
finish(params)
|
|
60
65
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
channel,
|
|
5
|
-
addHook
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
6
7
|
} = require('./helpers/instrument')
|
|
7
8
|
const shimmer = require('../../datadog-shimmer')
|
|
8
9
|
|
|
@@ -21,12 +22,14 @@ addHook({ name: 'ioredis', versions: ['>=2'] }, Redis => {
|
|
|
21
22
|
const connectionName = options.connectionName
|
|
22
23
|
const db = options.db
|
|
23
24
|
const connectionOptions = { host: options.host, port: options.port }
|
|
25
|
+
|
|
24
26
|
startCh.publish({ db, command: command.name, args: command.args, connectionOptions, connectionName })
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
29
|
+
const onResolve = asyncResource.bind(() => finish(asyncEndCh, errorCh))
|
|
30
|
+
const onReject = asyncResource.bind(err => finish(asyncEndCh, errorCh, err))
|
|
31
|
+
|
|
32
|
+
command.promise.then(onResolve, onReject)
|
|
30
33
|
|
|
31
34
|
try {
|
|
32
35
|
return sendCommand.apply(this, arguments)
|
|
@@ -21,14 +21,14 @@ addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js',
|
|
|
21
21
|
const name = command[0]
|
|
22
22
|
const args = command.slice(1)
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
start(this, name, args)
|
|
25
25
|
|
|
26
26
|
const res = addCommand.apply(this, arguments)
|
|
27
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
28
|
+
const onResolve = asyncResource.bind(() => finish(asyncEndCh, errorCh))
|
|
29
|
+
const onReject = asyncResource.bind(err => finish(asyncEndCh, errorCh, err))
|
|
27
30
|
|
|
28
|
-
res.then(
|
|
29
|
-
() => finish(asyncEndCh, errorCh),
|
|
30
|
-
err => finish(asyncEndCh, errorCh, err)
|
|
31
|
-
)
|
|
31
|
+
res.then(onResolve, onReject)
|
|
32
32
|
endCh.publish(undefined)
|
|
33
33
|
return res
|
|
34
34
|
})
|
|
@@ -45,7 +45,7 @@ addHook({ name: 'redis', versions: ['>=2.6 <4'] }, redis => {
|
|
|
45
45
|
|
|
46
46
|
const cb = asyncResource.bind(options.callback)
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
start(this, options.command, options.args)
|
|
49
49
|
|
|
50
50
|
options.callback = AsyncResource.bind(wrapCallback(asyncEndCh, errorCh, cb))
|
|
51
51
|
|
|
@@ -70,7 +70,7 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
|
|
|
70
70
|
|
|
71
71
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
start(this, command, args)
|
|
74
74
|
|
|
75
75
|
if (typeof callback === 'function') {
|
|
76
76
|
const cb = asyncResource.bind(callback)
|
|
@@ -95,7 +95,7 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
|
|
|
95
95
|
return redis
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
function
|
|
98
|
+
function start (client, command, args) {
|
|
99
99
|
const db = client.selected_db
|
|
100
100
|
const connectionOptions = client.connection_options || client.connection_option || client.connectionOption || {}
|
|
101
101
|
startCh.publish({ db, command, args, connectionOptions })
|
|
@@ -1,150 +1,105 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
2
5
|
|
|
3
6
|
const {
|
|
7
|
+
CI_APP_ORIGIN,
|
|
4
8
|
TEST_TYPE,
|
|
5
9
|
TEST_NAME,
|
|
6
10
|
TEST_SUITE,
|
|
7
|
-
TEST_STATUS,
|
|
8
|
-
TEST_FRAMEWORK_VERSION,
|
|
9
11
|
TEST_SKIP_REASON,
|
|
10
|
-
|
|
12
|
+
TEST_FRAMEWORK_VERSION,
|
|
11
13
|
ERROR_MESSAGE,
|
|
12
|
-
|
|
14
|
+
TEST_STATUS,
|
|
13
15
|
finishAllTraceSpans,
|
|
16
|
+
getTestEnvironmentMetadata,
|
|
14
17
|
getTestSuitePath
|
|
15
18
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
19
|
+
const { SPAN_TYPE, RESOURCE_NAME } = require('../../../ext/tags')
|
|
20
|
+
const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} else if (result.status === 2) {
|
|
21
|
-
span.setTag(tag, 'skip')
|
|
22
|
-
} else if (result.status === 4) {
|
|
23
|
-
span.setTag(tag, 'skip')
|
|
24
|
-
span.setTag(TEST_SKIP_REASON, 'not implemented')
|
|
25
|
-
} else {
|
|
26
|
-
span.setTag(tag, 'fail')
|
|
27
|
-
span.setTag(ERROR_MESSAGE, result.message)
|
|
22
|
+
class CucumberPlugin extends Plugin {
|
|
23
|
+
static get name () {
|
|
24
|
+
return 'cucumber'
|
|
28
25
|
}
|
|
29
|
-
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
span.setTag(tag, 'pass')
|
|
34
|
-
} else if (result.status === 'SKIPPED' || result.status === 'PENDING') {
|
|
35
|
-
span.setTag(tag, 'skip')
|
|
36
|
-
} else if (result.status === 'UNDEFINED') {
|
|
37
|
-
span.setTag(tag, 'skip')
|
|
38
|
-
span.setTag(TEST_SKIP_REASON, 'not implemented')
|
|
39
|
-
} else {
|
|
40
|
-
span.setTag(tag, 'fail')
|
|
41
|
-
span.setTag(ERROR_MESSAGE, result.message)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
27
|
+
constructor (...args) {
|
|
28
|
+
super(...args)
|
|
44
29
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
[TEST_TYPE]: 'test',
|
|
53
|
-
[TEST_NAME]: testName,
|
|
54
|
-
[TEST_SUITE]: testSuite,
|
|
55
|
-
[SAMPLING_RULE_DECISION]: 1,
|
|
56
|
-
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
57
|
-
...testEnvironmentMetadata
|
|
58
|
-
}
|
|
30
|
+
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', this.config)
|
|
31
|
+
const sourceRoot = process.cwd()
|
|
32
|
+
|
|
33
|
+
this.addSub('ci:cucumber:run:start', ({ pickleName, pickleUri }) => {
|
|
34
|
+
const store = storage.getStore()
|
|
35
|
+
const childOf = store ? store.span : store
|
|
36
|
+
const testSuite = getTestSuitePath(pickleUri, sourceRoot)
|
|
59
37
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
setStatus(testSpan, this.getWorstStepResult(), TEST_STATUS)
|
|
72
|
-
}).finally(() => {
|
|
73
|
-
finishAllTraceSpans(testSpan)
|
|
74
|
-
})
|
|
75
|
-
return promise
|
|
38
|
+
const span = this.tracer.startSpan('cucumber.test', {
|
|
39
|
+
childOf,
|
|
40
|
+
tags: {
|
|
41
|
+
[SPAN_TYPE]: 'test',
|
|
42
|
+
[RESOURCE_NAME]: pickleName,
|
|
43
|
+
[TEST_TYPE]: 'test',
|
|
44
|
+
[TEST_NAME]: pickleName,
|
|
45
|
+
[TEST_SUITE]: testSuite,
|
|
46
|
+
[SAMPLING_RULE_DECISION]: 1,
|
|
47
|
+
[TEST_FRAMEWORK_VERSION]: this.tracer._version,
|
|
48
|
+
...testEnvironmentMetadata
|
|
76
49
|
}
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
50
|
+
})
|
|
51
|
+
span.context()._trace.origin = CI_APP_ORIGIN
|
|
52
|
+
this.enter(span, store)
|
|
53
|
+
})
|
|
81
54
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return promise
|
|
55
|
+
this.addSub('ci:cucumber:run:end', () => {
|
|
56
|
+
this.exit()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
this.addSub('ci:cucumber:run-step:start', ({ resource }) => {
|
|
60
|
+
const store = storage.getStore()
|
|
61
|
+
const childOf = store ? store.span : store
|
|
62
|
+
const span = this.tracer.startSpan('cucumber.step', {
|
|
63
|
+
childOf,
|
|
64
|
+
tags: {
|
|
65
|
+
'cucumber.step': resource,
|
|
66
|
+
[RESOURCE_NAME]: resource
|
|
95
67
|
}
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
68
|
+
})
|
|
69
|
+
this.enter(span, store)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
this.addSub('ci:cucumber:run-step:end', () => {
|
|
73
|
+
this.exit()
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
this.addSub('ci:cucumber:run:async-end', ({ isStep, status, skipReason, errorMessage }) => {
|
|
77
|
+
const span = storage.getStore().span
|
|
78
|
+
const statusTag = isStep ? 'step.status' : TEST_STATUS
|
|
79
|
+
|
|
80
|
+
span.setTag(statusTag, status)
|
|
100
81
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
name: '@cucumber/cucumber',
|
|
104
|
-
versions: ['7.0.0 - 7.2.1'],
|
|
105
|
-
file: 'lib/runtime/pickle_runner.js',
|
|
106
|
-
patch (PickleRunner, tracer, config) {
|
|
107
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
|
|
108
|
-
const sourceRoot = process.cwd()
|
|
109
|
-
const pl = PickleRunner.default
|
|
110
|
-
this.wrap(
|
|
111
|
-
pl.prototype,
|
|
112
|
-
'run',
|
|
113
|
-
createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResult)
|
|
114
|
-
)
|
|
115
|
-
const getResourceName = (testStep) => {
|
|
116
|
-
return testStep.isHook ? 'hook' : testStep.pickleStep.text
|
|
82
|
+
if (skipReason) {
|
|
83
|
+
span.setTag(TEST_SKIP_REASON, skipReason)
|
|
117
84
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{
|
|
127
|
-
name: '@cucumber/cucumber',
|
|
128
|
-
versions: ['>=7.3.0'],
|
|
129
|
-
file: 'lib/runtime/test_case_runner.js',
|
|
130
|
-
patch (TestCaseRunner, tracer, config) {
|
|
131
|
-
const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
|
|
132
|
-
const sourceRoot = process.cwd()
|
|
133
|
-
const pl = TestCaseRunner.default
|
|
134
|
-
this.wrap(
|
|
135
|
-
pl.prototype,
|
|
136
|
-
'run',
|
|
137
|
-
createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResultLatest)
|
|
138
|
-
)
|
|
139
|
-
const getResourceName = (testStep) => {
|
|
140
|
-
return testStep.text
|
|
85
|
+
|
|
86
|
+
if (errorMessage) {
|
|
87
|
+
span.setTag(ERROR_MESSAGE, errorMessage)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
span.finish()
|
|
91
|
+
if (!isStep) {
|
|
92
|
+
finishAllTraceSpans(span)
|
|
141
93
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
this.addSub('ci:cucumber:error', (err) => {
|
|
97
|
+
if (err) {
|
|
98
|
+
const span = storage.getStore().span
|
|
99
|
+
span.setTag('error', err)
|
|
100
|
+
}
|
|
101
|
+
})
|
|
149
102
|
}
|
|
150
|
-
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = CucumberPlugin
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '2.
|
|
1
|
+
module.exports = '2.3.0'
|
|
@@ -99,6 +99,11 @@ class Config {
|
|
|
99
99
|
process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
|
|
100
100
|
'0.4'
|
|
101
101
|
)
|
|
102
|
+
const DD_TRACE_PARTIAL_FLUSH_MIN_SPANS = coalesce(
|
|
103
|
+
parseInt(options.flushMinSpans),
|
|
104
|
+
parseInt(process.env.DD_TRACE_PARTIAL_FLUSH_MIN_SPANS),
|
|
105
|
+
1000
|
|
106
|
+
)
|
|
102
107
|
const DD_TRACE_B3_ENABLED = coalesce(
|
|
103
108
|
options.experimental && options.experimental.b3,
|
|
104
109
|
process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
|
|
@@ -166,6 +171,7 @@ class Config {
|
|
|
166
171
|
this.hostname = DD_AGENT_HOST || (this.url && this.url.hostname)
|
|
167
172
|
this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
|
|
168
173
|
this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
|
|
174
|
+
this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
|
|
169
175
|
this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
|
|
170
176
|
this.logger = options.logger
|
|
171
177
|
this.plugins = !!coalesce(options.plugins, true)
|
|
@@ -229,7 +235,7 @@ function getAgentUrl (url, options) {
|
|
|
229
235
|
!process.env.DD_TRACE_AGENT_PORT &&
|
|
230
236
|
fs.existsSync('/var/run/datadog/apm.socket')
|
|
231
237
|
) {
|
|
232
|
-
return new URL('
|
|
238
|
+
return new URL('unix:///var/run/datadog/apm.socket')
|
|
233
239
|
}
|
|
234
240
|
}
|
|
235
241
|
|
|
@@ -35,7 +35,7 @@ class DatadogTracer extends Tracer {
|
|
|
35
35
|
this._debug = config.debug
|
|
36
36
|
this._prioritySampler = new PrioritySampler(config.env, config.experimental.sampler)
|
|
37
37
|
this._exporter = new Exporter(config, this._prioritySampler)
|
|
38
|
-
this._processor = new SpanProcessor(this._exporter, this._prioritySampler)
|
|
38
|
+
this._processor = new SpanProcessor(this._exporter, this._prioritySampler, config)
|
|
39
39
|
this._url = this._exporter._url
|
|
40
40
|
this._enableGetRumData = config.experimental.enableGetRumData
|
|
41
41
|
this._propagators = {
|
|
@@ -34,11 +34,16 @@ module.exports = class LogPlugin extends Plugin {
|
|
|
34
34
|
this.addSub(`apm:${this.constructor.name}:log`, (arg) => {
|
|
35
35
|
// TODO rather than checking this every time, setting it ought to enable/disable any plugin
|
|
36
36
|
// extending from this one
|
|
37
|
-
if (this.tracer._logInjection)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
if (!this.tracer._logInjection) return
|
|
38
|
+
|
|
39
|
+
const store = storage.getStore()
|
|
40
|
+
const span = store && store.span
|
|
41
|
+
|
|
42
|
+
if (!span) return
|
|
43
|
+
|
|
44
|
+
const holder = {}
|
|
45
|
+
this.tracer.inject(span, LOG, holder)
|
|
46
|
+
arg.message = messageProxy(arg.message, holder)
|
|
42
47
|
})
|
|
43
48
|
}
|
|
44
49
|
}
|
|
@@ -37,7 +37,7 @@ function getGitMetadata (ciMetadata) {
|
|
|
37
37
|
committerName,
|
|
38
38
|
committerEmail,
|
|
39
39
|
committerDate
|
|
40
|
-
] = sanitizedExec('git show -s --format=%an,%ae,%
|
|
40
|
+
] = sanitizedExec('git show -s --format=%an,%ae,%aI,%cn,%ce,%cI', { stdio: 'pipe' }).split(',')
|
|
41
41
|
|
|
42
42
|
return {
|
|
43
43
|
[GIT_REPOSITORY_URL]:
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
1
3
|
const log = require('./log')
|
|
2
4
|
const format = require('./format')
|
|
3
5
|
|
|
@@ -5,24 +7,37 @@ const startedSpans = new WeakSet()
|
|
|
5
7
|
const finishedSpans = new WeakSet()
|
|
6
8
|
|
|
7
9
|
class SpanProcessor {
|
|
8
|
-
constructor (exporter, prioritySampler) {
|
|
10
|
+
constructor (exporter, prioritySampler, config) {
|
|
9
11
|
this._exporter = exporter
|
|
10
12
|
this._prioritySampler = prioritySampler
|
|
13
|
+
this._config = config
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
process (span) {
|
|
14
17
|
const spanContext = span.context()
|
|
18
|
+
const active = []
|
|
19
|
+
const formatted = []
|
|
15
20
|
const trace = spanContext._trace
|
|
21
|
+
const { flushMinSpans } = this._config
|
|
22
|
+
const { started, finished } = trace
|
|
16
23
|
|
|
17
|
-
if (
|
|
24
|
+
if (started.length === finished.length || finished.length >= flushMinSpans) {
|
|
18
25
|
this._prioritySampler.sample(spanContext)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
|
|
27
|
+
for (const span of started) {
|
|
28
|
+
if (span._duration !== undefined) {
|
|
29
|
+
formatted.push(format(span))
|
|
30
|
+
} else {
|
|
31
|
+
active.push(span)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this._exporter.export(formatted)
|
|
36
|
+
this._erase(trace, active)
|
|
22
37
|
}
|
|
23
38
|
}
|
|
24
39
|
|
|
25
|
-
_erase (trace) {
|
|
40
|
+
_erase (trace, active) {
|
|
26
41
|
if (process.env.DD_TRACE_EXPERIMENTAL_STATE_TRACKING === 'true') {
|
|
27
42
|
const started = new Set()
|
|
28
43
|
const startedIds = new Set()
|
|
@@ -98,7 +113,7 @@ class SpanProcessor {
|
|
|
98
113
|
span.context()._tags = {}
|
|
99
114
|
}
|
|
100
115
|
|
|
101
|
-
trace.started =
|
|
116
|
+
trace.started = active
|
|
102
117
|
trace.finished = []
|
|
103
118
|
}
|
|
104
119
|
}
|