dd-trace 5.38.0 → 5.40.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/index.d.ts +30 -21
- package/package.json +4 -2
- package/packages/datadog-instrumentations/src/apollo-server-core.js +1 -1
- package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
- package/packages/datadog-instrumentations/src/express-session.js +41 -0
- package/packages/datadog-instrumentations/src/fetch.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/fetch.js +6 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/jest.js +16 -10
- package/packages/datadog-instrumentations/src/mocha/main.js +2 -1
- package/packages/datadog-instrumentations/src/nyc.js +2 -1
- package/packages/datadog-instrumentations/src/vitest.js +4 -2
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -8
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -4
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +5 -2
- package/packages/datadog-plugin-kafkajs/src/producer.js +4 -3
- package/packages/datadog-plugin-mongodb-core/src/index.js +10 -13
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -2
- package/packages/datadog-shimmer/src/shimmer.js +95 -95
- package/packages/dd-trace/src/appsec/addresses.js +1 -0
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/iast-context.js +2 -2
- package/packages/dd-trace/src/appsec/iast/index.js +0 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -5
- package/packages/dd-trace/src/appsec/index.js +23 -1
- package/packages/dd-trace/src/appsec/reporter.js +3 -8
- package/packages/dd-trace/src/appsec/rule_manager.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/set_user.js +9 -5
- package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -4
- package/packages/dd-trace/src/appsec/telemetry/common.js +24 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +126 -0
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +35 -0
- package/packages/dd-trace/src/appsec/telemetry/user.js +24 -0
- package/packages/dd-trace/src/appsec/telemetry/waf.js +92 -0
- package/packages/dd-trace/src/appsec/user_tracking.js +2 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +16 -4
- package/packages/dd-trace/src/config.js +31 -14
- package/packages/dd-trace/src/constants.js +1 -1
- package/packages/dd-trace/src/{data_streams.js → datastreams/checkpointer.js} +1 -1
- package/packages/dd-trace/src/{data_streams_context.js → datastreams/context.js} +2 -2
- package/packages/dd-trace/src/datastreams/index.js +104 -0
- package/packages/dd-trace/src/datastreams/manager.js +27 -0
- package/packages/dd-trace/src/datastreams/processor.js +1 -44
- package/packages/dd-trace/src/datastreams/size.js +53 -0
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +22 -15
- package/packages/dd-trace/src/dogstatsd.js +23 -4
- package/packages/dd-trace/src/exporters/agent/index.js +2 -2
- package/packages/dd-trace/src/flare/index.js +3 -0
- package/packages/dd-trace/src/noop/dogstatsd.js +6 -0
- package/packages/dd-trace/src/opentelemetry/tracer.js +45 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +11 -47
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +1 -1
- package/packages/dd-trace/src/opentracing/span.js +12 -2
- package/packages/dd-trace/src/payload-tagging/config/aws.json +8 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
- package/packages/dd-trace/src/priority_sampler.js +5 -3
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +15 -4
- package/packages/dd-trace/src/proxy.js +41 -22
- package/packages/dd-trace/src/{appsec/remote_config → remote_config}/capabilities.js +1 -0
- package/packages/dd-trace/src/{appsec/remote_config → remote_config}/index.js +8 -5
- package/packages/dd-trace/src/{appsec/remote_config → remote_config}/manager.js +5 -5
- package/packages/dd-trace/src/runtime_metrics/index.js +34 -0
- package/packages/dd-trace/src/{runtime_metrics.js → runtime_metrics/runtime_metrics.js} +4 -4
- package/packages/dd-trace/src/serverless.js +10 -1
- package/packages/dd-trace/src/service-naming/index.js +12 -4
- package/packages/dd-trace/src/span_processor.js +7 -4
- package/packages/dd-trace/src/span_stats.js +1 -2
- package/packages/dd-trace/src/standalone/index.js +70 -0
- package/packages/dd-trace/src/standalone/product.js +24 -0
- package/packages/dd-trace/src/standalone/tracesource.js +22 -0
- package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +47 -0
- package/packages/dd-trace/src/telemetry/index.js +16 -387
- package/packages/dd-trace/src/telemetry/telemetry.js +394 -0
- package/packages/dd-trace/src/tracer.js +7 -15
- package/packages/dd-trace/src/appsec/standalone.js +0 -130
- package/packages/dd-trace/src/appsec/telemetry.js +0 -218
- package/packages/dd-trace/src/service-naming/schemas/index.js +0 -6
- /package/packages/dd-trace/src/{appsec/remote_config → remote_config}/apply_states.js +0 -0
- /package/packages/dd-trace/src/{appsec/remote_config → remote_config}/scheduler.js +0 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const tracerVersion = require('../../../../package.json').version
|
|
3
|
+
const dc = require('dc-polyfill')
|
|
4
|
+
const os = require('os')
|
|
5
|
+
const dependencies = require('./dependencies')
|
|
6
|
+
const { sendData } = require('./send-data')
|
|
7
|
+
const { errors } = require('../startup-log')
|
|
8
|
+
const { manager: metricsManager } = require('./metrics')
|
|
9
|
+
const telemetryLogger = require('./logs')
|
|
10
|
+
const logger = require('../log')
|
|
11
|
+
|
|
12
|
+
const telemetryStartChannel = dc.channel('datadog:telemetry:start')
|
|
13
|
+
const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
|
|
14
|
+
const telemetryAppClosingChannel = dc.channel('datadog:telemetry:app-closing')
|
|
15
|
+
|
|
16
|
+
let config
|
|
17
|
+
let pluginManager
|
|
18
|
+
|
|
19
|
+
let application
|
|
20
|
+
let host
|
|
21
|
+
let heartbeatTimeout
|
|
22
|
+
let heartbeatInterval
|
|
23
|
+
let extendedInterval
|
|
24
|
+
let integrations
|
|
25
|
+
let configWithOrigin = []
|
|
26
|
+
let retryData = null
|
|
27
|
+
const extendedHeartbeatPayload = {}
|
|
28
|
+
|
|
29
|
+
const sentIntegrations = new Set()
|
|
30
|
+
|
|
31
|
+
function getRetryData () {
|
|
32
|
+
return retryData
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function updateRetryData (error, retryObj) {
|
|
36
|
+
if (error) {
|
|
37
|
+
if (retryObj.reqType === 'message-batch') {
|
|
38
|
+
const payload = retryObj.payload[0].payload
|
|
39
|
+
const reqType = retryObj.payload[0].request_type
|
|
40
|
+
retryData = { payload, reqType }
|
|
41
|
+
|
|
42
|
+
// Since this payload failed twice it now gets save in to the extended heartbeat
|
|
43
|
+
const failedPayload = retryObj.payload[1].payload
|
|
44
|
+
const failedReqType = retryObj.payload[1].request_type
|
|
45
|
+
|
|
46
|
+
// save away the dependencies and integration request for extended heartbeat.
|
|
47
|
+
if (failedReqType === 'app-integrations-change') {
|
|
48
|
+
if (extendedHeartbeatPayload.integrations) {
|
|
49
|
+
extendedHeartbeatPayload.integrations.push(failedPayload)
|
|
50
|
+
} else {
|
|
51
|
+
extendedHeartbeatPayload.integrations = [failedPayload]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (failedReqType === 'app-dependencies-loaded') {
|
|
55
|
+
if (extendedHeartbeatPayload.dependencies) {
|
|
56
|
+
extendedHeartbeatPayload.dependencies.push(failedPayload)
|
|
57
|
+
} else {
|
|
58
|
+
extendedHeartbeatPayload.dependencies = [failedPayload]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
retryData = retryObj
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
retryData = null
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getIntegrations () {
|
|
70
|
+
const newIntegrations = []
|
|
71
|
+
for (const pluginName in pluginManager._pluginsByName) {
|
|
72
|
+
if (sentIntegrations.has(pluginName)) {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
newIntegrations.push({
|
|
76
|
+
name: pluginName,
|
|
77
|
+
enabled: pluginManager._pluginsByName[pluginName]._enabled,
|
|
78
|
+
auto_enabled: true
|
|
79
|
+
})
|
|
80
|
+
sentIntegrations.add(pluginName)
|
|
81
|
+
}
|
|
82
|
+
return newIntegrations
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getProducts (config) {
|
|
86
|
+
const products = {
|
|
87
|
+
appsec: {
|
|
88
|
+
enabled: config.appsec.enabled
|
|
89
|
+
},
|
|
90
|
+
profiler: {
|
|
91
|
+
version: tracerVersion,
|
|
92
|
+
enabled: profilingEnabledToBoolean(config.profiling.enabled)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (errors.profilingError) {
|
|
96
|
+
products.profiler.error = errors.profilingError
|
|
97
|
+
errors.profilingError = {}
|
|
98
|
+
}
|
|
99
|
+
return products
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getInstallSignature (config) {
|
|
103
|
+
const { installSignature: sig } = config
|
|
104
|
+
if (sig && (sig.id || sig.time || sig.type)) {
|
|
105
|
+
return {
|
|
106
|
+
install_id: sig.id,
|
|
107
|
+
install_time: sig.time,
|
|
108
|
+
install_type: sig.type
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function appStarted (config) {
|
|
114
|
+
const app = {
|
|
115
|
+
products: getProducts(config),
|
|
116
|
+
configuration: configWithOrigin
|
|
117
|
+
}
|
|
118
|
+
const installSignature = getInstallSignature(config)
|
|
119
|
+
if (installSignature) {
|
|
120
|
+
app.install_signature = installSignature
|
|
121
|
+
}
|
|
122
|
+
// TODO: add app.error with correct error codes
|
|
123
|
+
// if (errors.agentError) {
|
|
124
|
+
// app.error = errors.agentError
|
|
125
|
+
// errors.agentError = {}
|
|
126
|
+
// }
|
|
127
|
+
return app
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function appClosing () {
|
|
131
|
+
if (!config?.telemetry?.enabled) {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
// Give chance to listeners to update metrics before shutting down.
|
|
135
|
+
telemetryAppClosingChannel.publish()
|
|
136
|
+
const { reqType, payload } = createPayload('app-closing')
|
|
137
|
+
sendData(config, application, host, reqType, payload)
|
|
138
|
+
// We flush before shutting down.
|
|
139
|
+
metricsManager.send(config, application, host)
|
|
140
|
+
telemetryLogger.send(config, application, host)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function onBeforeExit () {
|
|
144
|
+
process.removeListener('beforeExit', onBeforeExit)
|
|
145
|
+
appClosing()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function createAppObject (config) {
|
|
149
|
+
return {
|
|
150
|
+
service_name: config.service,
|
|
151
|
+
env: config.env,
|
|
152
|
+
service_version: config.version,
|
|
153
|
+
tracer_version: tracerVersion,
|
|
154
|
+
language_name: 'nodejs',
|
|
155
|
+
language_version: process.versions.node
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function createHostObject () {
|
|
160
|
+
const osName = os.type()
|
|
161
|
+
|
|
162
|
+
if (osName === 'Linux' || osName === 'Darwin') {
|
|
163
|
+
return {
|
|
164
|
+
hostname: os.hostname(),
|
|
165
|
+
os: osName,
|
|
166
|
+
architecture: os.arch(),
|
|
167
|
+
kernel_version: os.version(),
|
|
168
|
+
kernel_release: os.release(),
|
|
169
|
+
kernel_name: osName
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (osName === 'Windows_NT') {
|
|
174
|
+
return {
|
|
175
|
+
hostname: os.hostname(),
|
|
176
|
+
os: osName,
|
|
177
|
+
architecture: os.arch(),
|
|
178
|
+
os_version: os.version()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
hostname: os.hostname(), // TODO is this enough?
|
|
184
|
+
os: osName
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function getTelemetryData () {
|
|
189
|
+
return { config, application, host, heartbeatInterval }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function createBatchPayload (payload) {
|
|
193
|
+
const batchPayload = payload.map(item => {
|
|
194
|
+
return {
|
|
195
|
+
request_type: item.reqType,
|
|
196
|
+
payload: item.payload
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
return batchPayload
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function createPayload (currReqType, currPayload = {}) {
|
|
204
|
+
if (getRetryData()) {
|
|
205
|
+
const payload = { reqType: currReqType, payload: currPayload }
|
|
206
|
+
const batchPayload = createBatchPayload([payload, retryData])
|
|
207
|
+
return { reqType: 'message-batch', payload: batchPayload }
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return { reqType: currReqType, payload: currPayload }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function heartbeat (config, application, host) {
|
|
214
|
+
heartbeatTimeout = setTimeout(() => {
|
|
215
|
+
metricsManager.send(config, application, host)
|
|
216
|
+
telemetryLogger.send(config, application, host)
|
|
217
|
+
|
|
218
|
+
const { reqType, payload } = createPayload('app-heartbeat')
|
|
219
|
+
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
220
|
+
heartbeat(config, application, host)
|
|
221
|
+
}, heartbeatInterval).unref()
|
|
222
|
+
return heartbeatTimeout
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function extendedHeartbeat (config) {
|
|
226
|
+
extendedInterval = setInterval(() => {
|
|
227
|
+
const appPayload = appStarted(config)
|
|
228
|
+
const payload = {
|
|
229
|
+
...appPayload,
|
|
230
|
+
...extendedHeartbeatPayload
|
|
231
|
+
}
|
|
232
|
+
sendData(config, application, host, 'app-extended-heartbeat', payload)
|
|
233
|
+
Object.keys(extendedHeartbeatPayload).forEach(key => delete extendedHeartbeatPayload[key])
|
|
234
|
+
}, 1000 * 60 * 60 * 24).unref()
|
|
235
|
+
return extendedInterval
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function start (aConfig, thePluginManager) {
|
|
239
|
+
if (!aConfig.telemetry.enabled) {
|
|
240
|
+
if (aConfig.sca?.enabled) {
|
|
241
|
+
logger.warn('DD_APPSEC_SCA_ENABLED requires enabling telemetry to work.')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
config = aConfig
|
|
247
|
+
pluginManager = thePluginManager
|
|
248
|
+
application = createAppObject(config)
|
|
249
|
+
host = createHostObject()
|
|
250
|
+
heartbeatInterval = config.telemetry.heartbeatInterval
|
|
251
|
+
integrations = getIntegrations()
|
|
252
|
+
|
|
253
|
+
dependencies.start(config, application, host, getRetryData, updateRetryData)
|
|
254
|
+
telemetryLogger.start(config)
|
|
255
|
+
|
|
256
|
+
sendData(config, application, host, 'app-started', appStarted(config))
|
|
257
|
+
|
|
258
|
+
if (integrations.length > 0) {
|
|
259
|
+
sendData(config, application, host, 'app-integrations-change',
|
|
260
|
+
{ integrations }, updateRetryData)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
heartbeat(config, application, host)
|
|
264
|
+
|
|
265
|
+
extendedHeartbeat(config)
|
|
266
|
+
|
|
267
|
+
process.on('beforeExit', onBeforeExit)
|
|
268
|
+
telemetryStartChannel.publish(getTelemetryData())
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function stop () {
|
|
272
|
+
if (!config) {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
clearInterval(extendedInterval)
|
|
276
|
+
clearTimeout(heartbeatTimeout)
|
|
277
|
+
process.removeListener('beforeExit', onBeforeExit)
|
|
278
|
+
|
|
279
|
+
telemetryStopChannel.publish(getTelemetryData())
|
|
280
|
+
|
|
281
|
+
config = undefined
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function updateIntegrations () {
|
|
285
|
+
if (!config || !config.telemetry.enabled) {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
const integrations = getIntegrations()
|
|
289
|
+
if (integrations.length === 0) {
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const { reqType, payload } = createPayload('app-integrations-change', { integrations })
|
|
294
|
+
|
|
295
|
+
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function formatMapForTelemetry (map) {
|
|
299
|
+
// format from an object to a string map in order for
|
|
300
|
+
// telemetry intake to accept the configuration
|
|
301
|
+
return map
|
|
302
|
+
? Object.entries(map).map(([key, value]) => `${key}:${value}`).join(',')
|
|
303
|
+
: ''
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function updateConfig (changes, config) {
|
|
307
|
+
if (!config.telemetry.enabled) return
|
|
308
|
+
if (changes.length === 0) return
|
|
309
|
+
|
|
310
|
+
logger.trace(changes)
|
|
311
|
+
|
|
312
|
+
const application = createAppObject(config)
|
|
313
|
+
const host = createHostObject()
|
|
314
|
+
|
|
315
|
+
const nameMapping = {
|
|
316
|
+
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
317
|
+
logInjection: 'DD_LOG_INJECTION',
|
|
318
|
+
headerTags: 'DD_TRACE_HEADER_TAGS',
|
|
319
|
+
tags: 'DD_TAGS',
|
|
320
|
+
'sampler.rules': 'DD_TRACE_SAMPLING_RULES',
|
|
321
|
+
traceEnabled: 'DD_TRACE_ENABLED',
|
|
322
|
+
url: 'DD_TRACE_AGENT_URL',
|
|
323
|
+
'sampler.rateLimit': 'DD_TRACE_RATE_LIMIT',
|
|
324
|
+
queryStringObfuscation: 'DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP',
|
|
325
|
+
version: 'DD_VERSION',
|
|
326
|
+
env: 'DD_ENV',
|
|
327
|
+
service: 'DD_SERVICE',
|
|
328
|
+
clientIpHeader: 'DD_TRACE_CLIENT_IP_HEADER',
|
|
329
|
+
'grpc.client.error.statuses': 'DD_GRPC_CLIENT_ERROR_STATUSES',
|
|
330
|
+
'grpc.server.error.statuses': 'DD_GRPC_SERVER_ERROR_STATUSES',
|
|
331
|
+
traceId128BitLoggingEnabled: 'DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED'
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping', 'serviceMapping'])
|
|
335
|
+
|
|
336
|
+
const configuration = []
|
|
337
|
+
const names = [] // list of config names whose values have been changed
|
|
338
|
+
|
|
339
|
+
for (const change of changes) {
|
|
340
|
+
const name = nameMapping[change.name] || change.name
|
|
341
|
+
|
|
342
|
+
names.push(name)
|
|
343
|
+
const { origin, value } = change
|
|
344
|
+
const entry = { name, value, origin }
|
|
345
|
+
|
|
346
|
+
if (namesNeedFormatting.has(entry.name)) {
|
|
347
|
+
entry.value = formatMapForTelemetry(entry.value)
|
|
348
|
+
} else if (entry.name === 'url') {
|
|
349
|
+
if (entry.value) {
|
|
350
|
+
entry.value = entry.value.toString()
|
|
351
|
+
}
|
|
352
|
+
} else if (entry.name === 'DD_TRACE_SAMPLING_RULES') {
|
|
353
|
+
entry.value = JSON.stringify(entry.value)
|
|
354
|
+
} else if (Array.isArray(entry.value)) {
|
|
355
|
+
entry.value = value.join(',')
|
|
356
|
+
}
|
|
357
|
+
configuration.push(entry)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function isNotModified (entry) {
|
|
361
|
+
return !names.includes(entry.name)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (!configWithOrigin.length) {
|
|
365
|
+
configWithOrigin = configuration
|
|
366
|
+
} else {
|
|
367
|
+
// update configWithOrigin to contain up-to-date full list of config values for app-extended-heartbeat
|
|
368
|
+
configWithOrigin = configWithOrigin.filter(isNotModified)
|
|
369
|
+
configWithOrigin = configWithOrigin.concat(configuration)
|
|
370
|
+
const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
|
|
371
|
+
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function profilingEnabledToBoolean (profilingEnabled) {
|
|
376
|
+
if (typeof profilingEnabled === 'boolean') {
|
|
377
|
+
return profilingEnabled
|
|
378
|
+
}
|
|
379
|
+
if (['auto', 'true'].includes(profilingEnabled)) {
|
|
380
|
+
return true
|
|
381
|
+
}
|
|
382
|
+
if (profilingEnabled === 'false') {
|
|
383
|
+
return false
|
|
384
|
+
}
|
|
385
|
+
return undefined
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
module.exports = {
|
|
389
|
+
start,
|
|
390
|
+
stop,
|
|
391
|
+
updateIntegrations,
|
|
392
|
+
updateConfig,
|
|
393
|
+
appClosing
|
|
394
|
+
}
|
|
@@ -6,10 +6,7 @@ const Scope = require('./scope')
|
|
|
6
6
|
const { isError } = require('./util')
|
|
7
7
|
const { setStartupLogConfig } = require('./startup-log')
|
|
8
8
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
9
|
-
const { DataStreamsProcessor } = require('./datastreams
|
|
10
|
-
const { DsmPathwayCodec } = require('./datastreams/pathway')
|
|
11
|
-
const DataStreamsContext = require('./data_streams_context')
|
|
12
|
-
const { DataStreamsCheckpointer } = require('./data_streams')
|
|
9
|
+
const { DataStreamsCheckpointer, DataStreamsManager, DataStreamsProcessor } = require('./datastreams')
|
|
13
10
|
const { flushStartupLogs } = require('../../datadog-instrumentations/src/check_require_cache')
|
|
14
11
|
const log = require('./log/writer')
|
|
15
12
|
|
|
@@ -22,31 +19,26 @@ class DatadogTracer extends Tracer {
|
|
|
22
19
|
constructor (config, prioritySampler) {
|
|
23
20
|
super(config, prioritySampler)
|
|
24
21
|
this._dataStreamsProcessor = new DataStreamsProcessor(config)
|
|
22
|
+
this._dataStreamsManager = new DataStreamsManager(this._dataStreamsProcessor)
|
|
25
23
|
this.dataStreamsCheckpointer = new DataStreamsCheckpointer(this)
|
|
26
24
|
this._scope = new Scope()
|
|
27
25
|
setStartupLogConfig(config)
|
|
28
26
|
flushStartupLogs(log)
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
configure (
|
|
32
|
-
|
|
29
|
+
configure (config) {
|
|
30
|
+
const { env, sampler } = config
|
|
31
|
+
this._prioritySampler.configure(env, sampler, config)
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
// todo[piochelepiotr] These two methods are not related to the tracer, but to data streams monitoring.
|
|
36
35
|
// They should be moved outside of the tracer in the future.
|
|
37
36
|
setCheckpoint (edgeTags, span, payloadSize = 0) {
|
|
38
|
-
|
|
39
|
-
edgeTags, span, DataStreamsContext.getDataStreamsContext(), payloadSize
|
|
40
|
-
)
|
|
41
|
-
DataStreamsContext.setDataStreamsContext(ctx)
|
|
42
|
-
return ctx
|
|
37
|
+
return this._dataStreamsManager.setCheckpoint(edgeTags, span, payloadSize)
|
|
43
38
|
}
|
|
44
39
|
|
|
45
40
|
decodeDataStreamsContext (carrier) {
|
|
46
|
-
|
|
47
|
-
// we erase the previous context everytime we decode a new one
|
|
48
|
-
DataStreamsContext.setDataStreamsContext(ctx)
|
|
49
|
-
return ctx
|
|
41
|
+
return this._dataStreamsManager.decodeDataStreamsContext(carrier)
|
|
50
42
|
}
|
|
51
43
|
|
|
52
44
|
setOffset (offsetData) {
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { channel } = require('dc-polyfill')
|
|
4
|
-
const { USER_KEEP, AUTO_KEEP, AUTO_REJECT } = require('../../../../ext/priority')
|
|
5
|
-
const { MANUAL_KEEP } = require('../../../../ext/tags')
|
|
6
|
-
const PrioritySampler = require('../priority_sampler')
|
|
7
|
-
const RateLimiter = require('../rate_limiter')
|
|
8
|
-
const TraceState = require('../opentracing/propagation/tracestate')
|
|
9
|
-
const { hasOwn } = require('../util')
|
|
10
|
-
const { APM_TRACING_ENABLED_KEY, APPSEC_PROPAGATION_KEY, SAMPLING_MECHANISM_DEFAULT } = require('../constants')
|
|
11
|
-
|
|
12
|
-
const startCh = channel('dd-trace:span:start')
|
|
13
|
-
const injectCh = channel('dd-trace:span:inject')
|
|
14
|
-
const extractCh = channel('dd-trace:span:extract')
|
|
15
|
-
|
|
16
|
-
let enabled
|
|
17
|
-
|
|
18
|
-
class StandAloneAsmPrioritySampler extends PrioritySampler {
|
|
19
|
-
constructor (env) {
|
|
20
|
-
super(env, { sampleRate: 0, rateLimit: 0, rules: [] })
|
|
21
|
-
|
|
22
|
-
// let some regular APM traces go through, 1 per minute to keep alive the service
|
|
23
|
-
this._limiter = new RateLimiter(1, 'minute')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
configure (env, config) {
|
|
27
|
-
// rules not supported
|
|
28
|
-
this._env = env
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
_getPriorityFromTags (tags, context) {
|
|
32
|
-
if (hasOwn(tags, MANUAL_KEEP) &&
|
|
33
|
-
tags[MANUAL_KEEP] !== false &&
|
|
34
|
-
hasOwn(context._trace.tags, APPSEC_PROPAGATION_KEY)
|
|
35
|
-
) {
|
|
36
|
-
return USER_KEEP
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
_getPriorityFromAuto (span) {
|
|
41
|
-
const context = this._getContext(span)
|
|
42
|
-
|
|
43
|
-
context._sampling.mechanism = SAMPLING_MECHANISM_DEFAULT
|
|
44
|
-
|
|
45
|
-
if (hasOwn(context._trace.tags, APPSEC_PROPAGATION_KEY)) {
|
|
46
|
-
return USER_KEEP
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return this._isSampledByRateLimit(context) ? AUTO_KEEP : AUTO_REJECT
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function onSpanStart ({ span, fields }) {
|
|
54
|
-
const tags = span.context?.()?._tags
|
|
55
|
-
if (!tags) return
|
|
56
|
-
|
|
57
|
-
const { parent } = fields
|
|
58
|
-
if (!parent || parent._isRemote) {
|
|
59
|
-
tags[APM_TRACING_ENABLED_KEY] = 0
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function onSpanInject ({ spanContext, carrier }) {
|
|
64
|
-
if (!spanContext?._trace?.tags || !carrier) return
|
|
65
|
-
|
|
66
|
-
// do not inject trace and sampling if there is no appsec event
|
|
67
|
-
if (!hasOwn(spanContext._trace.tags, APPSEC_PROPAGATION_KEY)) {
|
|
68
|
-
for (const key in carrier) {
|
|
69
|
-
const lKey = key.toLowerCase()
|
|
70
|
-
if (lKey.startsWith('x-datadog')) {
|
|
71
|
-
delete carrier[key]
|
|
72
|
-
} else if (lKey === 'tracestate') {
|
|
73
|
-
const tracestate = TraceState.fromString(carrier[key])
|
|
74
|
-
tracestate.forVendor('dd', state => state.clear())
|
|
75
|
-
carrier[key] = tracestate.toString()
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function onSpanExtract ({ spanContext = {} }) {
|
|
82
|
-
if (!spanContext._trace?.tags || !spanContext._sampling) return
|
|
83
|
-
|
|
84
|
-
// reset upstream priority if _dd.p.appsec is not found
|
|
85
|
-
if (!hasOwn(spanContext._trace.tags, APPSEC_PROPAGATION_KEY)) {
|
|
86
|
-
spanContext._sampling.priority = undefined
|
|
87
|
-
} else if (spanContext._sampling.priority !== USER_KEEP) {
|
|
88
|
-
spanContext._sampling.priority = USER_KEEP
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function sample (span) {
|
|
93
|
-
const spanContext = span.context?.()
|
|
94
|
-
if (enabled && spanContext?._trace?.tags) {
|
|
95
|
-
spanContext._trace.tags[APPSEC_PROPAGATION_KEY] = '1'
|
|
96
|
-
|
|
97
|
-
// TODO: ask. can we reset here sampling like this?
|
|
98
|
-
if (spanContext._sampling?.priority < AUTO_KEEP) {
|
|
99
|
-
spanContext._sampling.priority = undefined
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function configure (config) {
|
|
105
|
-
const configChanged = enabled !== config.appsec?.standalone?.enabled
|
|
106
|
-
if (!configChanged) return
|
|
107
|
-
|
|
108
|
-
enabled = config.appsec?.standalone?.enabled
|
|
109
|
-
|
|
110
|
-
let prioritySampler
|
|
111
|
-
if (enabled) {
|
|
112
|
-
startCh.subscribe(onSpanStart)
|
|
113
|
-
injectCh.subscribe(onSpanInject)
|
|
114
|
-
extractCh.subscribe(onSpanExtract)
|
|
115
|
-
|
|
116
|
-
prioritySampler = new StandAloneAsmPrioritySampler(config.env)
|
|
117
|
-
} else {
|
|
118
|
-
if (startCh.hasSubscribers) startCh.unsubscribe(onSpanStart)
|
|
119
|
-
if (injectCh.hasSubscribers) injectCh.unsubscribe(onSpanInject)
|
|
120
|
-
if (extractCh.hasSubscribers) extractCh.unsubscribe(onSpanExtract)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return prioritySampler
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
module.exports = {
|
|
127
|
-
configure,
|
|
128
|
-
sample,
|
|
129
|
-
StandAloneAsmPrioritySampler
|
|
130
|
-
}
|