dd-trace 2.12.1 → 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 -1
- package/ext/formats.js +3 -5
- package/package.json +5 -5
- package/packages/datadog-core/src/storage/async_resource.js +19 -1
- package/packages/datadog-instrumentations/index.js +1 -52
- package/packages/datadog-instrumentations/src/connect.js +1 -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 +69 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
- package/packages/datadog-instrumentations/src/jest.js +33 -11
- package/packages/datadog-instrumentations/src/koa.js +1 -1
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/restify.js +27 -5
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
- 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-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
- package/packages/datadog-plugin-oracledb/src/index.js +12 -4
- package/packages/datadog-plugin-restify/src/index.js +7 -0
- 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/ci-visibility/exporters/git/git_metadata.js +220 -0
- package/packages/dd-trace/src/config.js +13 -0
- package/packages/dd-trace/src/encode/0.4.js +55 -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/{profiling/exporters → exporters/common}/form-data.js +0 -0
- package/packages/dd-trace/src/exporters/common/request.js +65 -39
- package/packages/dd-trace/src/exporters/common/writer.js +16 -6
- package/packages/dd-trace/src/id.js +16 -13
- package/packages/dd-trace/src/index.js +10 -0
- package/packages/dd-trace/src/noop/proxy.js +87 -0
- package/packages/dd-trace/src/noop/span.js +12 -12
- package/packages/dd-trace/src/noop/tracer.js +8 -5
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +6 -6
- package/packages/dd-trace/src/opentracing/span.js +63 -49
- package/packages/dd-trace/src/opentracing/span_context.js +1 -5
- package/packages/dd-trace/src/opentracing/tracer.js +31 -36
- package/packages/dd-trace/src/plugin_manager.js +97 -65
- package/packages/dd-trace/src/plugins/index.js +58 -45
- package/packages/dd-trace/src/plugins/util/ci.js +34 -9
- package/packages/dd-trace/src/plugins/util/git.js +52 -2
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
- package/packages/dd-trace/src/proxy.js +18 -90
- package/packages/dd-trace/src/startup-log.js +8 -19
- package/packages/dd-trace/src/telemetry.js +2 -15
- package/scripts/install_plugin_modules.js +17 -26
|
@@ -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
|
|
@@ -161,12 +161,12 @@ class MochaPlugin extends Plugin {
|
|
|
161
161
|
const testSuiteSpan = this._testSuites.get(test.parent)
|
|
162
162
|
|
|
163
163
|
if (testSuiteSpan) {
|
|
164
|
-
const testSuiteId = testSuiteSpan.context()._spanId.toString(
|
|
164
|
+
const testSuiteId = testSuiteSpan.context()._spanId.toString(16)
|
|
165
165
|
testSuiteTags[TEST_SUITE_ID] = testSuiteId
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
if (this.testSessionSpan) {
|
|
169
|
-
const testSessionId = this.testSessionSpan.context()._traceId.toString(
|
|
169
|
+
const testSessionId = this.testSessionSpan.context()._traceId.toString(16)
|
|
170
170
|
testSuiteTags[TEST_SESSION_ID] = testSessionId
|
|
171
171
|
testSuiteTags[TEST_COMMAND] = this.command
|
|
172
172
|
}
|
|
@@ -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
|
|
@@ -2,30 +2,75 @@
|
|
|
2
2
|
|
|
3
3
|
const URL = require('url').URL
|
|
4
4
|
const Writer = require('./writer')
|
|
5
|
-
const
|
|
5
|
+
const CoverageWriter = require('./coverage-writer')
|
|
6
|
+
|
|
7
|
+
const log = require('../../../log')
|
|
6
8
|
|
|
7
9
|
class AgentlessCiVisibilityExporter {
|
|
8
10
|
constructor (config) {
|
|
9
|
-
|
|
11
|
+
this._config = config
|
|
12
|
+
const { tags, site, url, isIntelligentTestRunnerEnabled } = config
|
|
13
|
+
this._isIntelligentTestRunnerEnabled = isIntelligentTestRunnerEnabled
|
|
10
14
|
this._url = url || new URL(`https://citestcycle-intake.${site}`)
|
|
11
15
|
this._writer = new Writer({ url: this._url, tags })
|
|
16
|
+
this._timer = undefined
|
|
17
|
+
this._coverageTimer = undefined
|
|
18
|
+
|
|
19
|
+
this._coverageUrl = url || new URL(`https://event-platform-intake.${site}`)
|
|
20
|
+
this._coverageWriter = new CoverageWriter({ url: this._coverageUrl })
|
|
21
|
+
|
|
22
|
+
process.once('beforeExit', () => {
|
|
23
|
+
this._writer.flush()
|
|
24
|
+
this._coverageWriter.flush()
|
|
25
|
+
})
|
|
26
|
+
}
|
|
12
27
|
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
exportCoverage ({ testSpan, coverageFiles }) {
|
|
29
|
+
const formattedCoverage = {
|
|
30
|
+
traceId: testSpan.context()._traceId,
|
|
31
|
+
spanId: testSpan.context()._spanId,
|
|
32
|
+
files: coverageFiles
|
|
33
|
+
}
|
|
34
|
+
this._coverageWriter.append(formattedCoverage)
|
|
35
|
+
|
|
36
|
+
const { flushInterval } = this._config
|
|
37
|
+
|
|
38
|
+
if (flushInterval === 0) {
|
|
39
|
+
this._coverageWriter.flush()
|
|
40
|
+
} else if (flushInterval > 0 && !this._coverageTimer) {
|
|
41
|
+
this._coverageTimer = setTimeout(() => {
|
|
42
|
+
this._coverageWriter.flush()
|
|
43
|
+
this._coverageTimer = clearTimeout(this._coverageTimer)
|
|
44
|
+
}, flushInterval).unref()
|
|
15
45
|
}
|
|
16
|
-
this._scheduler && this._scheduler.start()
|
|
17
46
|
}
|
|
18
47
|
|
|
19
48
|
export (trace) {
|
|
20
49
|
this._writer.append(trace)
|
|
21
50
|
|
|
22
|
-
|
|
51
|
+
const { flushInterval } = this._config
|
|
52
|
+
|
|
53
|
+
if (flushInterval === 0) {
|
|
23
54
|
this._writer.flush()
|
|
55
|
+
} else if (flushInterval > 0 && !this._timer) {
|
|
56
|
+
this._timer = setTimeout(() => {
|
|
57
|
+
this._writer.flush()
|
|
58
|
+
this._timer = clearTimeout(this._timer)
|
|
59
|
+
}, flushInterval).unref()
|
|
24
60
|
}
|
|
25
61
|
}
|
|
26
62
|
|
|
27
|
-
|
|
28
|
-
|
|
63
|
+
setUrl (url, coverageUrl = url) {
|
|
64
|
+
try {
|
|
65
|
+
url = new URL(url)
|
|
66
|
+
coverageUrl = new URL(coverageUrl)
|
|
67
|
+
this._url = url
|
|
68
|
+
this._coverageUrl = coverageUrl
|
|
69
|
+
this._writer.setUrl(url)
|
|
70
|
+
this._coverageWriter.setUrl(coverageUrl)
|
|
71
|
+
} catch (e) {
|
|
72
|
+
log.error(e)
|
|
73
|
+
}
|
|
29
74
|
}
|
|
30
75
|
}
|
|
31
76
|
|
|
@@ -5,16 +5,37 @@ const log = require('../../../log')
|
|
|
5
5
|
const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
|
|
6
6
|
const BaseWriter = require('../../../exporters/common/writer')
|
|
7
7
|
|
|
8
|
+
function safeJSONStringify (value) {
|
|
9
|
+
return JSON.stringify(value, (key, value) =>
|
|
10
|
+
key !== 'dd-api-key' ? value : undefined
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
class Writer extends BaseWriter {
|
|
9
15
|
constructor ({ url, tags }) {
|
|
10
16
|
super(...arguments)
|
|
11
17
|
const { 'runtime-id': runtimeId, env, service } = tags
|
|
12
18
|
this._url = url
|
|
13
|
-
this._encoder = new AgentlessCiVisibilityEncoder({ runtimeId, env, service })
|
|
19
|
+
this._encoder = new AgentlessCiVisibilityEncoder(this, { runtimeId, env, service })
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
_sendPayload (data, _, done) {
|
|
17
|
-
|
|
23
|
+
const options = {
|
|
24
|
+
path: '/api/v2/citestcycle',
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {
|
|
27
|
+
'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
|
|
28
|
+
'Content-Type': 'application/msgpack'
|
|
29
|
+
},
|
|
30
|
+
timeout: 15000
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
options.protocol = this._url.protocol
|
|
34
|
+
options.hostname = this._url.hostname
|
|
35
|
+
options.port = this._url.port
|
|
36
|
+
|
|
37
|
+
log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
|
|
38
|
+
request(data, options, (err, res) => {
|
|
18
39
|
if (err) {
|
|
19
40
|
log.error(err)
|
|
20
41
|
done()
|
|
@@ -26,26 +47,4 @@ class Writer extends BaseWriter {
|
|
|
26
47
|
}
|
|
27
48
|
}
|
|
28
49
|
|
|
29
|
-
function makeRequest (data, url, cb) {
|
|
30
|
-
const options = {
|
|
31
|
-
path: '/api/v2/citestcycle',
|
|
32
|
-
method: 'POST',
|
|
33
|
-
headers: {
|
|
34
|
-
'Content-Type': 'application/msgpack',
|
|
35
|
-
'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
|
|
36
|
-
},
|
|
37
|
-
timeout: 15000
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
options.protocol = url.protocol
|
|
41
|
-
options.hostname = url.hostname
|
|
42
|
-
options.port = url.port
|
|
43
|
-
|
|
44
|
-
log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
|
|
45
|
-
|
|
46
|
-
request(data, options, false, (err, res) => {
|
|
47
|
-
cb(err, res)
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
50
|
module.exports = Writer
|