dd-trace 5.25.0 → 5.26.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 -0
- package/index.d.ts +10 -8
- package/init.js +60 -47
- package/package.json +5 -2
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-instrumentations/src/express.js +1 -1
- package/packages/datadog-instrumentations/src/handlebars.js +40 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -7
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +34 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +10 -9
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-grpc/src/server.js +2 -1
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -1
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +2 -2
- package/packages/datadog-plugin-rhea/src/consumer.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +2 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +6 -6
- package/packages/dd-trace/src/appsec/recommended.json +353 -155
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +0 -7
- package/packages/dd-trace/src/appsec/reporter.js +1 -0
- package/packages/dd-trace/src/config.js +13 -4
- package/packages/dd-trace/src/constants.js +6 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
- package/packages/dd-trace/src/crashtracking/index.js +15 -0
- package/packages/dd-trace/src/crashtracking/noop.js +8 -0
- package/packages/dd-trace/src/llmobs/sdk.js +1 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +3 -0
- package/packages/dd-trace/src/log/index.js +10 -13
- package/packages/dd-trace/src/log/log.js +52 -0
- package/packages/dd-trace/src/log/writer.js +50 -19
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +15 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -22
- package/packages/dd-trace/src/opentracing/span.js +14 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +39 -11
- package/packages/dd-trace/src/proxy.js +5 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
- package/packages/dd-trace/src/telemetry/metrics.js +6 -1
- package/packages/dd-trace/src/util.js +16 -1
- package/version.js +4 -2
- /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
|
@@ -180,6 +180,20 @@ class DatadogSpan {
|
|
|
180
180
|
})
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
addSpanPointer (ptrKind, ptrDir, ptrHash) {
|
|
184
|
+
const zeroContext = new SpanContext({
|
|
185
|
+
traceId: id('0'),
|
|
186
|
+
spanId: id('0')
|
|
187
|
+
})
|
|
188
|
+
const attributes = {
|
|
189
|
+
'ptr.kind': ptrKind,
|
|
190
|
+
'ptr.dir': ptrDir,
|
|
191
|
+
'ptr.hash': ptrHash,
|
|
192
|
+
'link.kind': 'span-pointer'
|
|
193
|
+
}
|
|
194
|
+
this.addLink(zeroContext, attributes)
|
|
195
|
+
}
|
|
196
|
+
|
|
183
197
|
addEvent (name, attributesOrStartTime, startTime) {
|
|
184
198
|
const event = { name }
|
|
185
199
|
if (attributesOrStartTime) {
|
|
@@ -18,6 +18,7 @@ class DatadogSpanContext {
|
|
|
18
18
|
this._tags = props.tags || {}
|
|
19
19
|
this._sampling = props.sampling || {}
|
|
20
20
|
this._spanSampling = undefined
|
|
21
|
+
this._links = props.links || []
|
|
21
22
|
this._baggageItems = props.baggageItems || {}
|
|
22
23
|
this._traceparent = props.traceparent
|
|
23
24
|
this._tracestate = props.tracestate
|
|
@@ -101,9 +101,8 @@ class TracingPlugin extends Plugin {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
startSpan (name, { childOf, kind, meta, metrics, service, resource, type } = {}, enter = true) {
|
|
104
|
+
startSpan (name, { childOf, kind, meta, metrics, service, resource, type, extractedLinks } = {}, enter = true) {
|
|
105
105
|
const store = storage.getStore()
|
|
106
|
-
|
|
107
106
|
if (store && childOf === undefined) {
|
|
108
107
|
childOf = store.span
|
|
109
108
|
}
|
|
@@ -119,7 +118,8 @@ class TracingPlugin extends Plugin {
|
|
|
119
118
|
...meta,
|
|
120
119
|
...metrics
|
|
121
120
|
},
|
|
122
|
-
integrationName: type
|
|
121
|
+
integrationName: type,
|
|
122
|
+
links: extractedLinks
|
|
123
123
|
})
|
|
124
124
|
|
|
125
125
|
analyticsSampler.sample(span, this.config.measured)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const log = require('../../log')
|
|
2
|
+
const tags = require('../../../../../ext/tags')
|
|
3
|
+
|
|
4
|
+
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
5
|
+
const HTTP_ROUTE = tags.HTTP_ROUTE
|
|
6
|
+
const SPAN_KIND = tags.SPAN_KIND
|
|
7
|
+
const SPAN_TYPE = tags.SPAN_TYPE
|
|
8
|
+
const HTTP_URL = tags.HTTP_URL
|
|
9
|
+
const HTTP_METHOD = tags.HTTP_METHOD
|
|
10
|
+
|
|
11
|
+
const PROXY_HEADER_SYSTEM = 'x-dd-proxy'
|
|
12
|
+
const PROXY_HEADER_START_TIME_MS = 'x-dd-proxy-request-time-ms'
|
|
13
|
+
const PROXY_HEADER_PATH = 'x-dd-proxy-path'
|
|
14
|
+
const PROXY_HEADER_HTTPMETHOD = 'x-dd-proxy-httpmethod'
|
|
15
|
+
const PROXY_HEADER_DOMAIN = 'x-dd-proxy-domain-name'
|
|
16
|
+
const PROXY_HEADER_STAGE = 'x-dd-proxy-stage'
|
|
17
|
+
|
|
18
|
+
const supportedProxies = {
|
|
19
|
+
'aws-apigateway': {
|
|
20
|
+
spanName: 'aws.apigateway',
|
|
21
|
+
component: 'aws-apigateway'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function createInferredProxySpan (headers, childOf, tracer, context) {
|
|
26
|
+
if (!headers) {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!tracer._config?.inferredProxyServicesEnabled) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const proxyContext = extractInferredProxyContext(headers)
|
|
35
|
+
|
|
36
|
+
if (!proxyContext) {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const proxySpanInfo = supportedProxies[proxyContext.proxySystemName]
|
|
41
|
+
|
|
42
|
+
log.debug(`Successfully extracted inferred span info ${proxyContext} for proxy: ${proxyContext.proxySystemName}`)
|
|
43
|
+
|
|
44
|
+
const span = tracer.startSpan(
|
|
45
|
+
proxySpanInfo.spanName,
|
|
46
|
+
{
|
|
47
|
+
childOf,
|
|
48
|
+
type: 'web',
|
|
49
|
+
startTime: proxyContext.requestTime,
|
|
50
|
+
tags: {
|
|
51
|
+
service: proxyContext.domainName || tracer._config.service,
|
|
52
|
+
component: proxySpanInfo.component,
|
|
53
|
+
[SPAN_KIND]: 'internal',
|
|
54
|
+
[SPAN_TYPE]: 'web',
|
|
55
|
+
[HTTP_METHOD]: proxyContext.method,
|
|
56
|
+
[HTTP_URL]: proxyContext.domainName + proxyContext.path,
|
|
57
|
+
[HTTP_ROUTE]: proxyContext.path,
|
|
58
|
+
stage: proxyContext.stage
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
tracer.scope().activate(span)
|
|
64
|
+
context.inferredProxySpan = span
|
|
65
|
+
childOf = span
|
|
66
|
+
|
|
67
|
+
log.debug('Successfully created inferred proxy span.')
|
|
68
|
+
|
|
69
|
+
setInferredProxySpanTags(span, proxyContext)
|
|
70
|
+
|
|
71
|
+
return childOf
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function setInferredProxySpanTags (span, proxyContext) {
|
|
75
|
+
span.setTag(RESOURCE_NAME, `${proxyContext.method} ${proxyContext.path}`)
|
|
76
|
+
span.setTag('_dd.inferred_span', '1')
|
|
77
|
+
return span
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function extractInferredProxyContext (headers) {
|
|
81
|
+
if (!(PROXY_HEADER_START_TIME_MS in headers)) {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!(PROXY_HEADER_SYSTEM in headers && headers[PROXY_HEADER_SYSTEM] in supportedProxies)) {
|
|
86
|
+
log.debug(`Received headers to create inferred proxy span but headers include an unsupported proxy type ${headers}`)
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
requestTime: headers[PROXY_HEADER_START_TIME_MS]
|
|
92
|
+
? parseInt(headers[PROXY_HEADER_START_TIME_MS], 10)
|
|
93
|
+
: null,
|
|
94
|
+
method: headers[PROXY_HEADER_HTTPMETHOD],
|
|
95
|
+
path: headers[PROXY_HEADER_PATH],
|
|
96
|
+
stage: headers[PROXY_HEADER_STAGE],
|
|
97
|
+
domainName: headers[PROXY_HEADER_DOMAIN],
|
|
98
|
+
proxySystemName: headers[PROXY_HEADER_SYSTEM]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function finishInferredProxySpan (context) {
|
|
103
|
+
const { req } = context
|
|
104
|
+
|
|
105
|
+
if (!context.inferredProxySpan) return
|
|
106
|
+
|
|
107
|
+
if (context.inferredProxySpanFinished && !req.stream) return
|
|
108
|
+
|
|
109
|
+
// context.config.hooks.request(context.inferredProxySpan, req, res) # TODO: Do we need this??
|
|
110
|
+
|
|
111
|
+
// Only close the inferred span if one was created
|
|
112
|
+
if (context.inferredProxySpan) {
|
|
113
|
+
context.inferredProxySpan.finish()
|
|
114
|
+
context.inferredProxySpanFinished = true
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
createInferredProxySpan,
|
|
120
|
+
finishInferredProxySpan
|
|
121
|
+
}
|
|
@@ -10,6 +10,7 @@ const kinds = require('../../../../../ext/kinds')
|
|
|
10
10
|
const urlFilter = require('./urlfilter')
|
|
11
11
|
const { extractIp } = require('./ip_extractor')
|
|
12
12
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
|
|
13
|
+
const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
|
|
13
14
|
|
|
14
15
|
const WEB = types.WEB
|
|
15
16
|
const SERVER = kinds.SERVER
|
|
@@ -97,7 +98,7 @@ const web = {
|
|
|
97
98
|
context.span.context()._name = name
|
|
98
99
|
span = context.span
|
|
99
100
|
} else {
|
|
100
|
-
span = web.startChildSpan(tracer, name, req
|
|
101
|
+
span = web.startChildSpan(tracer, name, req)
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
context.tracer = tracer
|
|
@@ -253,9 +254,20 @@ const web = {
|
|
|
253
254
|
},
|
|
254
255
|
|
|
255
256
|
// Extract the parent span from the headers and start a new span as its child
|
|
256
|
-
startChildSpan (tracer, name,
|
|
257
|
-
const
|
|
258
|
-
const
|
|
257
|
+
startChildSpan (tracer, name, req) {
|
|
258
|
+
const headers = req.headers
|
|
259
|
+
const context = contexts.get(req)
|
|
260
|
+
let childOf = tracer.extract(FORMAT_HTTP_HEADERS, headers)
|
|
261
|
+
|
|
262
|
+
// we may have headers signaling a router proxy span should be created (such as for AWS API Gateway)
|
|
263
|
+
if (tracer._config?.inferredProxyServicesEnabled) {
|
|
264
|
+
const proxySpan = createInferredProxySpan(headers, childOf, tracer, context)
|
|
265
|
+
if (proxySpan) {
|
|
266
|
+
childOf = proxySpan
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const span = tracer.startSpan(name, { childOf, extractedLinks: childOf?.links })
|
|
259
271
|
|
|
260
272
|
return span
|
|
261
273
|
},
|
|
@@ -263,13 +275,21 @@ const web = {
|
|
|
263
275
|
// Validate a request's status code and then add error tags if necessary
|
|
264
276
|
addStatusError (req, statusCode) {
|
|
265
277
|
const context = contexts.get(req)
|
|
266
|
-
const span = context
|
|
267
|
-
const error = context.error
|
|
268
|
-
const hasExistingError = span.context()._tags.error || span.context()._tags[ERROR_MESSAGE]
|
|
278
|
+
const { span, inferredProxySpan, error } = context
|
|
269
279
|
|
|
270
|
-
|
|
280
|
+
const spanHasExistingError = span.context()._tags.error || span.context()._tags[ERROR_MESSAGE]
|
|
281
|
+
const inferredSpanContext = inferredProxySpan?.context()
|
|
282
|
+
const inferredSpanHasExistingError = inferredSpanContext?._tags.error || inferredSpanContext?._tags[ERROR_MESSAGE]
|
|
283
|
+
|
|
284
|
+
const isValidStatusCode = context.config.validateStatus(statusCode)
|
|
285
|
+
|
|
286
|
+
if (!spanHasExistingError && !isValidStatusCode) {
|
|
271
287
|
span.setTag(ERROR, error || true)
|
|
272
288
|
}
|
|
289
|
+
|
|
290
|
+
if (inferredProxySpan && !inferredSpanHasExistingError && !isValidStatusCode) {
|
|
291
|
+
inferredProxySpan.setTag(ERROR, error || true)
|
|
292
|
+
}
|
|
273
293
|
},
|
|
274
294
|
|
|
275
295
|
// Add an error to the request
|
|
@@ -316,6 +336,8 @@ const web = {
|
|
|
316
336
|
web.finishMiddleware(context)
|
|
317
337
|
|
|
318
338
|
web.finishSpan(context)
|
|
339
|
+
|
|
340
|
+
finishInferredProxySpan(context)
|
|
319
341
|
},
|
|
320
342
|
|
|
321
343
|
obfuscateQs (config, url) {
|
|
@@ -426,7 +448,7 @@ function reactivate (req, fn) {
|
|
|
426
448
|
}
|
|
427
449
|
|
|
428
450
|
function addRequestTags (context, spanType) {
|
|
429
|
-
const { req, span, config } = context
|
|
451
|
+
const { req, span, inferredProxySpan, config } = context
|
|
430
452
|
const url = extractURL(req)
|
|
431
453
|
|
|
432
454
|
span.addTags({
|
|
@@ -443,6 +465,7 @@ function addRequestTags (context, spanType) {
|
|
|
443
465
|
|
|
444
466
|
if (clientIp) {
|
|
445
467
|
span.setTag(HTTP_CLIENT_IP, clientIp)
|
|
468
|
+
inferredProxySpan?.setTag(HTTP_CLIENT_IP, clientIp)
|
|
446
469
|
}
|
|
447
470
|
}
|
|
448
471
|
|
|
@@ -450,7 +473,7 @@ function addRequestTags (context, spanType) {
|
|
|
450
473
|
}
|
|
451
474
|
|
|
452
475
|
function addResponseTags (context) {
|
|
453
|
-
const { req, res, paths, span } = context
|
|
476
|
+
const { req, res, paths, span, inferredProxySpan } = context
|
|
454
477
|
|
|
455
478
|
if (paths.length > 0) {
|
|
456
479
|
span.setTag(HTTP_ROUTE, paths.join(''))
|
|
@@ -459,6 +482,9 @@ function addResponseTags (context) {
|
|
|
459
482
|
span.addTags({
|
|
460
483
|
[HTTP_STATUS_CODE]: res.statusCode
|
|
461
484
|
})
|
|
485
|
+
inferredProxySpan?.addTags({
|
|
486
|
+
[HTTP_STATUS_CODE]: res.statusCode
|
|
487
|
+
})
|
|
462
488
|
|
|
463
489
|
web.addStatusError(req, res.statusCode)
|
|
464
490
|
}
|
|
@@ -477,7 +503,7 @@ function addResourceTag (context) {
|
|
|
477
503
|
}
|
|
478
504
|
|
|
479
505
|
function addHeaders (context) {
|
|
480
|
-
const { req, res, config, span } = context
|
|
506
|
+
const { req, res, config, span, inferredProxySpan } = context
|
|
481
507
|
|
|
482
508
|
config.headers.forEach(([key, tag]) => {
|
|
483
509
|
const reqHeader = req.headers[key]
|
|
@@ -485,10 +511,12 @@ function addHeaders (context) {
|
|
|
485
511
|
|
|
486
512
|
if (reqHeader) {
|
|
487
513
|
span.setTag(tag || `${HTTP_REQUEST_HEADERS}.${key}`, reqHeader)
|
|
514
|
+
inferredProxySpan?.setTag(tag || `${HTTP_REQUEST_HEADERS}.${key}`, reqHeader)
|
|
488
515
|
}
|
|
489
516
|
|
|
490
517
|
if (resHeader) {
|
|
491
518
|
span.setTag(tag || `${HTTP_RESPONSE_HEADERS}.${key}`, resHeader)
|
|
519
|
+
inferredProxySpan?.setTag(tag || `${HTTP_RESPONSE_HEADERS}.${key}`, resHeader)
|
|
492
520
|
}
|
|
493
521
|
})
|
|
494
522
|
}
|
|
@@ -59,6 +59,11 @@ class Tracer extends NoopProxy {
|
|
|
59
59
|
|
|
60
60
|
try {
|
|
61
61
|
const config = new Config(options) // TODO: support dynamic code config
|
|
62
|
+
|
|
63
|
+
if (config.crashtracking.enabled) {
|
|
64
|
+
require('./crashtracking').start(config)
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
telemetry.start(config, this._pluginManager)
|
|
63
68
|
|
|
64
69
|
if (config.dogstatsd) {
|
|
@@ -35,18 +35,23 @@ function onLog (log) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function onErrorLog (msg) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
level: 'ERROR',
|
|
47
|
-
message: msg
|
|
48
|
-
})
|
|
38
|
+
const { message, cause } = msg
|
|
39
|
+
if (!message && !cause) return
|
|
40
|
+
|
|
41
|
+
const telLog = {
|
|
42
|
+
level: 'ERROR',
|
|
43
|
+
|
|
44
|
+
// existing log.error(err) without message will be reported as 'Generic Error'
|
|
45
|
+
message: message ?? 'Generic Error'
|
|
49
46
|
}
|
|
47
|
+
|
|
48
|
+
if (cause) {
|
|
49
|
+
telLog.stack_trace = cause.stack
|
|
50
|
+
const errorType = cause.name ?? 'Error'
|
|
51
|
+
telLog.message = `${errorType}: ${telLog.message}`
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onLog(telLog)
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
function start (config) {
|
|
@@ -48,16 +48,11 @@ function sanitize (logEntry) {
|
|
|
48
48
|
.map(line => line.replace(ddBasePath, ''))
|
|
49
49
|
|
|
50
50
|
logEntry.stack_trace = stackLines.join(EOL)
|
|
51
|
-
if (logEntry.stack_trace === '') {
|
|
52
|
-
// If entire stack was removed
|
|
53
|
-
// in which case we'd rather not log it at all.
|
|
51
|
+
if (logEntry.stack_trace === '' && !logEntry.message) {
|
|
52
|
+
// If entire stack was removed and there is no message we'd rather not log it at all.
|
|
54
53
|
return null
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
if (!isDDCode) {
|
|
58
|
-
logEntry.message = 'omitted'
|
|
59
|
-
}
|
|
60
|
-
|
|
61
56
|
return logEntry
|
|
62
57
|
}
|
|
63
58
|
|
|
@@ -82,7 +77,7 @@ const logCollector = {
|
|
|
82
77
|
return true
|
|
83
78
|
}
|
|
84
79
|
} catch (e) {
|
|
85
|
-
log.error(
|
|
80
|
+
log.error('Unable to add log to logCollector: %s', e.message)
|
|
86
81
|
}
|
|
87
82
|
return false
|
|
88
83
|
},
|
|
@@ -27,13 +27,18 @@ function hasPoints (metric) {
|
|
|
27
27
|
return metric.points.length > 0
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
let versionTag
|
|
31
|
+
|
|
30
32
|
class Metric {
|
|
31
33
|
constructor (namespace, metric, common, tags) {
|
|
32
34
|
this.namespace = namespace.toString()
|
|
33
35
|
this.metric = common ? metric : `nodejs.${metric}`
|
|
34
36
|
this.tags = tagArray(tags)
|
|
35
37
|
if (common) {
|
|
36
|
-
|
|
38
|
+
if (versionTag === undefined) {
|
|
39
|
+
versionTag = `version:${process.version}`
|
|
40
|
+
}
|
|
41
|
+
this.tags.push(versionTag)
|
|
37
42
|
}
|
|
38
43
|
this.common = common
|
|
39
44
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const crypto = require('crypto')
|
|
3
4
|
const path = require('path')
|
|
4
5
|
|
|
5
6
|
function isTrue (str) {
|
|
@@ -73,11 +74,25 @@ function hasOwn (object, prop) {
|
|
|
73
74
|
return Object.prototype.hasOwnProperty.call(object, prop)
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Generates a unique hash from an array of strings by joining them with | before hashing.
|
|
79
|
+
* Used to uniquely identify AWS requests for span pointers.
|
|
80
|
+
* @param {string[]} components - Array of strings to hash
|
|
81
|
+
* @returns {string} A 32-character hash uniquely identifying the components
|
|
82
|
+
*/
|
|
83
|
+
function generatePointerHash (components) {
|
|
84
|
+
// If passing S3's ETag as a component, make sure any quotes have already been removed!
|
|
85
|
+
const dataToHash = components.join('|')
|
|
86
|
+
const hash = crypto.createHash('sha256').update(dataToHash).digest('hex')
|
|
87
|
+
return hash.substring(0, 32)
|
|
88
|
+
}
|
|
89
|
+
|
|
76
90
|
module.exports = {
|
|
77
91
|
isTrue,
|
|
78
92
|
isFalse,
|
|
79
93
|
isError,
|
|
80
94
|
globMatch,
|
|
81
95
|
calculateDDBasePath,
|
|
82
|
-
hasOwn
|
|
96
|
+
hasOwn,
|
|
97
|
+
generatePointerHash
|
|
83
98
|
}
|
package/version.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/* eslint-disable no-var */
|
|
4
|
+
|
|
5
|
+
var ddMatches = require('./package.json').version.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
6
|
+
var nodeMatches = process.versions.node.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
5
7
|
|
|
6
8
|
module.exports = {
|
|
7
9
|
DD_MAJOR: parseInt(ddMatches[1]),
|