dd-trace 5.20.0 → 5.22.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/index.d.ts +2 -1
- package/package.json +6 -6
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +4 -4
- package/packages/datadog-instrumentations/src/body-parser.js +17 -5
- package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
- package/packages/datadog-instrumentations/src/child_process.js +2 -2
- package/packages/datadog-instrumentations/src/connect.js +4 -4
- package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
- package/packages/datadog-instrumentations/src/couchbase.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +16 -5
- package/packages/datadog-instrumentations/src/dns.js +10 -10
- package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +3 -3
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fastify.js +6 -6
- package/packages/datadog-instrumentations/src/fetch.js +1 -1
- package/packages/datadog-instrumentations/src/find-my-way.js +2 -2
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +2 -2
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -6
- package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
- package/packages/datadog-instrumentations/src/hapi.js +10 -13
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -2
- package/packages/datadog-instrumentations/src/http/client.js +3 -3
- package/packages/datadog-instrumentations/src/jest.js +5 -4
- package/packages/datadog-instrumentations/src/knex.js +2 -2
- package/packages/datadog-instrumentations/src/koa.js +5 -5
- package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
- package/packages/datadog-instrumentations/src/mariadb.js +8 -8
- package/packages/datadog-instrumentations/src/memcached.js +2 -2
- package/packages/datadog-instrumentations/src/microgateway-core.js +4 -4
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +91 -70
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -3
- package/packages/datadog-instrumentations/src/mocha.js +4 -0
- package/packages/datadog-instrumentations/src/moleculer/server.js +2 -2
- package/packages/datadog-instrumentations/src/mongodb-core.js +7 -7
- package/packages/datadog-instrumentations/src/mongoose.js +5 -6
- package/packages/datadog-instrumentations/src/mysql.js +3 -3
- package/packages/datadog-instrumentations/src/mysql2.js +6 -6
- package/packages/datadog-instrumentations/src/net.js +2 -2
- package/packages/datadog-instrumentations/src/next.js +5 -5
- package/packages/datadog-instrumentations/src/nyc.js +23 -0
- package/packages/datadog-instrumentations/src/openai.js +58 -69
- package/packages/datadog-instrumentations/src/oracledb.js +8 -8
- package/packages/datadog-instrumentations/src/passport-http.js +1 -1
- package/packages/datadog-instrumentations/src/passport-local.js +1 -1
- package/packages/datadog-instrumentations/src/passport-utils.js +1 -1
- package/packages/datadog-instrumentations/src/pg.js +1 -1
- package/packages/datadog-instrumentations/src/pino.js +4 -4
- package/packages/datadog-instrumentations/src/playwright.js +6 -4
- package/packages/datadog-instrumentations/src/redis.js +2 -2
- package/packages/datadog-instrumentations/src/restify.js +4 -4
- package/packages/datadog-instrumentations/src/rhea.js +4 -4
- package/packages/datadog-instrumentations/src/router.js +5 -5
- package/packages/datadog-instrumentations/src/sharedb.js +2 -2
- package/packages/datadog-instrumentations/src/vitest.js +22 -5
- package/packages/datadog-instrumentations/src/winston.js +2 -3
- package/packages/datadog-plugin-cucumber/src/index.js +12 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +21 -10
- package/packages/datadog-plugin-hapi/src/index.js +2 -2
- package/packages/datadog-plugin-jest/src/index.js +18 -4
- package/packages/datadog-plugin-mocha/src/index.js +25 -6
- package/packages/datadog-plugin-nyc/src/index.js +35 -0
- package/packages/datadog-plugin-openai/src/index.js +58 -47
- package/packages/datadog-plugin-playwright/src/index.js +9 -4
- package/packages/datadog-plugin-vitest/src/index.js +30 -4
- package/packages/datadog-shimmer/src/shimmer.js +144 -10
- package/packages/dd-trace/src/appsec/blocking.js +23 -17
- package/packages/dd-trace/src/appsec/graphql.js +3 -1
- package/packages/dd-trace/src/appsec/iast/iast-log.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/manager.js +4 -1
- package/packages/dd-trace/src/appsec/rule_manager.js +8 -0
- package/packages/dd-trace/src/appsec/telemetry.js +3 -3
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +40 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -4
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +8 -7
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -4
- package/packages/dd-trace/src/ci-visibility/telemetry.js +29 -2
- package/packages/dd-trace/src/config.js +157 -142
- package/packages/dd-trace/src/lambda/handler.js +1 -0
- package/packages/dd-trace/src/lambda/index.js +12 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +22 -39
- package/packages/dd-trace/src/opentelemetry/span_context.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +23 -14
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +9 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +61 -6
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/git.js +14 -1
- package/packages/dd-trace/src/plugins/util/test.js +1 -5
- package/packages/dd-trace/src/profiler.js +15 -5
- package/packages/dd-trace/src/profiling/config.js +2 -4
- package/packages/dd-trace/src/profiling/exporter_cli.js +13 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +7 -1
- package/packages/dd-trace/src/profiling/profiler.js +0 -9
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +49 -58
- package/packages/dd-trace/src/proxy.js +21 -21
- package/packages/dd-trace/src/telemetry/index.js +24 -7
- package/packages/dd-trace/src/telemetry/logs/index.js +20 -0
|
@@ -2,61 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
const { AsyncLocalStorage } = require('async_hooks')
|
|
4
4
|
const { trace, ROOT_CONTEXT } = require('@opentelemetry/api')
|
|
5
|
+
const DataDogSpanContext = require('../opentracing/span_context')
|
|
5
6
|
|
|
6
7
|
const SpanContext = require('./span_context')
|
|
7
8
|
const tracer = require('../../')
|
|
8
9
|
|
|
9
|
-
// Horrible hack to acquire the otherwise inaccessible SPAN_KEY so we can redirect it...
|
|
10
|
-
// This is used for getting the current span context in OpenTelemetry, but the SPAN_KEY value is
|
|
11
|
-
// not exposed as it's meant to be read-only from outside the module. We want to hijack this logic
|
|
12
|
-
// so we can instead get the span context from the datadog context manager instead.
|
|
13
|
-
let SPAN_KEY
|
|
14
|
-
trace.getSpan({
|
|
15
|
-
getValue (key) {
|
|
16
|
-
SPAN_KEY = key
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
// Whenever a value is acquired from the context map we should mostly delegate to the real getter,
|
|
21
|
-
// but when accessing the current span we should hijack that access to instead provide a fake span
|
|
22
|
-
// which we can use to get an OTel span context wrapping the datadog active scope span context.
|
|
23
|
-
function wrappedGetValue (target) {
|
|
24
|
-
return (key) => {
|
|
25
|
-
if (key === SPAN_KEY) {
|
|
26
|
-
return {
|
|
27
|
-
spanContext () {
|
|
28
|
-
const activeSpan = tracer.scope().active()
|
|
29
|
-
const context = activeSpan && activeSpan.context()
|
|
30
|
-
return new SpanContext(context)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return target.getValue(key)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
10
|
class ContextManager {
|
|
39
11
|
constructor () {
|
|
40
12
|
this._store = new AsyncLocalStorage()
|
|
41
13
|
}
|
|
42
14
|
|
|
43
15
|
active () {
|
|
44
|
-
const
|
|
16
|
+
const activeSpan = tracer.scope().active()
|
|
17
|
+
const store = this._store.getStore()
|
|
18
|
+
const context = (activeSpan && activeSpan.context()) || store || ROOT_CONTEXT
|
|
45
19
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
if (!(context instanceof DataDogSpanContext)) {
|
|
21
|
+
return context
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!context._otelSpanContext) {
|
|
25
|
+
const newSpanContext = new SpanContext(context)
|
|
26
|
+
context._otelSpanContext = newSpanContext
|
|
27
|
+
}
|
|
28
|
+
if (store && trace.getSpanContext(store) === context._otelSpanContext) {
|
|
29
|
+
return store
|
|
30
|
+
}
|
|
31
|
+
return trace.setSpanContext(store || ROOT_CONTEXT, context._otelSpanContext)
|
|
51
32
|
}
|
|
52
33
|
|
|
53
34
|
with (context, fn, thisArg, ...args) {
|
|
54
35
|
const span = trace.getSpan(context)
|
|
55
36
|
const ddScope = tracer.scope()
|
|
56
|
-
|
|
37
|
+
const run = () => {
|
|
57
38
|
const cb = thisArg == null ? fn : fn.bind(thisArg)
|
|
58
39
|
return this._store.run(context, cb, ...args)
|
|
59
|
-
}
|
|
40
|
+
}
|
|
41
|
+
if (span && span._ddSpan) {
|
|
42
|
+
return ddScope.activate(span._ddSpan, run)
|
|
43
|
+
}
|
|
44
|
+
return run()
|
|
60
45
|
}
|
|
61
46
|
|
|
62
47
|
bind (context, target) {
|
|
@@ -66,9 +51,7 @@ class ContextManager {
|
|
|
66
51
|
}
|
|
67
52
|
}
|
|
68
53
|
|
|
69
|
-
// Not part of the spec but the Node.js API expects these
|
|
70
54
|
enable () {}
|
|
71
55
|
disable () {}
|
|
72
56
|
}
|
|
73
|
-
|
|
74
57
|
module.exports = ContextManager
|
|
@@ -24,11 +24,11 @@ class SpanContext {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
get traceId () {
|
|
27
|
-
return this._ddContext.
|
|
27
|
+
return this._ddContext.toTraceId(true)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
get spanId () {
|
|
31
|
-
return this._ddContext.
|
|
31
|
+
return this._ddContext.toSpanId(true)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
get traceFlags () {
|
|
@@ -7,6 +7,7 @@ const Sampler = require('./sampler')
|
|
|
7
7
|
const Span = require('./span')
|
|
8
8
|
const id = require('../id')
|
|
9
9
|
const SpanContext = require('./span_context')
|
|
10
|
+
const TextMapPropagator = require('../opentracing/propagation/text_map')
|
|
10
11
|
|
|
11
12
|
class Tracer {
|
|
12
13
|
constructor (library, config, tracerProvider) {
|
|
@@ -22,6 +23,24 @@ class Tracer {
|
|
|
22
23
|
return this._tracerProvider.resource
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
_createSpanContextFromParent (parentSpanContext) {
|
|
27
|
+
return new SpanContext({
|
|
28
|
+
traceId: parentSpanContext._traceId,
|
|
29
|
+
spanId: id(),
|
|
30
|
+
parentId: parentSpanContext._spanId,
|
|
31
|
+
sampling: parentSpanContext._sampling,
|
|
32
|
+
baggageItems: Object.assign({}, parentSpanContext._baggageItems),
|
|
33
|
+
trace: parentSpanContext._trace,
|
|
34
|
+
tracestate: parentSpanContext._tracestate
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Extracted method to create span context for a new span
|
|
39
|
+
_createSpanContextForNewSpan (context) {
|
|
40
|
+
const { traceId, spanId, traceFlags, traceState } = context
|
|
41
|
+
return TextMapPropagator._convertOtelContextToDatadog(traceId, spanId, traceFlags, traceState)
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
startSpan (name, options = {}, context = api.context.active()) {
|
|
26
45
|
// remove span from context in case a root span is requested via options
|
|
27
46
|
if (options.root) {
|
|
@@ -29,21 +48,11 @@ class Tracer {
|
|
|
29
48
|
}
|
|
30
49
|
const parentSpan = api.trace.getSpan(context)
|
|
31
50
|
const parentSpanContext = parentSpan && parentSpan.spanContext()
|
|
32
|
-
|
|
33
51
|
let spanContext
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
spanContext = new SpanContext({
|
|
39
|
-
traceId: parent._traceId,
|
|
40
|
-
spanId: id(),
|
|
41
|
-
parentId: parent._spanId,
|
|
42
|
-
sampling: parent._sampling,
|
|
43
|
-
baggageItems: Object.assign({}, parent._baggageItems),
|
|
44
|
-
trace: parent._trace,
|
|
45
|
-
tracestate: parent._tracestate
|
|
46
|
-
})
|
|
52
|
+
if (parentSpanContext && api.trace.isSpanContextValid(parentSpanContext)) {
|
|
53
|
+
spanContext = parentSpanContext._ddContext
|
|
54
|
+
? this._createSpanContextFromParent(parentSpanContext._ddContext)
|
|
55
|
+
: this._createSpanContextForNewSpan(parentSpanContext)
|
|
47
56
|
} else {
|
|
48
57
|
spanContext = new SpanContext()
|
|
49
58
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { trace, context } = require('@opentelemetry/api')
|
|
3
|
+
const { trace, context, propagation } = require('@opentelemetry/api')
|
|
4
|
+
const { W3CTraceContextPropagator } = require('@opentelemetry/core')
|
|
4
5
|
|
|
5
6
|
const tracer = require('../../')
|
|
6
7
|
|
|
@@ -52,6 +53,13 @@ class TracerProvider {
|
|
|
52
53
|
if (!trace.setGlobalTracerProvider(this)) {
|
|
53
54
|
trace.getTracerProvider().setDelegate(this)
|
|
54
55
|
}
|
|
56
|
+
// The default propagator used is the W3C Trace Context propagator, users should be able to pass in others
|
|
57
|
+
// as needed
|
|
58
|
+
if (config.propagator) {
|
|
59
|
+
propagation.setGlobalPropagator(config.propagator)
|
|
60
|
+
} else {
|
|
61
|
+
propagation.setGlobalPropagator(new W3CTraceContextPropagator())
|
|
62
|
+
}
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
forceFlush () {
|
|
@@ -15,7 +15,7 @@ class LogPropagator {
|
|
|
15
15
|
|
|
16
16
|
if (spanContext) {
|
|
17
17
|
if (this._config.traceId128BitLoggingEnabled && spanContext._trace.tags['_dd.p.tid']) {
|
|
18
|
-
carrier.dd.trace_id = spanContext.
|
|
18
|
+
carrier.dd.trace_id = spanContext.toTraceId(true)
|
|
19
19
|
} else {
|
|
20
20
|
carrier.dd.trace_id = spanContext.toTraceId()
|
|
21
21
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const pick = require('../../../../datadog-core/src/utils/src/pick')
|
|
4
4
|
const id = require('../../id')
|
|
5
5
|
const DatadogSpanContext = require('../span_context')
|
|
6
|
+
const OtelSpanContext = require('../../opentelemetry/span_context')
|
|
6
7
|
const log = require('../../log')
|
|
7
8
|
const TraceState = require('./tracestate')
|
|
8
9
|
const tags = require('../../../../../ext/tags')
|
|
@@ -235,8 +236,7 @@ class TextMapPropagator {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
_hasParentIdInTags (spanContext) {
|
|
238
|
-
return tags.DD_PARENT_ID in spanContext._trace.tags
|
|
239
|
-
spanContext._trace.tags[tags.DD_PARENT_ID] !== zeroTraceId
|
|
239
|
+
return tags.DD_PARENT_ID in spanContext._trace.tags
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
_updateParentIdFromDdHeaders (carrier, firstSpanContext) {
|
|
@@ -444,10 +444,6 @@ class TextMapPropagator {
|
|
|
444
444
|
}
|
|
445
445
|
})
|
|
446
446
|
|
|
447
|
-
if (!spanContext._trace.tags[tags.DD_PARENT_ID]) {
|
|
448
|
-
spanContext._trace.tags[tags.DD_PARENT_ID] = zeroTraceId
|
|
449
|
-
}
|
|
450
|
-
|
|
451
447
|
this._extractBaggageItems(carrier, spanContext)
|
|
452
448
|
return spanContext
|
|
453
449
|
}
|
|
@@ -618,6 +614,65 @@ class TextMapPropagator {
|
|
|
618
614
|
|
|
619
615
|
return spanContext._traceId.toString(16)
|
|
620
616
|
}
|
|
617
|
+
|
|
618
|
+
static _convertOtelContextToDatadog (traceId, spanId, traceFlag, ts, meta = {}) {
|
|
619
|
+
const origin = null
|
|
620
|
+
let samplingPriority = traceFlag
|
|
621
|
+
|
|
622
|
+
ts = ts?.traceparent || null
|
|
623
|
+
|
|
624
|
+
if (ts) {
|
|
625
|
+
// Use TraceState.fromString to parse the tracestate header
|
|
626
|
+
const traceState = TraceState.fromString(ts)
|
|
627
|
+
let ddTraceStateData = null
|
|
628
|
+
|
|
629
|
+
// Extract Datadog specific trace state data
|
|
630
|
+
traceState.forVendor('dd', (state) => {
|
|
631
|
+
ddTraceStateData = state
|
|
632
|
+
return state // You might need to adjust this part based on actual logic needed
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
if (ddTraceStateData) {
|
|
636
|
+
// Assuming ddTraceStateData is now a Map or similar structure containing Datadog trace state data
|
|
637
|
+
// Extract values as needed, similar to the original logic
|
|
638
|
+
const samplingPriorityTs = ddTraceStateData.get('s')
|
|
639
|
+
const origin = ddTraceStateData.get('o')
|
|
640
|
+
// Convert Map to object for meta
|
|
641
|
+
const otherPropagatedTags = Object.fromEntries(ddTraceStateData.entries())
|
|
642
|
+
|
|
643
|
+
// Update meta and samplingPriority based on extracted values
|
|
644
|
+
Object.assign(meta, otherPropagatedTags)
|
|
645
|
+
samplingPriority = TextMapPropagator._getSamplingPriority(traceFlag, parseInt(samplingPriorityTs, 10), origin)
|
|
646
|
+
} else {
|
|
647
|
+
log.debug(`no dd list member in tracestate from incoming request: ${ts}`)
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const spanContext = new OtelSpanContext({
|
|
652
|
+
traceId: id(traceId, 16), spanId: id(), tags: meta, parentId: id(spanId, 16)
|
|
653
|
+
})
|
|
654
|
+
|
|
655
|
+
spanContext._sampling = { priority: samplingPriority }
|
|
656
|
+
spanContext._trace = { origin }
|
|
657
|
+
return spanContext
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
static _getSamplingPriority (traceparentSampled, tracestateSamplingPriority, origin = null) {
|
|
661
|
+
const fromRumWithoutPriority = !tracestateSamplingPriority && origin === 'rum'
|
|
662
|
+
|
|
663
|
+
let samplingPriority
|
|
664
|
+
if (!fromRumWithoutPriority && traceparentSampled === 0 &&
|
|
665
|
+
(!tracestateSamplingPriority || tracestateSamplingPriority >= 0)) {
|
|
666
|
+
samplingPriority = 0
|
|
667
|
+
} else if (!fromRumWithoutPriority && traceparentSampled === 1 &&
|
|
668
|
+
(!tracestateSamplingPriority || tracestateSamplingPriority < 0)) {
|
|
669
|
+
samplingPriority = 1
|
|
670
|
+
} else {
|
|
671
|
+
samplingPriority = tracestateSamplingPriority
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return samplingPriority
|
|
675
|
+
}
|
|
621
676
|
}
|
|
622
677
|
|
|
623
678
|
module.exports = TextMapPropagator
|
|
@@ -145,7 +145,7 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
145
145
|
incrementCountMetric(name, {
|
|
146
146
|
testLevel,
|
|
147
147
|
testFramework,
|
|
148
|
-
isUnsupportedCIProvider: this.
|
|
148
|
+
isUnsupportedCIProvider: !this.ciProviderName,
|
|
149
149
|
...tags
|
|
150
150
|
})
|
|
151
151
|
},
|
|
@@ -179,7 +179,7 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
179
179
|
|
|
180
180
|
this.codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
|
|
181
181
|
|
|
182
|
-
this.
|
|
182
|
+
this.ciProviderName = ciProviderName
|
|
183
183
|
|
|
184
184
|
this.testConfiguration = {
|
|
185
185
|
repositoryUrl,
|
|
@@ -69,6 +69,7 @@ module.exports = {
|
|
|
69
69
|
get 'node:http2' () { return require('../../../datadog-plugin-http2/src') },
|
|
70
70
|
get 'node:https' () { return require('../../../datadog-plugin-http/src') },
|
|
71
71
|
get 'node:net' () { return require('../../../datadog-plugin-net/src') },
|
|
72
|
+
get nyc () { return require('../../../datadog-plugin-nyc/src') },
|
|
72
73
|
get oracledb () { return require('../../../datadog-plugin-oracledb/src') },
|
|
73
74
|
get openai () { return require('../../../datadog-plugin-openai/src') },
|
|
74
75
|
get paperplane () { return require('../../../datadog-plugin-paperplane/src') },
|
|
@@ -77,6 +77,18 @@ function isDirectory (path) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function isGitAvailable () {
|
|
81
|
+
const isWindows = os.platform() === 'win32'
|
|
82
|
+
const command = isWindows ? 'where' : 'which'
|
|
83
|
+
try {
|
|
84
|
+
cp.execFileSync(command, ['git'], { stdio: 'pipe' })
|
|
85
|
+
return true
|
|
86
|
+
} catch (e) {
|
|
87
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'check_git', exitCode: 'missing' })
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
80
92
|
function isShallowRepository () {
|
|
81
93
|
return sanitizedExec(
|
|
82
94
|
'git',
|
|
@@ -342,5 +354,6 @@ module.exports = {
|
|
|
342
354
|
getCommitsRevList,
|
|
343
355
|
GIT_REV_LIST_MAX_BUFFER,
|
|
344
356
|
isShallowRepository,
|
|
345
|
-
unshallowRepository
|
|
357
|
+
unshallowRepository,
|
|
358
|
+
isGitAvailable
|
|
346
359
|
}
|
|
@@ -95,9 +95,6 @@ const MOCHA_WORKER_TRACE_PAYLOAD_CODE = 80
|
|
|
95
95
|
const EFD_STRING = "Retried by Datadog's Early Flake Detection"
|
|
96
96
|
const EFD_TEST_NAME_REGEX = new RegExp(EFD_STRING + ' \\(#\\d+\\): ', 'g')
|
|
97
97
|
|
|
98
|
-
// Flaky test retries
|
|
99
|
-
const NUM_FAILED_TEST_RETRIES = 5
|
|
100
|
-
|
|
101
98
|
module.exports = {
|
|
102
99
|
TEST_CODE_OWNERS,
|
|
103
100
|
TEST_FRAMEWORK,
|
|
@@ -170,8 +167,7 @@ module.exports = {
|
|
|
170
167
|
TEST_BROWSER_DRIVER,
|
|
171
168
|
TEST_BROWSER_DRIVER_VERSION,
|
|
172
169
|
TEST_BROWSER_NAME,
|
|
173
|
-
TEST_BROWSER_VERSION
|
|
174
|
-
NUM_FAILED_TEST_RETRIES
|
|
170
|
+
TEST_BROWSER_VERSION
|
|
175
171
|
}
|
|
176
172
|
|
|
177
173
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
@@ -8,8 +8,8 @@ process.once('beforeExit', () => { profiler.stop() })
|
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
10
10
|
start: config => {
|
|
11
|
-
const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA } = config
|
|
12
|
-
const { enabled, sourceMap, exporters
|
|
11
|
+
const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA, injectionEnabled } = config
|
|
12
|
+
const { enabled, sourceMap, exporters } = config.profiling
|
|
13
13
|
const logger = {
|
|
14
14
|
debug: (message) => log.debug(message),
|
|
15
15
|
info: (message) => log.info(message),
|
|
@@ -17,9 +17,17 @@ module.exports = {
|
|
|
17
17
|
error: (message) => log.error(message)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
const libraryInjected = injectionEnabled.length > 0
|
|
21
|
+
let activation
|
|
22
|
+
if (enabled === 'auto') {
|
|
23
|
+
activation = 'auto'
|
|
24
|
+
} else if (enabled === 'true') {
|
|
25
|
+
activation = 'manual'
|
|
26
|
+
} else if (injectionEnabled.includes('profiler')) {
|
|
27
|
+
activation = 'injection'
|
|
28
|
+
} // else activation = undefined
|
|
29
|
+
|
|
20
30
|
return profiler.start({
|
|
21
|
-
enabled,
|
|
22
|
-
heuristicsEnabled,
|
|
23
31
|
service,
|
|
24
32
|
version,
|
|
25
33
|
env,
|
|
@@ -31,7 +39,9 @@ module.exports = {
|
|
|
31
39
|
port,
|
|
32
40
|
tags,
|
|
33
41
|
repositoryUrl,
|
|
34
|
-
commitSHA
|
|
42
|
+
commitSHA,
|
|
43
|
+
libraryInjected,
|
|
44
|
+
activation
|
|
35
45
|
})
|
|
36
46
|
},
|
|
37
47
|
|
|
@@ -23,7 +23,6 @@ class Config {
|
|
|
23
23
|
DD_PROFILING_CODEHOTSPOTS_ENABLED,
|
|
24
24
|
DD_PROFILING_CPU_ENABLED,
|
|
25
25
|
DD_PROFILING_DEBUG_SOURCE_MAPS,
|
|
26
|
-
DD_PROFILING_ENABLED,
|
|
27
26
|
DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
|
|
28
27
|
DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED,
|
|
29
28
|
DD_PROFILING_EXPERIMENTAL_CPU_ENABLED,
|
|
@@ -49,7 +48,6 @@ class Config {
|
|
|
49
48
|
DD_VERSION
|
|
50
49
|
} = process.env
|
|
51
50
|
|
|
52
|
-
const enabled = isTrue(coalesce(options.enabled, DD_PROFILING_ENABLED, true))
|
|
53
51
|
const env = coalesce(options.env, DD_ENV)
|
|
54
52
|
const service = options.service || DD_SERVICE || 'node'
|
|
55
53
|
const host = os.hostname()
|
|
@@ -64,8 +62,6 @@ class Config {
|
|
|
64
62
|
const pprofPrefix = coalesce(options.pprofPrefix,
|
|
65
63
|
DD_PROFILING_PPROF_PREFIX, '')
|
|
66
64
|
|
|
67
|
-
this.enabled = enabled
|
|
68
|
-
this.heuristicsEnabled = options.heuristicsEnabled
|
|
69
65
|
this.service = service
|
|
70
66
|
this.env = env
|
|
71
67
|
this.host = host
|
|
@@ -129,6 +125,8 @@ class Config {
|
|
|
129
125
|
port
|
|
130
126
|
})))
|
|
131
127
|
|
|
128
|
+
this.libraryInjected = options.libraryInjected
|
|
129
|
+
this.activation = options.activation
|
|
132
130
|
this.exporters = ensureExporters(options.exporters || [
|
|
133
131
|
new AgentExporter(this)
|
|
134
132
|
], this)
|
|
@@ -16,10 +16,22 @@ function exporterFromURL (url) {
|
|
|
16
16
|
if (url.protocol === 'file:') {
|
|
17
17
|
return new FileExporter({ pprofPrefix: fileURLToPath(url) })
|
|
18
18
|
} else {
|
|
19
|
+
const injectionEnabled = (process.env.DD_INJECTION_ENABLED || '').split(',')
|
|
20
|
+
const libraryInjected = injectionEnabled.length > 0
|
|
21
|
+
const profilingEnabled = (process.env.DD_PROFILING_ENABLED || '').toLowerCase()
|
|
22
|
+
const activation = ['true', '1'].includes(profilingEnabled)
|
|
23
|
+
? 'manual'
|
|
24
|
+
: profilingEnabled === 'auto'
|
|
25
|
+
? 'auto'
|
|
26
|
+
: injectionEnabled.includes('profiling')
|
|
27
|
+
? 'injection'
|
|
28
|
+
: 'unknown'
|
|
19
29
|
return new AgentExporter({
|
|
20
30
|
url,
|
|
21
31
|
logger,
|
|
22
|
-
uploadTimeout: timeoutMs
|
|
32
|
+
uploadTimeout: timeoutMs,
|
|
33
|
+
libraryInjected,
|
|
34
|
+
activation
|
|
23
35
|
})
|
|
24
36
|
}
|
|
25
37
|
}
|
|
@@ -53,7 +53,7 @@ function computeRetries (uploadTimeout) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
class AgentExporter {
|
|
56
|
-
constructor ({ url, logger, uploadTimeout, env, host, service, version } = {}) {
|
|
56
|
+
constructor ({ url, logger, uploadTimeout, env, host, service, version, libraryInjected, activation } = {}) {
|
|
57
57
|
this._url = url
|
|
58
58
|
this._logger = logger
|
|
59
59
|
|
|
@@ -65,6 +65,8 @@ class AgentExporter {
|
|
|
65
65
|
this._host = host
|
|
66
66
|
this._service = service
|
|
67
67
|
this._appVersion = version
|
|
68
|
+
this._libraryInjected = !!libraryInjected
|
|
69
|
+
this._activation = activation || 'unknown'
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
export ({ profiles, start, end, tags }) {
|
|
@@ -105,6 +107,10 @@ class AgentExporter {
|
|
|
105
107
|
kernel_version: os.version()
|
|
106
108
|
},
|
|
107
109
|
profiler: {
|
|
110
|
+
activation: this._activation,
|
|
111
|
+
ssi: {
|
|
112
|
+
mechanism: this._libraryInjected ? 'injected_agent' : 'none'
|
|
113
|
+
},
|
|
108
114
|
version
|
|
109
115
|
},
|
|
110
116
|
runtime: {
|
|
@@ -5,7 +5,6 @@ const { Config } = require('./config')
|
|
|
5
5
|
const { snapshotKinds } = require('./constants')
|
|
6
6
|
const { threadNamePrefix } = require('./profilers/shared')
|
|
7
7
|
const dc = require('dc-polyfill')
|
|
8
|
-
const telemetryLog = dc.channel('datadog:telemetry:log')
|
|
9
8
|
|
|
10
9
|
const profileSubmittedChannel = dc.channel('datadog:profiling:profile-submitted')
|
|
11
10
|
|
|
@@ -20,13 +19,6 @@ function logError (logger, err) {
|
|
|
20
19
|
if (logger) {
|
|
21
20
|
logger.error(err)
|
|
22
21
|
}
|
|
23
|
-
if (telemetryLog.hasSubscribers) {
|
|
24
|
-
telemetryLog.publish({
|
|
25
|
-
message: err.message,
|
|
26
|
-
level: 'ERROR',
|
|
27
|
-
stack_trace: err.stack
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
22
|
}
|
|
31
23
|
|
|
32
24
|
class Profiler extends EventEmitter {
|
|
@@ -55,7 +47,6 @@ class Profiler extends EventEmitter {
|
|
|
55
47
|
if (this._enabled) return true
|
|
56
48
|
|
|
57
49
|
const config = this._config = new Config(options)
|
|
58
|
-
if (!config.enabled && !config.heuristicsEnabled) return false
|
|
59
50
|
|
|
60
51
|
this._logger = config.logger
|
|
61
52
|
this._enabled = true
|