dd-trace 3.0.0-pre.1 → 3.1.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 +2 -2
- package/MIGRATING.md +119 -0
- package/ci/init.js +0 -1
- package/ext/formats.js +3 -5
- package/index.d.ts +1 -11
- package/package.json +7 -7
- package/packages/datadog-core/src/storage/async_resource.js +19 -1
- package/packages/datadog-core/src/storage/index.js +1 -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/grpc/client.js +2 -2
- package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
- package/packages/datadog-instrumentations/src/hapi.js +3 -31
- package/packages/datadog-instrumentations/src/helpers/hooks.js +68 -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/pg.js +2 -2
- 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-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 +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/{profiling/exporters → exporters/common}/form-data.js +0 -0
- package/packages/dd-trace/src/exporters/common/request.js +23 -11
- package/packages/dd-trace/src/exporters/common/writer.js +9 -6
- package/packages/dd-trace/src/id.js +16 -13
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/index.js +10 -0
- package/packages/dd-trace/src/noop/proxy.js +77 -0
- package/packages/dd-trace/src/noop/scope.js +2 -6
- 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 +101 -68
- package/packages/dd-trace/src/plugins/index.js +57 -44
- 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 -71
- package/packages/dd-trace/src/scope.js +1 -58
- 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
- package/ci/jest/env.js +0 -38
|
@@ -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
|
}
|
|
@@ -153,7 +153,10 @@ function mochaHook (Runner) {
|
|
|
153
153
|
if (isHook && testOrHook.ctx) {
|
|
154
154
|
test = testOrHook.ctx.currentTest
|
|
155
155
|
}
|
|
156
|
-
|
|
156
|
+
let asyncResource
|
|
157
|
+
if (test) {
|
|
158
|
+
asyncResource = getTestAsyncResource(test)
|
|
159
|
+
}
|
|
157
160
|
if (asyncResource) {
|
|
158
161
|
asyncResource.runInAsyncScope(() => {
|
|
159
162
|
if (isHook) {
|
|
@@ -11,12 +11,12 @@ const startCh = channel('apm:pg:query:start')
|
|
|
11
11
|
const finishCh = channel('apm:pg:query:finish')
|
|
12
12
|
const errorCh = channel('apm:pg:query:error')
|
|
13
13
|
|
|
14
|
-
addHook({ name: 'pg', versions: ['>=
|
|
14
|
+
addHook({ name: 'pg', versions: ['>=8.0.3'] }, pg => {
|
|
15
15
|
shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
|
|
16
16
|
return pg
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=
|
|
19
|
+
addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=8.0.3'] }, Client => {
|
|
20
20
|
shimmer.wrap(Client.prototype, 'query', query => wrapQuery(query))
|
|
21
21
|
return Client
|
|
22
22
|
})
|
|
@@ -6,7 +6,10 @@ const handlers = ['use', 'pre']
|
|
|
6
6
|
const methods = ['del', 'get', 'head', 'opts', 'post', 'put', 'patch']
|
|
7
7
|
|
|
8
8
|
const handleChannel = channel('apm:restify:request:handle')
|
|
9
|
-
const
|
|
9
|
+
const errorChannel = channel('apm:restify:middleware:error')
|
|
10
|
+
const enterChannel = channel('apm:restify:middleware:enter')
|
|
11
|
+
const exitChannel = channel('apm:restify:middleware:exit')
|
|
12
|
+
const nextChannel = channel('apm:restify:middleware:next')
|
|
10
13
|
|
|
11
14
|
function wrapSetupRequest (setupRequest) {
|
|
12
15
|
return function (req, res) {
|
|
@@ -37,18 +40,37 @@ function wrapFn (fn) {
|
|
|
37
40
|
if (Array.isArray(fn)) return wrapMiddleware(fn)
|
|
38
41
|
|
|
39
42
|
return function (req, res, next) {
|
|
40
|
-
if (
|
|
41
|
-
|
|
43
|
+
if (typeof next === 'function') {
|
|
44
|
+
arguments[2] = wrapNext(req, next)
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
const route = req.route && req.route.path
|
|
48
|
+
|
|
49
|
+
enterChannel.publish({ req, route })
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return fn.apply(this, arguments)
|
|
53
|
+
} catch (error) {
|
|
54
|
+
errorChannel.publish({ req, error })
|
|
55
|
+
nextChannel.publish({ req })
|
|
56
|
+
exitChannel.publish({ req })
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function wrapNext (req, next) {
|
|
62
|
+
return function () {
|
|
63
|
+
nextChannel.publish({ req })
|
|
64
|
+
exitChannel.publish({ req })
|
|
65
|
+
|
|
66
|
+
next.apply(this, arguments)
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
69
|
|
|
48
70
|
addHook({ name: 'restify', versions: ['>=3'], file: 'lib/server.js' }, Server => {
|
|
49
71
|
shimmer.wrap(Server.prototype, '_setupRequest', wrapSetupRequest)
|
|
50
72
|
shimmer.massWrap(Server.prototype, handlers, wrapHandler)
|
|
51
|
-
shimmer.
|
|
73
|
+
shimmer.massWrap(Server.prototype, methods, wrapMethod)
|
|
52
74
|
|
|
53
75
|
return Server
|
|
54
76
|
})
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const Tags = require('opentracing').Tags
|
|
4
3
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
5
4
|
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
6
5
|
const { storage } = require('../../datadog-core')
|
|
@@ -33,7 +32,7 @@ class BaseAwsSdkPlugin extends Plugin {
|
|
|
33
32
|
const serviceName = this.getServiceName(serviceIdentifier)
|
|
34
33
|
const childOf = this.tracer.scope().active()
|
|
35
34
|
const tags = {
|
|
36
|
-
|
|
35
|
+
'span.kind': 'client',
|
|
37
36
|
'service.name': serviceName,
|
|
38
37
|
'aws.operation': operation,
|
|
39
38
|
'aws.region': awsRegion,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const Tags = require('opentracing').Tags
|
|
4
3
|
const log = require('../../../dd-trace/src/log')
|
|
5
4
|
const BaseAwsSdkPlugin = require('../base')
|
|
6
5
|
const { storage } = require('../../../datadog-core')
|
|
@@ -25,7 +24,7 @@ class Sqs extends BaseAwsSdkPlugin {
|
|
|
25
24
|
tags: Object.assign(
|
|
26
25
|
{},
|
|
27
26
|
this.requestTags.get(request) || {},
|
|
28
|
-
{
|
|
27
|
+
{ 'span.kind': 'server' }
|
|
29
28
|
)
|
|
30
29
|
}
|
|
31
30
|
const span = plugin.tracer.startSpan('aws.response', options)
|
|
@@ -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
|
|
@@ -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
|