dd-trace 2.12.0 → 3.0.0-pre.1
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/ci/init.js +2 -26
- package/ci/jest/env.js +2 -3
- package/index.d.ts +0 -7
- package/package.json +1 -1
- package/packages/datadog-instrumentations/src/connect.js +4 -4
- package/packages/datadog-instrumentations/src/fastify.js +12 -25
- package/packages/datadog-instrumentations/src/koa.js +4 -4
- package/packages/datadog-instrumentations/src/router.js +4 -4
- package/packages/datadog-plugin-grpc/src/client.js +2 -2
- package/packages/datadog-plugin-grpc/src/server.js +2 -2
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +13 -8
- package/packages/dd-trace/src/config.js +8 -0
- package/packages/dd-trace/src/encode/0.4.js +4 -0
- package/packages/dd-trace/src/exporters/common/request.js +48 -34
- package/packages/dd-trace/src/exporters/common/writer.js +8 -1
- package/packages/dd-trace/src/noop/tracer.js +0 -4
- package/packages/dd-trace/src/plugin_manager.js +5 -1
- package/packages/dd-trace/src/plugins/index.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +52 -4
- package/packages/dd-trace/src/proxy.js +0 -19
- package/packages/dd-trace/src/scope.js +1 -126
- package/packages/dd-trace/src/tracer.js +0 -4
- package/cypress/plugin.js +0 -5
- package/cypress/support.js +0 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -548
package/ci/init.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
2
|
const tracer = require('../packages/dd-trace')
|
|
5
3
|
const { ORIGIN_KEY } = require('../packages/dd-trace/src/constants')
|
|
6
|
-
const {
|
|
7
|
-
const { pickleHook, testCaseHook } = require('../packages/datadog-instrumentations/src/cucumber')
|
|
4
|
+
const { isTrue } = require('../packages/dd-trace/src/util')
|
|
8
5
|
|
|
9
6
|
const options = {
|
|
10
7
|
startupLogs: false,
|
|
@@ -15,9 +12,7 @@ const options = {
|
|
|
15
12
|
|
|
16
13
|
let shouldInit = true
|
|
17
14
|
|
|
18
|
-
const isAgentlessEnabled = process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED
|
|
19
|
-
process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== 'false' &&
|
|
20
|
-
process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== '0'
|
|
15
|
+
const isAgentlessEnabled = isTrue(process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED)
|
|
21
16
|
|
|
22
17
|
if (isAgentlessEnabled) {
|
|
23
18
|
if (process.env.DATADOG_API_KEY || process.env.DD_API_KEY) {
|
|
@@ -32,25 +27,6 @@ so dd-trace will not be initialized.`)
|
|
|
32
27
|
}
|
|
33
28
|
}
|
|
34
29
|
|
|
35
|
-
// TODO: remove this in a later major version since we now recommend using
|
|
36
|
-
// `NODE_OPTIONS='-r dd-trace/ci/init'`.
|
|
37
|
-
try {
|
|
38
|
-
for (const filename in require.cache) {
|
|
39
|
-
const cache = require.cache[filename]
|
|
40
|
-
const id = filename.split(path.sep).join('/')
|
|
41
|
-
|
|
42
|
-
if (id.includes('/node_modules/mocha/lib/runner.js')) {
|
|
43
|
-
cache.exports = mochaHook(cache.exports)
|
|
44
|
-
} else if (id.includes('/node_modules/@cucumber/cucumber/lib/runtime/pickle_runner.js')) {
|
|
45
|
-
cache.exports = pickleHook(cache.exports)
|
|
46
|
-
} else if (id.includes('/node_modules/@cucumber/cucumber/lib/runtime/test_case_runner.js')) {
|
|
47
|
-
cache.exports = testCaseHook(cache.exports)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
} catch (e) {
|
|
51
|
-
// ignore error and let the tracer initialize anyway
|
|
52
|
-
}
|
|
53
|
-
|
|
54
30
|
if (shouldInit) {
|
|
55
31
|
tracer.init(options)
|
|
56
32
|
tracer.use('fs', false)
|
package/ci/jest/env.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const tracer = require('../../packages/dd-trace')
|
|
4
4
|
const { ORIGIN_KEY } = require('../../packages/dd-trace/src/constants')
|
|
5
|
+
const { isTrue } = require('../../packages/dd-trace/src/util')
|
|
5
6
|
|
|
6
7
|
const options = {
|
|
7
8
|
startupLogs: false,
|
|
@@ -10,9 +11,7 @@ const options = {
|
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const isAgentlessEnabled = process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED
|
|
14
|
-
process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== 'false' &&
|
|
15
|
-
process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== '0'
|
|
14
|
+
const isAgentlessEnabled = isTrue(process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED)
|
|
16
15
|
|
|
17
16
|
if (isAgentlessEnabled) {
|
|
18
17
|
if (process.env.DATADOG_API_KEY || process.env.DD_API_KEY) {
|
package/index.d.ts
CHANGED
|
@@ -562,7 +562,6 @@ interface Plugins {
|
|
|
562
562
|
"elasticsearch": plugins.elasticsearch;
|
|
563
563
|
"express": plugins.express;
|
|
564
564
|
"fastify": plugins.fastify;
|
|
565
|
-
"fs": plugins.fs;
|
|
566
565
|
"generic-pool": plugins.generic_pool;
|
|
567
566
|
"google-cloud-pubsub": plugins.google_cloud_pubsub;
|
|
568
567
|
"graphql": plugins.graphql;
|
|
@@ -903,12 +902,6 @@ declare namespace plugins {
|
|
|
903
902
|
*/
|
|
904
903
|
interface fastify extends HttpServer {}
|
|
905
904
|
|
|
906
|
-
/**
|
|
907
|
-
* This plugin automatically instruments the
|
|
908
|
-
* [fs](https://nodejs.org/api/fs.html) module.
|
|
909
|
-
*/
|
|
910
|
-
interface fs extends Instrumentation {}
|
|
911
|
-
|
|
912
905
|
/**
|
|
913
906
|
* This plugin patches the [generic-pool](https://github.com/coopernurse/node-pool)
|
|
914
907
|
* module to bind the callbacks the the caller context.
|
package/package.json
CHANGED
|
@@ -78,12 +78,12 @@ function wrapLayerHandle (layer) {
|
|
|
78
78
|
|
|
79
79
|
try {
|
|
80
80
|
return original.apply(this, arguments)
|
|
81
|
-
} catch (
|
|
82
|
-
errorChannel.publish(
|
|
81
|
+
} catch (error) {
|
|
82
|
+
errorChannel.publish({ req, error })
|
|
83
83
|
nextChannel.publish({ req })
|
|
84
84
|
exitChannel.publish({ req })
|
|
85
85
|
|
|
86
|
-
throw
|
|
86
|
+
throw error
|
|
87
87
|
}
|
|
88
88
|
})
|
|
89
89
|
})
|
|
@@ -92,7 +92,7 @@ function wrapLayerHandle (layer) {
|
|
|
92
92
|
function wrapNext (req, next) {
|
|
93
93
|
return function (error) {
|
|
94
94
|
if (error) {
|
|
95
|
-
errorChannel.publish(error)
|
|
95
|
+
errorChannel.publish({ req, error })
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
nextChannel.publish({ req })
|
|
@@ -6,7 +6,6 @@ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
|
6
6
|
const errorChannel = channel('apm:fastify:middleware:error')
|
|
7
7
|
const handleChannel = channel('apm:fastify:request:handle')
|
|
8
8
|
|
|
9
|
-
const requestResources = new WeakMap()
|
|
10
9
|
const parsingResources = new WeakMap()
|
|
11
10
|
|
|
12
11
|
function wrapFastify (fastify, hasParsingEvents) {
|
|
@@ -42,16 +41,13 @@ function wrapAddHook (addHook) {
|
|
|
42
41
|
|
|
43
42
|
arguments[arguments.length - 1] = shimmer.wrap(fn, function (request, reply, done) {
|
|
44
43
|
const req = getReq(request)
|
|
45
|
-
const requestResource = requestResources.get(req)
|
|
46
|
-
|
|
47
|
-
if (!requestResource) return fn.apply(this, arguments)
|
|
48
44
|
|
|
49
45
|
try {
|
|
50
46
|
if (typeof done === 'function') {
|
|
51
47
|
done = arguments[arguments.length - 1]
|
|
52
48
|
|
|
53
49
|
arguments[arguments.length - 1] = function (err) {
|
|
54
|
-
publishError(err,
|
|
50
|
+
publishError(err, req)
|
|
55
51
|
|
|
56
52
|
if (name === 'onRequest' || name === 'preParsing') {
|
|
57
53
|
const parsingResource = new AsyncResource('bound-anonymous-fn')
|
|
@@ -71,13 +67,13 @@ function wrapAddHook (addHook) {
|
|
|
71
67
|
const promise = fn.apply(this, arguments)
|
|
72
68
|
|
|
73
69
|
if (promise && typeof promise.catch === 'function') {
|
|
74
|
-
return promise.catch(err => publishError(err,
|
|
70
|
+
return promise.catch(err => publishError(err, req))
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
return promise
|
|
78
74
|
}
|
|
79
75
|
} catch (e) {
|
|
80
|
-
throw publishError(e,
|
|
76
|
+
throw publishError(e, req)
|
|
81
77
|
}
|
|
82
78
|
})
|
|
83
79
|
|
|
@@ -90,14 +86,10 @@ function onRequest (request, reply, done) {
|
|
|
90
86
|
|
|
91
87
|
const req = getReq(request)
|
|
92
88
|
const res = getRes(reply)
|
|
93
|
-
const requestResource = new AsyncResource('bound-anonymous-fn')
|
|
94
89
|
|
|
95
|
-
|
|
90
|
+
handleChannel.publish({ req, res })
|
|
96
91
|
|
|
97
|
-
return
|
|
98
|
-
handleChannel.publish({ req, res })
|
|
99
|
-
return done()
|
|
100
|
-
})
|
|
92
|
+
return done()
|
|
101
93
|
}
|
|
102
94
|
|
|
103
95
|
function preHandler (request, reply, done) {
|
|
@@ -105,9 +97,8 @@ function preHandler (request, reply, done) {
|
|
|
105
97
|
if (!reply || typeof reply.send !== 'function') return done()
|
|
106
98
|
|
|
107
99
|
const req = getReq(request)
|
|
108
|
-
const requestResource = requestResources.get(req)
|
|
109
100
|
|
|
110
|
-
reply.send = wrapSend(reply.send,
|
|
101
|
+
reply.send = wrapSend(reply.send, req)
|
|
111
102
|
|
|
112
103
|
done()
|
|
113
104
|
}
|
|
@@ -133,12 +124,10 @@ function preParsing (request, reply, payload, done) {
|
|
|
133
124
|
parsingResource.runInAsyncScope(() => done())
|
|
134
125
|
}
|
|
135
126
|
|
|
136
|
-
function wrapSend (send,
|
|
137
|
-
return function sendWithTrace (
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
errorChannel.publish(payload)
|
|
141
|
-
})
|
|
127
|
+
function wrapSend (send, req) {
|
|
128
|
+
return function sendWithTrace (error) {
|
|
129
|
+
if (error instanceof Error) {
|
|
130
|
+
errorChannel.publish({ req, error })
|
|
142
131
|
}
|
|
143
132
|
|
|
144
133
|
return send.apply(this, arguments)
|
|
@@ -153,11 +142,9 @@ function getRes (reply) {
|
|
|
153
142
|
return reply && (reply.raw || reply.res || reply)
|
|
154
143
|
}
|
|
155
144
|
|
|
156
|
-
function publishError (error,
|
|
145
|
+
function publishError (error, req) {
|
|
157
146
|
if (error) {
|
|
158
|
-
|
|
159
|
-
errorChannel.publish(error)
|
|
160
|
-
})
|
|
147
|
+
errorChannel.publish({ error, req })
|
|
161
148
|
}
|
|
162
149
|
|
|
163
150
|
return error
|
|
@@ -126,13 +126,13 @@ function wrapMiddleware (fn, layer) {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
function fulfill (ctx, error) {
|
|
129
|
-
if (error) {
|
|
130
|
-
errorChannel.publish(error)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
129
|
const req = ctx.req
|
|
134
130
|
const route = ctx.routePath
|
|
135
131
|
|
|
132
|
+
if (error) {
|
|
133
|
+
errorChannel.publish({ req, error })
|
|
134
|
+
}
|
|
135
|
+
|
|
136
136
|
// TODO: make sure that the parent class cannot override this in `enter`
|
|
137
137
|
if (route) {
|
|
138
138
|
routeChannel.publish({ req, route })
|
|
@@ -49,12 +49,12 @@ function createWrapRouterMethod (name) {
|
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
51
|
return original.apply(this, arguments)
|
|
52
|
-
} catch (
|
|
53
|
-
errorChannel.publish(
|
|
52
|
+
} catch (error) {
|
|
53
|
+
errorChannel.publish({ req, error })
|
|
54
54
|
nextChannel.publish({ req })
|
|
55
55
|
exitChannel.publish({ req })
|
|
56
56
|
|
|
57
|
-
throw
|
|
57
|
+
throw error
|
|
58
58
|
}
|
|
59
59
|
})
|
|
60
60
|
})
|
|
@@ -91,7 +91,7 @@ function createWrapRouterMethod (name) {
|
|
|
91
91
|
function wrapNext (req, next) {
|
|
92
92
|
return function (error) {
|
|
93
93
|
if (error) {
|
|
94
|
-
errorChannel.publish(error)
|
|
94
|
+
errorChannel.publish({ req, error })
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
nextChannel.publish({ req })
|
|
@@ -19,13 +19,13 @@ class GrpcClientPlugin extends Plugin {
|
|
|
19
19
|
const metadataFilter = this.config.metadataFilter
|
|
20
20
|
const store = storage.getStore()
|
|
21
21
|
const childOf = store && store.span
|
|
22
|
-
const span = this.tracer.startSpan('grpc.
|
|
22
|
+
const span = this.tracer.startSpan('grpc.client', {
|
|
23
23
|
childOf,
|
|
24
24
|
tags: {
|
|
25
25
|
[Tags.SPAN_KIND]: 'client',
|
|
26
26
|
'span.type': 'http',
|
|
27
27
|
'resource.name': path,
|
|
28
|
-
'service.name': this.config.service ||
|
|
28
|
+
'service.name': this.config.service || this.tracer._service,
|
|
29
29
|
'component': 'grpc'
|
|
30
30
|
}
|
|
31
31
|
})
|
|
@@ -19,13 +19,13 @@ class GrpcServerPlugin extends Plugin {
|
|
|
19
19
|
const metadataFilter = this.config.metadataFilter
|
|
20
20
|
const store = storage.getStore()
|
|
21
21
|
const childOf = extract(this.tracer, metadata)
|
|
22
|
-
const span = this.tracer.startSpan('grpc.
|
|
22
|
+
const span = this.tracer.startSpan('grpc.server', {
|
|
23
23
|
childOf,
|
|
24
24
|
tags: {
|
|
25
25
|
[Tags.SPAN_KIND]: 'server',
|
|
26
26
|
'span.type': 'web',
|
|
27
27
|
'resource.name': name,
|
|
28
|
-
'service.name': this.config.service ||
|
|
28
|
+
'service.name': this.config.service || this.tracer._service,
|
|
29
29
|
'component': 'grpc'
|
|
30
30
|
}
|
|
31
31
|
})
|
|
@@ -15,7 +15,7 @@ class HttpServerPlugin extends Plugin {
|
|
|
15
15
|
|
|
16
16
|
this.addSub('apm:http:server:request:start', ({ req, res }) => {
|
|
17
17
|
const store = storage.getStore()
|
|
18
|
-
const span = web.startSpan(this.tracer, this.config, req, res, '
|
|
18
|
+
const span = web.startSpan(this.tracer, this.config, req, res, 'web.request')
|
|
19
19
|
|
|
20
20
|
this.enter(span, { ...store, req })
|
|
21
21
|
|
|
@@ -16,7 +16,10 @@ class RouterPlugin extends WebPlugin {
|
|
|
16
16
|
this._contexts = new WeakMap()
|
|
17
17
|
|
|
18
18
|
this.addSub(`apm:${this.constructor.name}:middleware:enter`, ({ req, name, route }) => {
|
|
19
|
-
const childOf = this._getActive(req)
|
|
19
|
+
const childOf = this._getActive(req) || this._getStoreSpan()
|
|
20
|
+
|
|
21
|
+
if (!childOf) return
|
|
22
|
+
|
|
20
23
|
const span = this._getMiddlewareSpan(name, childOf)
|
|
21
24
|
const context = this._createContext(req, route, childOf)
|
|
22
25
|
|
|
@@ -46,14 +49,16 @@ class RouterPlugin extends WebPlugin {
|
|
|
46
49
|
context.middleware.pop().finish()
|
|
47
50
|
})
|
|
48
51
|
|
|
49
|
-
this.addSub(`apm:${this.constructor.name}:middleware:error`,
|
|
50
|
-
|
|
52
|
+
this.addSub(`apm:${this.constructor.name}:middleware:error`, ({ req, error }) => {
|
|
53
|
+
web.addError(req, error)
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
if (!this.config.middleware) return
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
const span = this._getActive(req)
|
|
58
|
+
|
|
59
|
+
if (!span) return
|
|
60
|
+
|
|
61
|
+
span.setTag('error', error)
|
|
57
62
|
})
|
|
58
63
|
|
|
59
64
|
this.addSub(`apm:http:server:request:finish`, ({ req }) => {
|
|
@@ -72,7 +77,7 @@ class RouterPlugin extends WebPlugin {
|
|
|
72
77
|
_getActive (req) {
|
|
73
78
|
const context = this._contexts.get(req)
|
|
74
79
|
|
|
75
|
-
if (!context) return
|
|
80
|
+
if (!context) return
|
|
76
81
|
if (context.middleware.length === 0) return context.span
|
|
77
82
|
|
|
78
83
|
return context.middleware[context.middleware.length - 1]
|
|
@@ -13,6 +13,9 @@ const uuid = require('crypto-randomuuid')
|
|
|
13
13
|
const fromEntries = Object.fromEntries || (entries =>
|
|
14
14
|
entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
|
|
15
15
|
|
|
16
|
+
// eslint-disable-next-line max-len
|
|
17
|
+
const qsRegex = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\\s|%20)*(?::|%3A)(?:\\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\\s|%20)+[a-z0-9\\._\\-]|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\\w=-]|%3D)+\\.ey[I-L](?:[\\w=-]|%3D)+(?:\\.(?:[\\w.+\\/=-]|%3D|%2F|%2B)+)?|[\\-]{5}BEGIN(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY[\\-]{5}[^\\-]+[\\-]{5}END(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY|ssh-rsa(?:\\s|%20)*(?:[a-z0-9\\/\\.+]|%2F|%5C|%2B){100,}'
|
|
18
|
+
|
|
16
19
|
class Config {
|
|
17
20
|
constructor (options) {
|
|
18
21
|
options = options || {}
|
|
@@ -109,6 +112,10 @@ class Config {
|
|
|
109
112
|
parseInt(process.env.DD_TRACE_PARTIAL_FLUSH_MIN_SPANS),
|
|
110
113
|
1000
|
|
111
114
|
)
|
|
115
|
+
const DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP = coalesce(
|
|
116
|
+
process.env.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
|
|
117
|
+
qsRegex
|
|
118
|
+
)
|
|
112
119
|
const DD_TRACE_B3_ENABLED = coalesce(
|
|
113
120
|
options.experimental && options.experimental.b3,
|
|
114
121
|
process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
|
|
@@ -203,6 +210,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
203
210
|
this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
|
|
204
211
|
this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
|
|
205
212
|
this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
|
|
213
|
+
this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
|
|
206
214
|
this.logger = options.logger
|
|
207
215
|
this.plugins = !!coalesce(options.plugins, true)
|
|
208
216
|
this.service = DD_SERVICE
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// TODO: Add test with slow or unresponsive agent.
|
|
4
|
+
// TODO: Add telemetry for things like dropped requests, errors, etc.
|
|
5
|
+
|
|
3
6
|
const http = require('http')
|
|
4
7
|
const https = require('https')
|
|
5
|
-
const log = require('../../log')
|
|
6
8
|
const docker = require('./docker')
|
|
7
9
|
const { storage } = require('../../../../datadog-core')
|
|
8
10
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
+
const keepAlive = true
|
|
12
|
+
const maxTotalSockets = 8
|
|
13
|
+
const httpAgent = new http.Agent({ keepAlive, maxTotalSockets })
|
|
14
|
+
const httpsAgent = new https.Agent({ keepAlive, maxTotalSockets })
|
|
11
15
|
const containerId = docker.id()
|
|
12
16
|
|
|
17
|
+
let activeRequests = 0
|
|
18
|
+
|
|
13
19
|
function request (data, options, keepAlive, callback) {
|
|
14
20
|
if (!options.headers) {
|
|
15
21
|
options.headers = {}
|
|
16
22
|
}
|
|
23
|
+
|
|
24
|
+
// The timeout should be kept low to avoid excessive queueing.
|
|
25
|
+
const timeout = options.timeout || 2000
|
|
17
26
|
const isSecure = options.protocol === 'https:'
|
|
18
27
|
const client = isSecure ? https : http
|
|
19
28
|
const dataArray = [].concat(data)
|
|
29
|
+
|
|
20
30
|
options.headers['Content-Length'] = byteLength(dataArray)
|
|
21
31
|
|
|
22
32
|
if (containerId) {
|
|
@@ -27,39 +37,15 @@ function request (data, options, keepAlive, callback) {
|
|
|
27
37
|
options.agent = isSecure ? httpsAgent : httpAgent
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
const
|
|
31
|
-
dataArray.forEach(buffer => firstRequest.write(buffer))
|
|
32
|
-
|
|
33
|
-
// The first request will be retried
|
|
34
|
-
const firstRequestErrorHandler = () => {
|
|
35
|
-
log.debug('Retrying request to the intake')
|
|
36
|
-
const retriedReq = retriableRequest(options, client, callback)
|
|
37
|
-
dataArray.forEach(buffer => retriedReq.write(buffer))
|
|
38
|
-
// The retried request will fail normally
|
|
39
|
-
retriedReq.on('error', e => callback(new Error(`Network error trying to reach the intake: ${e.message}`)))
|
|
40
|
-
retriedReq.end()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
firstRequest.on('error', firstRequestErrorHandler)
|
|
44
|
-
firstRequest.end()
|
|
45
|
-
|
|
46
|
-
return firstRequest
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function retriableRequest (options, client, callback) {
|
|
50
|
-
const store = storage.getStore()
|
|
51
|
-
|
|
52
|
-
storage.enterWith({ noop: true })
|
|
53
|
-
|
|
54
|
-
const timeout = options.timeout || 15000
|
|
55
|
-
|
|
56
|
-
const request = client.request(options, res => {
|
|
40
|
+
const onResponse = res => {
|
|
57
41
|
let responseData = ''
|
|
58
42
|
|
|
59
43
|
res.setTimeout(timeout)
|
|
60
44
|
|
|
61
45
|
res.on('data', chunk => { responseData += chunk })
|
|
62
46
|
res.on('end', () => {
|
|
47
|
+
activeRequests--
|
|
48
|
+
|
|
63
49
|
if (res.statusCode >= 200 && res.statusCode <= 299) {
|
|
64
50
|
callback(null, responseData, res.statusCode)
|
|
65
51
|
} else {
|
|
@@ -69,15 +55,43 @@ function retriableRequest (options, client, callback) {
|
|
|
69
55
|
callback(error, null, res.statusCode)
|
|
70
56
|
}
|
|
71
57
|
})
|
|
72
|
-
}
|
|
73
|
-
request.setTimeout(timeout, request.abort)
|
|
74
|
-
storage.enterWith(store)
|
|
58
|
+
}
|
|
75
59
|
|
|
76
|
-
|
|
60
|
+
const makeRequest = onError => {
|
|
61
|
+
if (!request.writable) return callback(null)
|
|
62
|
+
|
|
63
|
+
activeRequests++
|
|
64
|
+
|
|
65
|
+
const store = storage.getStore()
|
|
66
|
+
|
|
67
|
+
storage.enterWith({ noop: true })
|
|
68
|
+
|
|
69
|
+
const req = client.request(options, onResponse)
|
|
70
|
+
|
|
71
|
+
req.once('error', err => {
|
|
72
|
+
activeRequests--
|
|
73
|
+
onError(err)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
dataArray.forEach(buffer => req.write(buffer))
|
|
77
|
+
|
|
78
|
+
req.setTimeout(timeout, req.abort)
|
|
79
|
+
req.end()
|
|
80
|
+
|
|
81
|
+
storage.enterWith(store)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
makeRequest(() => makeRequest(callback))
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
function byteLength (data) {
|
|
80
88
|
return data.length > 0 ? data.reduce((prev, next) => prev + next.length, 0) : 0
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
Object.defineProperty(request, 'writable', {
|
|
92
|
+
get () {
|
|
93
|
+
return activeRequests < maxTotalSockets
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
83
97
|
module.exports = request
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
|
|
3
|
+
const request = require('./request')
|
|
2
4
|
const log = require('../../log')
|
|
3
5
|
|
|
4
6
|
class Writer {
|
|
@@ -9,7 +11,10 @@ class Writer {
|
|
|
9
11
|
flush (done = () => {}) {
|
|
10
12
|
const count = this._encoder.count()
|
|
11
13
|
|
|
12
|
-
if (
|
|
14
|
+
if (!request.writable) {
|
|
15
|
+
this._encoder.reset()
|
|
16
|
+
done()
|
|
17
|
+
} else if (count > 0) {
|
|
13
18
|
const payload = this._encoder.makePayload()
|
|
14
19
|
|
|
15
20
|
this._sendPayload(payload, count, done)
|
|
@@ -19,6 +24,8 @@ class Writer {
|
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
append (spans) {
|
|
27
|
+
if (!request.writable) return
|
|
28
|
+
|
|
22
29
|
log.debug(() => `Encoding trace: ${JSON.stringify(spans)}`)
|
|
23
30
|
|
|
24
31
|
this._encode(spans)
|
|
@@ -63,7 +63,7 @@ module.exports = class PluginManager {
|
|
|
63
63
|
|
|
64
64
|
// like instrumenter.enable()
|
|
65
65
|
configure (config = {}) {
|
|
66
|
-
const { logInjection, serviceMapping, experimental } = config
|
|
66
|
+
const { logInjection, serviceMapping, experimental, queryStringObfuscation } = config
|
|
67
67
|
|
|
68
68
|
for (const PluginClass of Object.values(plugins)) {
|
|
69
69
|
const name = PluginClass.name
|
|
@@ -87,6 +87,10 @@ module.exports = class PluginManager {
|
|
|
87
87
|
pluginConfig.logInjection = logInjection
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
if (queryStringObfuscation !== undefined) {
|
|
91
|
+
pluginConfig.queryStringObfuscation = queryStringObfuscation
|
|
92
|
+
}
|
|
93
|
+
|
|
90
94
|
// TODO: update so that it's available for every CI Visibility's plugin
|
|
91
95
|
if (name === 'mocha') {
|
|
92
96
|
pluginConfig.isAgentlessEnabled = experimental && experimental.exporter === 'datadog'
|
|
@@ -15,7 +15,6 @@ module.exports = {
|
|
|
15
15
|
'express': require('../../../datadog-plugin-express/src'),
|
|
16
16
|
'fastify': require('../../../datadog-plugin-fastify/src'),
|
|
17
17
|
'find-my-way': require('../../../datadog-plugin-find-my-way/src'),
|
|
18
|
-
'fs': require('../../../datadog-plugin-fs/src'),
|
|
19
18
|
'google-cloud-pubsub': require('../../../datadog-plugin-google-cloud-pubsub/src'),
|
|
20
19
|
'graphql': require('../../../datadog-plugin-graphql/src'),
|
|
21
20
|
'grpc': require('../../../datadog-plugin-grpc/src'),
|