dd-trace 2.13.0 → 2.14.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/package.json +2 -1
- package/packages/datadog-core/src/storage/async_resource.js +19 -1
- package/packages/datadog-instrumentations/src/cucumber.js +15 -0
- package/packages/datadog-instrumentations/src/fs.js +11 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +5 -1
- package/packages/datadog-instrumentations/src/jest.js +33 -11
- package/packages/datadog-plugin-cucumber/src/index.js +4 -0
- package/packages/datadog-plugin-fs/src/index.js +72 -38
- package/packages/datadog-plugin-jest/src/index.js +25 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
- package/packages/datadog-plugin-oracledb/src/index.js +12 -4
- package/packages/dd-trace/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
- package/packages/dd-trace/src/config.js +7 -0
- package/packages/dd-trace/src/encode/0.4.js +51 -58
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
- package/packages/dd-trace/src/exporters/agent/index.js +13 -7
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/request.js +20 -9
- package/packages/dd-trace/src/exporters/common/writer.js +9 -6
- package/packages/dd-trace/src/index.js +10 -0
- package/packages/dd-trace/src/noop/proxy.js +87 -0
- package/packages/dd-trace/src/plugin_manager.js +6 -4
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/proxy.js +5 -81
- package/packages/dd-trace/src/telemetry.js +1 -1
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -8,6 +8,7 @@ require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
|
|
|
8
8
|
require,diagnostics_channel,MIT,Copyright 2021 Simon D.
|
|
9
9
|
require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
|
|
10
10
|
require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
|
|
11
|
+
require,istanbul-lib-coverage,BSD-3-Clause,Copyright 2012-2015 Yahoo! Inc.
|
|
11
12
|
require,koalas,MIT,Copyright 2013-2017 Brian Woodward
|
|
12
13
|
require,limiter,MIT,Copyright 2011 John Hurliman
|
|
13
14
|
require,lodash.kebabcase,MIT,Copyright JS Foundation and other contributors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"diagnostics_channel": "^1.1.0",
|
|
68
68
|
"ignore": "^5.2.0",
|
|
69
69
|
"import-in-the-middle": "^1.3.0",
|
|
70
|
+
"istanbul-lib-coverage": "3.2.0",
|
|
70
71
|
"koalas": "^1.0.2",
|
|
71
72
|
"limiter": "^1.1.4",
|
|
72
73
|
"lodash.kebabcase": "^4.1.1",
|
|
@@ -6,9 +6,27 @@ const { channel } = require('diagnostics_channel')
|
|
|
6
6
|
const beforeCh = channel('dd-trace:storage:before')
|
|
7
7
|
const afterCh = channel('dd-trace:storage:after')
|
|
8
8
|
|
|
9
|
+
let PrivateSymbol = Symbol
|
|
10
|
+
function makePrivateSymbol () {
|
|
11
|
+
// eslint-disable-next-line no-new-func
|
|
12
|
+
PrivateSymbol = new Function('name', 'return %CreatePrivateSymbol(name)')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
makePrivateSymbol()
|
|
17
|
+
} catch (e) {
|
|
18
|
+
try {
|
|
19
|
+
const v8 = require('v8')
|
|
20
|
+
v8.setFlagsFromString('--allow-natives-syntax')
|
|
21
|
+
makePrivateSymbol()
|
|
22
|
+
v8.setFlagsFromString('--no-allow-natives-syntax')
|
|
23
|
+
// eslint-disable-next-line no-empty
|
|
24
|
+
} catch (e) {}
|
|
25
|
+
}
|
|
26
|
+
|
|
9
27
|
class AsyncResourceStorage {
|
|
10
28
|
constructor () {
|
|
11
|
-
this._ddResourceStore =
|
|
29
|
+
this._ddResourceStore = PrivateSymbol('ddResourceStore')
|
|
12
30
|
this._enabled = false
|
|
13
31
|
this._hook = createHook(this._createHook())
|
|
14
32
|
}
|
|
@@ -7,6 +7,7 @@ const runStartCh = channel('ci:cucumber:run:start')
|
|
|
7
7
|
const runFinishCh = channel('ci:cucumber:run:finish')
|
|
8
8
|
const runStepStartCh = channel('ci:cucumber:run-step:start')
|
|
9
9
|
const errorCh = channel('ci:cucumber:error')
|
|
10
|
+
const sessionFinishCh = channel('ci:cucumber:session:finish')
|
|
10
11
|
|
|
11
12
|
// TODO: remove in a later major version
|
|
12
13
|
const patched = new WeakSet()
|
|
@@ -128,4 +129,18 @@ addHook({
|
|
|
128
129
|
file: 'lib/runtime/test_case_runner.js'
|
|
129
130
|
}, testCaseHook)
|
|
130
131
|
|
|
132
|
+
addHook({
|
|
133
|
+
name: '@cucumber/cucumber',
|
|
134
|
+
versions: ['>=7.0.0'],
|
|
135
|
+
file: 'lib/runtime/index.js'
|
|
136
|
+
}, (Runtime) => {
|
|
137
|
+
shimmer.wrap(Runtime.default.prototype, 'start', start => async function () {
|
|
138
|
+
const result = await start.apply(this, arguments)
|
|
139
|
+
sessionFinishCh.publish(undefined)
|
|
140
|
+
return result
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
return Runtime
|
|
144
|
+
})
|
|
145
|
+
|
|
131
146
|
module.exports = { pickleHook, testCaseHook }
|
|
@@ -23,6 +23,7 @@ module.exports = {
|
|
|
23
23
|
'express': () => require('../express'),
|
|
24
24
|
'fastify': () => require('../fastify'),
|
|
25
25
|
'find-my-way': () => require('../find-my-way'),
|
|
26
|
+
'fs': () => require('../fs'),
|
|
26
27
|
'graphql': () => require('../graphql'),
|
|
27
28
|
'grpc': () => require('../grpc'),
|
|
28
29
|
'hapi': () => require('../hapi'),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
2
|
+
const istanbul = require('istanbul-lib-coverage')
|
|
3
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
5
|
|
|
@@ -7,7 +7,8 @@ const testStartCh = channel('ci:jest:test:start')
|
|
|
7
7
|
const testSkippedCh = channel('ci:jest:test:skip')
|
|
8
8
|
const testRunFinishCh = channel('ci:jest:test:finish')
|
|
9
9
|
const testErrCh = channel('ci:jest:test:err')
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const testCodeCoverageCh = channel('ci:jest:test:code-coverage')
|
|
11
12
|
|
|
12
13
|
const {
|
|
13
14
|
getTestSuitePath,
|
|
@@ -16,6 +17,24 @@ const {
|
|
|
16
17
|
|
|
17
18
|
const { getFormattedJestTestParameters, getJestTestName } = require('../../datadog-plugin-jest/src/util')
|
|
18
19
|
|
|
20
|
+
// This function also resets the coverage counters
|
|
21
|
+
function extractCoverageInformation (coverage, rootDir) {
|
|
22
|
+
const coverageMap = istanbul.createCoverageMap(coverage)
|
|
23
|
+
|
|
24
|
+
return coverageMap
|
|
25
|
+
.files()
|
|
26
|
+
.filter(filename => {
|
|
27
|
+
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
28
|
+
const lineCoverage = fileCoverage.getLineCoverage()
|
|
29
|
+
const isAnyLineExecuted = Object.entries(lineCoverage).some(([, numExecutions]) => !!numExecutions)
|
|
30
|
+
|
|
31
|
+
fileCoverage.resetHits()
|
|
32
|
+
|
|
33
|
+
return isAnyLineExecuted
|
|
34
|
+
})
|
|
35
|
+
.map(filename => filename.replace(`${rootDir}/`, ''))
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
const specStatusToTestStatus = {
|
|
20
39
|
'pending': 'skip',
|
|
21
40
|
'disabled': 'skip',
|
|
@@ -49,15 +68,11 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
49
68
|
constructor (config, context) {
|
|
50
69
|
super(config, context)
|
|
51
70
|
const rootDir = config.globalConfig ? config.globalConfig.rootDir : config.rootDir
|
|
71
|
+
this.rootDir = rootDir
|
|
52
72
|
this.testSuite = getTestSuitePath(context.testPath, rootDir)
|
|
53
73
|
this.nameToParams = {}
|
|
54
74
|
this.global._ddtrace = global._ddtrace
|
|
55
75
|
}
|
|
56
|
-
async teardown () {
|
|
57
|
-
super.teardown().finally(() => {
|
|
58
|
-
testSuiteFinish.publish()
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
76
|
|
|
62
77
|
async handleTestEvent (event, state) {
|
|
63
78
|
if (super.handleTestEvent) {
|
|
@@ -99,6 +114,10 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
99
114
|
if (event.name === 'test_done') {
|
|
100
115
|
const asyncResource = asyncResources.get(event.test)
|
|
101
116
|
asyncResource.runInAsyncScope(() => {
|
|
117
|
+
if (this.global.__coverage__) {
|
|
118
|
+
const coverageFiles = extractCoverageInformation(this.global.__coverage__, this.rootDir)
|
|
119
|
+
testCodeCoverageCh.publish(coverageFiles)
|
|
120
|
+
}
|
|
102
121
|
let status = 'pass'
|
|
103
122
|
if (event.test.errors && event.test.errors.length) {
|
|
104
123
|
status = 'fail'
|
|
@@ -111,10 +130,13 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
111
130
|
})
|
|
112
131
|
}
|
|
113
132
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
133
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
134
|
+
asyncResource.runInAsyncScope(() => {
|
|
135
|
+
testSkippedCh.publish({
|
|
136
|
+
name: getJestTestName(event.test),
|
|
137
|
+
suite: this.testSuite,
|
|
138
|
+
runner: 'jest-circus'
|
|
139
|
+
})
|
|
118
140
|
})
|
|
119
141
|
}
|
|
120
142
|
}
|
|
@@ -30,6 +30,10 @@ class CucumberPlugin extends Plugin {
|
|
|
30
30
|
const sourceRoot = process.cwd()
|
|
31
31
|
const codeOwnersEntries = getCodeOwnersFileEntries(sourceRoot)
|
|
32
32
|
|
|
33
|
+
this.addSub('ci:cucumber:session:finish', () => {
|
|
34
|
+
this.tracer._exporter._writer.flush()
|
|
35
|
+
})
|
|
36
|
+
|
|
33
37
|
this.addSub('ci:cucumber:run:start', ({ pickleName, pickleUri }) => {
|
|
34
38
|
const store = storage.getStore()
|
|
35
39
|
const childOf = store ? store.span : store
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// The `fs` plugin is an old style plugin that has not been updated for the new
|
|
4
|
+
// plugin system and was hacked in for backward compatibility with 2.x.
|
|
5
|
+
|
|
3
6
|
const { storage } = require('../../datadog-core')
|
|
7
|
+
const { channel } = require('../../datadog-instrumentations/src/helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
10
|
|
|
5
11
|
let kDirReadPromisified
|
|
6
12
|
let kDirClosePromisified
|
|
7
13
|
let kHandle
|
|
14
|
+
let fsConfig
|
|
15
|
+
let fsInstance
|
|
8
16
|
|
|
9
17
|
const ddFhSym = Symbol('ddFileHandle')
|
|
10
18
|
|
|
@@ -144,8 +152,8 @@ function createWrapDirAsyncIterator (config, tracer, instrumenter) {
|
|
|
144
152
|
}
|
|
145
153
|
}
|
|
146
154
|
}
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
shimmer.wrap(this, kDirReadPromisified, createWrapDirRead(config, tracer))
|
|
156
|
+
shimmer.wrap(this, kDirClosePromisified, createWrapKDirClose(config, tracer, instrumenter))
|
|
149
157
|
return asyncIterator.apply(this, arguments)
|
|
150
158
|
}
|
|
151
159
|
}
|
|
@@ -158,8 +166,8 @@ function createWrapKDirClose (config, tracer, instrumenter) {
|
|
|
158
166
|
return tracer.trace('fs.operation', { tags, orphanable }, (span) => {
|
|
159
167
|
const p = kDirClose.apply(this, arguments)
|
|
160
168
|
const unwrapBoth = () => {
|
|
161
|
-
|
|
162
|
-
|
|
169
|
+
shimmer.unwrap(this, kDirReadPromisified)
|
|
170
|
+
shimmer.unwrap(this, kDirClosePromisified)
|
|
163
171
|
}
|
|
164
172
|
p.then(unwrapBoth, unwrapBoth)
|
|
165
173
|
return p
|
|
@@ -339,7 +347,7 @@ function makeFSTags (resourceName, path, options, config, tracer) {
|
|
|
339
347
|
'component': 'fs',
|
|
340
348
|
'span.kind': 'internal',
|
|
341
349
|
'resource.name': resourceName,
|
|
342
|
-
'service.name':
|
|
350
|
+
'service.name': fsConfig.service || tracer._service
|
|
343
351
|
}
|
|
344
352
|
|
|
345
353
|
switch (typeof path) {
|
|
@@ -399,9 +407,9 @@ function patchClassicFunctions (fs, tracer, config) {
|
|
|
399
407
|
if (tagMakerName in tagMakers) {
|
|
400
408
|
const tagMaker = tagMakers[tagMakerName]
|
|
401
409
|
if (name.endsWith('Sync')) {
|
|
402
|
-
|
|
410
|
+
shimmer.wrap(fs, name, createWrap(tracer, config, name, tagMaker))
|
|
403
411
|
} else {
|
|
404
|
-
|
|
412
|
+
shimmer.wrap(fs, name, createWrapCb(tracer, config, name, tagMaker))
|
|
405
413
|
}
|
|
406
414
|
if (name in promisifiable) {
|
|
407
415
|
copySymbols(original, fs[name])
|
|
@@ -424,8 +432,6 @@ function patchFileHandle (fs, tracer, config) {
|
|
|
424
432
|
tagMaker = createFDTags
|
|
425
433
|
}
|
|
426
434
|
|
|
427
|
-
const instrumenter = this
|
|
428
|
-
|
|
429
435
|
const desc = Reflect.getOwnPropertyDescriptor(fileHandlePrototype, kHandle)
|
|
430
436
|
if (!desc || !desc.get) {
|
|
431
437
|
Reflect.defineProperty(fileHandlePrototype, kHandle, {
|
|
@@ -434,13 +440,13 @@ function patchFileHandle (fs, tracer, config) {
|
|
|
434
440
|
},
|
|
435
441
|
set (h) {
|
|
436
442
|
this[ddFhSym] = h
|
|
437
|
-
|
|
443
|
+
shimmer.wrap(this, 'close', createWrap(tracer, config, 'filehandle.close', tagMakers.close))
|
|
438
444
|
},
|
|
439
445
|
configurable: true
|
|
440
446
|
})
|
|
441
447
|
}
|
|
442
448
|
|
|
443
|
-
|
|
449
|
+
shimmer.wrap(fileHandlePrototype, name, createWrap(tracer, config, 'filehandle.' + name, tagMaker))
|
|
444
450
|
}
|
|
445
451
|
})
|
|
446
452
|
}
|
|
@@ -449,17 +455,17 @@ function patchPromiseFunctions (fs, tracer, config) {
|
|
|
449
455
|
for (const name in fs.promises) {
|
|
450
456
|
if (name in tagMakers) {
|
|
451
457
|
const tagMaker = tagMakers[name]
|
|
452
|
-
|
|
458
|
+
shimmer.wrap(fs.promises, name, createWrap(tracer, config, 'promises.' + name, tagMaker))
|
|
453
459
|
}
|
|
454
460
|
}
|
|
455
461
|
}
|
|
456
462
|
|
|
457
463
|
function patchDirFunctions (fs, tracer, config) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
464
|
+
shimmer.wrap(fs.Dir.prototype, 'close', createWrapDirClose(config, tracer))
|
|
465
|
+
shimmer.wrap(fs.Dir.prototype, 'closeSync', createWrapDirClose(config, tracer, true))
|
|
466
|
+
shimmer.wrap(fs.Dir.prototype, 'read', createWrapDirRead(config, tracer))
|
|
467
|
+
shimmer.wrap(fs.Dir.prototype, 'readSync', createWrapDirRead(config, tracer, true))
|
|
468
|
+
shimmer.wrap(fs.Dir.prototype, Symbol.asyncIterator, createWrapDirAsyncIterator(config, tracer, this))
|
|
463
469
|
}
|
|
464
470
|
|
|
465
471
|
function unpatchClassicFunctions (fs) {
|
|
@@ -467,7 +473,7 @@ function unpatchClassicFunctions (fs) {
|
|
|
467
473
|
if (!fs[name]) continue
|
|
468
474
|
const tagMakerName = name.endsWith('Sync') ? name.substr(0, name.length - 4) : name
|
|
469
475
|
if (tagMakerName in tagMakers) {
|
|
470
|
-
|
|
476
|
+
shimmer.unwrap(fs, name)
|
|
471
477
|
}
|
|
472
478
|
}
|
|
473
479
|
}
|
|
@@ -478,7 +484,7 @@ function unpatchFileHandle (fs) {
|
|
|
478
484
|
if (typeof name !== 'string' || name === 'constructor' || name === 'fd' || name === 'getAsyncId') {
|
|
479
485
|
continue
|
|
480
486
|
}
|
|
481
|
-
|
|
487
|
+
shimmer.unwrap(fileHandlePrototype, name)
|
|
482
488
|
}
|
|
483
489
|
delete fileHandlePrototype[kHandle]
|
|
484
490
|
})
|
|
@@ -487,22 +493,46 @@ function unpatchFileHandle (fs) {
|
|
|
487
493
|
function unpatchPromiseFunctions (fs) {
|
|
488
494
|
for (const name in fs.promises) {
|
|
489
495
|
if (name in tagMakers) {
|
|
490
|
-
|
|
496
|
+
shimmer.unwrap(fs.promises, name)
|
|
491
497
|
}
|
|
492
498
|
}
|
|
493
499
|
}
|
|
494
500
|
|
|
495
501
|
function unpatchDirFunctions (fs) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
502
|
+
shimmer.unwrap(fs.Dir.prototype, 'close')
|
|
503
|
+
shimmer.unwrap(fs.Dir.prototype, 'closeSync')
|
|
504
|
+
shimmer.unwrap(fs.Dir.prototype, 'read')
|
|
505
|
+
shimmer.unwrap(fs.Dir.prototype, 'readSync')
|
|
506
|
+
shimmer.unwrap(fs.Dir.prototype, Symbol.asyncIterator)
|
|
501
507
|
}
|
|
502
508
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
509
|
+
const hookChannel = channel('apm:fs:hook')
|
|
510
|
+
|
|
511
|
+
hookChannel.subscribe(fs => {
|
|
512
|
+
fsInstance = fs
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
class FsPlugin extends Plugin {
|
|
516
|
+
static get name () {
|
|
517
|
+
return 'fs'
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
configure (config) {
|
|
521
|
+
fsConfig = config
|
|
522
|
+
|
|
523
|
+
super.configure(config)
|
|
524
|
+
|
|
525
|
+
this._unpatch()
|
|
526
|
+
|
|
527
|
+
if (this._enabled) {
|
|
528
|
+
this._patch()
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
_patch () {
|
|
533
|
+
const fs = fsInstance
|
|
534
|
+
const tracer = this.tracer
|
|
535
|
+
const config = this.config
|
|
506
536
|
const realpathNative = fs.realpath.native
|
|
507
537
|
const realpathSyncNative = fs.realpathSync.native
|
|
508
538
|
patchClassicFunctions.call(this, fs, tracer, config)
|
|
@@ -513,18 +543,20 @@ module.exports = {
|
|
|
513
543
|
if (fs.Dir) {
|
|
514
544
|
patchDirFunctions.call(this, fs, tracer, config)
|
|
515
545
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
546
|
+
shimmer.wrap(fs, 'createReadStream', createWrapCreateReadStream(config, tracer))
|
|
547
|
+
shimmer.wrap(fs, 'createWriteStream', createWrapCreateWriteStream(config, tracer))
|
|
548
|
+
shimmer.wrap(fs, 'existsSync', createWrap(tracer, config, 'existsSync', createPathTags))
|
|
549
|
+
shimmer.wrap(fs, 'exists', createWrapExists(config, tracer))
|
|
520
550
|
if (realpathNative) {
|
|
521
551
|
fs.realpath.native = createWrapCb(tracer, config, 'realpath.native', createPathTags)(realpathNative)
|
|
522
552
|
}
|
|
523
553
|
if (realpathSyncNative) {
|
|
524
554
|
fs.realpathSync.native = createWrap(tracer, config, 'realpath.native', createPathTags)(realpathSyncNative)
|
|
525
555
|
}
|
|
526
|
-
}
|
|
527
|
-
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
_unpatch () {
|
|
559
|
+
const fs = fsInstance
|
|
528
560
|
unpatchClassicFunctions.call(this, fs)
|
|
529
561
|
if (fs.promises) {
|
|
530
562
|
unpatchFileHandle.call(this, fs)
|
|
@@ -533,13 +565,15 @@ module.exports = {
|
|
|
533
565
|
if (fs.Dir) {
|
|
534
566
|
unpatchDirFunctions.call(this, fs)
|
|
535
567
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
568
|
+
shimmer.unwrap(fs, 'createReadStream')
|
|
569
|
+
shimmer.unwrap(fs, 'createWriteStream')
|
|
570
|
+
shimmer.unwrap(fs, 'existsSync')
|
|
571
|
+
shimmer.unwrap(fs, 'exists')
|
|
540
572
|
}
|
|
541
573
|
}
|
|
542
574
|
|
|
575
|
+
module.exports = FsPlugin
|
|
576
|
+
|
|
543
577
|
/** TODO fs functions:
|
|
544
578
|
|
|
545
579
|
unwatchFile
|
|
@@ -15,6 +15,9 @@ const {
|
|
|
15
15
|
TEST_CODE_OWNERS
|
|
16
16
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
17
17
|
|
|
18
|
+
// https://github.com/facebook/jest/blob/d6ad15b0f88a05816c2fe034dd6900d28315d570/packages/jest-worker/src/types.ts#L38
|
|
19
|
+
const CHILD_MESSAGE_END = 2
|
|
20
|
+
|
|
18
21
|
function getTestSpanMetadata (tracer, test) {
|
|
19
22
|
const childOf = getTestParentSpan(tracer)
|
|
20
23
|
|
|
@@ -38,9 +41,31 @@ class JestPlugin extends Plugin {
|
|
|
38
41
|
constructor (...args) {
|
|
39
42
|
super(...args)
|
|
40
43
|
|
|
44
|
+
// Used to handle the end of a jest worker to be able to flush
|
|
45
|
+
const handler = ([message]) => {
|
|
46
|
+
if (message === CHILD_MESSAGE_END) {
|
|
47
|
+
this.tracer._exporter._writer.flush(() => {
|
|
48
|
+
// eslint-disable-next-line
|
|
49
|
+
// https://github.com/facebook/jest/blob/24ed3b5ecb419c023ee6fdbc838f07cc028fc007/packages/jest-worker/src/workers/processChild.ts#L118-L133
|
|
50
|
+
// Only after the flush is done we clean up open handles
|
|
51
|
+
// so the worker process can hopefully exit gracefully
|
|
52
|
+
process.removeListener('message', handler)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
process.on('message', handler)
|
|
57
|
+
|
|
41
58
|
this.testEnvironmentMetadata = getTestEnvironmentMetadata('jest', this.config)
|
|
42
59
|
this.codeOwnersEntries = getCodeOwnersFileEntries()
|
|
43
60
|
|
|
61
|
+
this.addSub('ci:jest:test:code-coverage', (coverageFiles) => {
|
|
62
|
+
if (!this.config.isAgentlessEnabled || !this.config.isIntelligentTestRunnerEnabled) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
const testSpan = storage.getStore().span
|
|
66
|
+
this.tracer._exporter.exportCoverage({ testSpan, coverageFiles })
|
|
67
|
+
})
|
|
68
|
+
|
|
44
69
|
this.addSub('ci:jest:test:start', (test) => {
|
|
45
70
|
const store = storage.getStore()
|
|
46
71
|
const span = this.startTestSpan(test)
|
|
@@ -55,10 +80,6 @@ class JestPlugin extends Plugin {
|
|
|
55
80
|
finishAllTraceSpans(span)
|
|
56
81
|
})
|
|
57
82
|
|
|
58
|
-
this.addSub('ci:jest:test-suite:finish', () => {
|
|
59
|
-
this.tracer._exporter._writer.flush()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
83
|
this.addSub('ci:jest:test:err', (error) => {
|
|
63
84
|
if (error) {
|
|
64
85
|
const span = storage.getStore().span
|
|
@@ -14,7 +14,7 @@ class MongodbCorePlugin extends Plugin {
|
|
|
14
14
|
|
|
15
15
|
this.addSub(`apm:mongodb:query:start`, ({ ns, ops, options, name }) => {
|
|
16
16
|
const query = getQuery(ops)
|
|
17
|
-
const resource = getResource(ns, query, name)
|
|
17
|
+
const resource = truncate(getResource(ns, query, name))
|
|
18
18
|
const store = storage.getStore()
|
|
19
19
|
const childOf = store ? store.span : store
|
|
20
20
|
const span = this.tracer.startSpan('mongodb.query', {
|
|
@@ -55,8 +55,8 @@ class MongodbCorePlugin extends Plugin {
|
|
|
55
55
|
|
|
56
56
|
function getQuery (cmd) {
|
|
57
57
|
if (!cmd || typeof cmd !== 'object' || Array.isArray(cmd)) return
|
|
58
|
-
if (cmd.query) return JSON.stringify(
|
|
59
|
-
if (cmd.filter) return JSON.stringify(
|
|
58
|
+
if (cmd.query) return JSON.stringify(limitDepth(cmd.query))
|
|
59
|
+
if (cmd.filter) return JSON.stringify(limitDepth(cmd.filter))
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function getResource (ns, query, operationName) {
|
|
@@ -69,12 +69,25 @@ function getResource (ns, query, operationName) {
|
|
|
69
69
|
return parts.join(' ')
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function truncate (input) {
|
|
73
|
+
return input.slice(0, Math.min(input.length, 10000))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function simplify (input) {
|
|
77
|
+
return isBSON(input) ? input.toHexString() : input
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function shouldSimplify (input) {
|
|
81
|
+
return !isObject(input) || isBSON(input)
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
function shouldHide (input) {
|
|
73
|
-
return
|
|
85
|
+
return Buffer.isBuffer(input) || typeof input === 'function'
|
|
74
86
|
}
|
|
75
87
|
|
|
76
|
-
function
|
|
88
|
+
function limitDepth (input) {
|
|
77
89
|
if (shouldHide(input)) return '?'
|
|
90
|
+
if (shouldSimplify(input)) return simplify(input)
|
|
78
91
|
|
|
79
92
|
const output = {}
|
|
80
93
|
const queue = [{
|
|
@@ -92,8 +105,10 @@ function sanitize (input) {
|
|
|
92
105
|
if (typeof input[key] === 'function') continue
|
|
93
106
|
|
|
94
107
|
const child = input[key]
|
|
95
|
-
if (depth >=
|
|
108
|
+
if (depth >= 10 || shouldHide(child)) {
|
|
96
109
|
output[key] = '?'
|
|
110
|
+
} else if (shouldSimplify(child)) {
|
|
111
|
+
output[key] = simplify(child)
|
|
97
112
|
} else {
|
|
98
113
|
queue.push({
|
|
99
114
|
input: child,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
6
|
+
const log = require('../../dd-trace/src/log')
|
|
6
7
|
|
|
7
8
|
class OracledbPlugin extends Plugin {
|
|
8
9
|
static get name () {
|
|
@@ -14,18 +15,25 @@ class OracledbPlugin extends Plugin {
|
|
|
14
15
|
|
|
15
16
|
this.addSub('apm:oracledb:execute:start', ({ query, connAttrs }) => {
|
|
16
17
|
const service = getServiceName(this.tracer, this.config, connAttrs)
|
|
17
|
-
|
|
18
|
+
let connectStringObj
|
|
19
|
+
try {
|
|
20
|
+
connectStringObj = new URL(`http://${connAttrs.connectString}`)
|
|
21
|
+
} catch (e) {
|
|
22
|
+
log.error(e)
|
|
23
|
+
}
|
|
18
24
|
const tags = {
|
|
19
25
|
'span.kind': 'client',
|
|
20
26
|
'span.type': 'sql',
|
|
21
27
|
'sql.query': query,
|
|
22
|
-
'db.instance': connectStringObj.pathname.substring(1),
|
|
23
|
-
'db.hostname': connectStringObj.hostname,
|
|
24
28
|
'db.user': this.config.user,
|
|
25
|
-
'db.port': connectStringObj.port,
|
|
26
29
|
'resource.name': query,
|
|
27
30
|
'service.name': service
|
|
28
31
|
}
|
|
32
|
+
if (typeof connectStringObj !== 'undefined') {
|
|
33
|
+
tags['db.instance'] = connectStringObj.pathname.substring(1)
|
|
34
|
+
tags['db.hostname'] = connectStringObj.hostname
|
|
35
|
+
tags['db.port'] = connectStringObj.port
|
|
36
|
+
}
|
|
29
37
|
const store = storage.getStore()
|
|
30
38
|
const childOf = store ? store.span : store
|
|
31
39
|
const span = this.tracer.startSpan('oracle.query', {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const request = require('../../../exporters/common/request')
|
|
3
|
+
const log = require('../../../log')
|
|
4
|
+
|
|
5
|
+
const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
|
|
6
|
+
const BaseWriter = require('../../../exporters/common/writer')
|
|
7
|
+
|
|
8
|
+
function safeJSONStringify (value) {
|
|
9
|
+
return JSON.stringify(value, (key, value) =>
|
|
10
|
+
key !== 'dd-api-key' ? value : undefined
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class Writer extends BaseWriter {
|
|
15
|
+
constructor ({ url }) {
|
|
16
|
+
super(...arguments)
|
|
17
|
+
this._url = url
|
|
18
|
+
this._encoder = new CoverageCIVisibilityEncoder()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_sendPayload (form, _, done) {
|
|
22
|
+
const options = {
|
|
23
|
+
path: '/api/v2/citestcov',
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: {
|
|
26
|
+
'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
|
|
27
|
+
...form.getHeaders()
|
|
28
|
+
},
|
|
29
|
+
timeout: 15000
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
options.protocol = this._url.protocol
|
|
33
|
+
options.hostname = this._url.hostname
|
|
34
|
+
options.port = this._url.port
|
|
35
|
+
|
|
36
|
+
log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
|
|
37
|
+
|
|
38
|
+
request(form, options, (err, res) => {
|
|
39
|
+
if (err) {
|
|
40
|
+
log.error(err)
|
|
41
|
+
done()
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
log.debug(`Response from the intake: ${res}`)
|
|
45
|
+
done()
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = Writer
|