dd-trace 5.56.0 → 5.57.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/index.d.ts +44 -2
- package/init.js +4 -1
- package/package.json +20 -20
- package/packages/datadog-esbuild/index.js +22 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +4 -6
- package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
- package/packages/datadog-instrumentations/src/fastify.js +91 -9
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
- package/packages/datadog-instrumentations/src/ioredis.js +8 -13
- package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
- package/packages/datadog-instrumentations/src/jest.js +28 -6
- package/packages/datadog-instrumentations/src/memcached.js +17 -24
- package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
- package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
- package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
- package/packages/datadog-instrumentations/src/openai.js +30 -2
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +116 -0
- package/packages/datadog-instrumentations/src/redis.js +32 -43
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/sharedb.js +10 -16
- package/packages/datadog-instrumentations/src/vitest.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-bunyan/src/index.js +2 -2
- package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +4 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
- package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
- package/packages/datadog-plugin-http/src/client.js +1 -0
- package/packages/datadog-plugin-http/src/server.js +2 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -0
- package/packages/datadog-plugin-http2/src/server.js +1 -0
- package/packages/datadog-plugin-jest/src/index.js +4 -3
- package/packages/datadog-plugin-memcached/src/index.js +6 -2
- package/packages/datadog-plugin-mocha/src/index.js +3 -2
- package/packages/datadog-plugin-moleculer/src/client.js +15 -9
- package/packages/datadog-plugin-moleculer/src/server.js +9 -5
- package/packages/datadog-plugin-next/src/index.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +127 -80
- package/packages/datadog-plugin-pino/src/index.js +2 -2
- package/packages/datadog-plugin-prisma/src/client.js +62 -0
- package/packages/datadog-plugin-prisma/src/engine.js +81 -0
- package/packages/datadog-plugin-prisma/src/index.js +22 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +9 -3
- package/packages/datadog-plugin-router/src/index.js +1 -0
- package/packages/datadog-plugin-sharedb/src/index.js +13 -5
- package/packages/datadog-plugin-winston/src/index.js +2 -2
- package/packages/dd-trace/src/appsec/channels.js +26 -21
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +16 -1
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
- package/packages/dd-trace/src/config.js +286 -270
- package/packages/dd-trace/src/constants.js +2 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
- package/packages/dd-trace/src/datastreams/context.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
- package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
- package/packages/dd-trace/src/dogstatsd.js +3 -3
- package/packages/dd-trace/src/exporters/agent/index.js +10 -5
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/log/index.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
- package/packages/dd-trace/src/guardrails/index.js +3 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/index.js +11 -5
- package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +13 -13
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
- package/packages/dd-trace/src/opentracing/span.js +1 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/cache.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
- package/packages/dd-trace/src/plugins/database.js +3 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
- package/packages/dd-trace/src/plugins/outbound.js +8 -6
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +83 -30
- package/packages/dd-trace/src/plugins/util/git.js +1 -0
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/test.js +80 -10
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiler.js +0 -2
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
- package/packages/dd-trace/src/proxy.js +12 -27
- package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/supported-configurations.json +12 -3
- package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
- package/packages/dd-trace/src/tracer.js +11 -0
- package/packages/dd-trace/src/tracer_metadata.js +25 -0
- package/packages/dd-trace/src/util.js +11 -4
- package/version.js +3 -1
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const telemetryMetrics = require('../telemetry/metrics')
|
|
4
|
-
const profilersNamespace = telemetryMetrics.manager.namespace('profilers')
|
|
5
3
|
const dc = require('dc-polyfill')
|
|
6
4
|
const log = require('../log')
|
|
7
5
|
|
|
@@ -9,42 +7,17 @@ const log = require('../log')
|
|
|
9
7
|
const DEFAULT_LONG_LIVED_THRESHOLD = 30_000
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
|
-
* This class embodies the SSI profiler-triggering heuristics
|
|
13
|
-
* the profiler behavior under SSI. It emits the following metrics:
|
|
14
|
-
* - `number_of_profiles`: The number of profiles that were submitted
|
|
15
|
-
* - `number_of_runtime_id`: The number of runtime IDs in the app (always 1 for Node.js, emitted
|
|
16
|
-
* once when the tags won't change for the remaineder of of the app's lifetime.)
|
|
17
|
-
* It will also add tags describing the state of heuristics triggers, the enablement choice, and
|
|
18
|
-
* whether actual profiles were sent (as opposed to mock profiles). There is a mock profiler that is
|
|
19
|
-
* activated when the profiler is not enabled, and it will emit mock profile submission events at
|
|
20
|
-
* the same cadence the profiler would, providing insight into how many profiles would've been
|
|
21
|
-
* emitted if SSI enabled profiling. Note that heuristics (and thus telemetry) is per tracer
|
|
22
|
-
* instance, and each worker thread will have its own instance.
|
|
10
|
+
* This class embodies the SSI profiler-triggering heuristics under SSI.
|
|
23
11
|
*/
|
|
24
12
|
class SSIHeuristics {
|
|
25
13
|
constructor (config) {
|
|
26
|
-
const injectionIncludesProfiler = config.injectionEnabled.includes('profiler')
|
|
27
|
-
this._heuristicsActive = injectionIncludesProfiler || config.profiling.enabled === 'auto'
|
|
28
|
-
this._emitsTelemetry = config.injectionEnabled.length > 0 && config.profiling.enabled !== 'false'
|
|
29
|
-
|
|
30
|
-
if (this._emitsTelemetry) {
|
|
31
|
-
if (config.profiling.enabled === 'true') {
|
|
32
|
-
this.enablementChoice = 'manually_enabled'
|
|
33
|
-
} else if (injectionIncludesProfiler) {
|
|
34
|
-
this.enablementChoice = 'ssi_enabled'
|
|
35
|
-
} else if (config.profiling.enabled === 'auto') {
|
|
36
|
-
this.enablementChoice = 'auto_enabled'
|
|
37
|
-
} else {
|
|
38
|
-
this.enablementChoice = 'ssi_not_enabled'
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
14
|
const longLivedThreshold = config.profiling.longLivedThreshold || DEFAULT_LONG_LIVED_THRESHOLD
|
|
43
15
|
if (typeof longLivedThreshold !== 'number' || longLivedThreshold <= 0) {
|
|
44
16
|
this.longLivedThreshold = DEFAULT_LONG_LIVED_THRESHOLD
|
|
45
17
|
log.warn(
|
|
46
|
-
|
|
47
|
-
|
|
18
|
+
'Invalid SSIHeuristics.longLivedThreshold value: %s. Using default value:',
|
|
19
|
+
config.profiling.longLivedThreshold,
|
|
20
|
+
DEFAULT_LONG_LIVED_THRESHOLD
|
|
48
21
|
)
|
|
49
22
|
} else {
|
|
50
23
|
this.longLivedThreshold = longLivedThreshold
|
|
@@ -55,39 +28,21 @@ class SSIHeuristics {
|
|
|
55
28
|
this.shortLived = true
|
|
56
29
|
}
|
|
57
30
|
|
|
58
|
-
get emitsTelemetry () {
|
|
59
|
-
return this._emitsTelemetry
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get heuristicsActive () {
|
|
63
|
-
return this._heuristicsActive
|
|
64
|
-
}
|
|
65
|
-
|
|
66
31
|
start () {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this._onProfileSubmitted = this._onProfileSubmitted.bind(this)
|
|
82
|
-
this._onMockProfileSubmitted = this._onMockProfileSubmitted.bind(this)
|
|
83
|
-
|
|
84
|
-
dc.subscribe('datadog:profiling:profile-submitted', this._onProfileSubmitted)
|
|
85
|
-
dc.subscribe('datadog:profiling:mock-profile-submitted', this._onMockProfileSubmitted)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
this._onAppClosing = this._onAppClosing.bind(this)
|
|
89
|
-
dc.subscribe('datadog:telemetry:app-closing', this._onAppClosing)
|
|
90
|
-
}
|
|
32
|
+
// Used to determine short-livedness of the process. We could use the process start time as the
|
|
33
|
+
// reference point, but the tracer initialization point is more relevant, as we couldn't be
|
|
34
|
+
// collecting profiles earlier anyway. The difference is not particularly significant if the
|
|
35
|
+
// tracer is initialized early in the process lifetime.
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
this.shortLived = false
|
|
38
|
+
this._maybeTriggered()
|
|
39
|
+
}, this.longLivedThreshold).unref()
|
|
40
|
+
|
|
41
|
+
this._onSpanCreated = this._onSpanCreated.bind(this)
|
|
42
|
+
dc.subscribe('dd-trace:span:start', this._onSpanCreated)
|
|
43
|
+
|
|
44
|
+
this._onAppClosing = this._onAppClosing.bind(this)
|
|
45
|
+
dc.subscribe('datadog:telemetry:app-closing', this._onAppClosing)
|
|
91
46
|
}
|
|
92
47
|
|
|
93
48
|
onTriggered (callback) {
|
|
@@ -118,70 +73,7 @@ class SSIHeuristics {
|
|
|
118
73
|
dc.unsubscribe('dd-trace:span:start', this._onSpanCreated)
|
|
119
74
|
}
|
|
120
75
|
|
|
121
|
-
_onProfileSubmitted () {
|
|
122
|
-
this.hasSentProfiles = true
|
|
123
|
-
this._incProfileCount()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
_onMockProfileSubmitted () {
|
|
127
|
-
this._incProfileCount()
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
_incProfileCount () {
|
|
131
|
-
this._ensureProfileMetrics()
|
|
132
|
-
this._profileCount.inc()
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
_ensureProfileMetrics () {
|
|
136
|
-
const decision = []
|
|
137
|
-
if (this.noSpan) {
|
|
138
|
-
decision.push('no_span')
|
|
139
|
-
}
|
|
140
|
-
if (this.shortLived) {
|
|
141
|
-
decision.push('short_lived')
|
|
142
|
-
}
|
|
143
|
-
if (decision.length === 0) {
|
|
144
|
-
decision.push('triggered')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const tags = [
|
|
148
|
-
'installation:ssi',
|
|
149
|
-
`enablement_choice:${this.enablementChoice}`,
|
|
150
|
-
`has_sent_profiles:${this.hasSentProfiles}`,
|
|
151
|
-
`heuristic_hypothetical_decision:${decision.join('_')}`
|
|
152
|
-
]
|
|
153
|
-
|
|
154
|
-
this._profileCount = profilersNamespace.count('ssi_heuristic.number_of_profiles', tags)
|
|
155
|
-
this._runtimeIdCount = profilersNamespace.count('ssi_heuristic.number_of_runtime_id', tags)
|
|
156
|
-
|
|
157
|
-
if (
|
|
158
|
-
!this._emittedRuntimeId &&
|
|
159
|
-
decision[0] === 'triggered' &&
|
|
160
|
-
// When heuristics are active, hasSentProfiles can transition from false to true when the
|
|
161
|
-
// profiler gets started and the first profile is submitted, so we have to wait for it.
|
|
162
|
-
(!this.heuristicsActive || this.hasSentProfiles)
|
|
163
|
-
) {
|
|
164
|
-
// Tags won't change anymore, so we can emit the runtime ID metric now.
|
|
165
|
-
this._emittedRuntimeId = true
|
|
166
|
-
this._runtimeIdCount.inc()
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
76
|
_onAppClosing () {
|
|
171
|
-
if (this.emitsTelemetry) {
|
|
172
|
-
this._ensureProfileMetrics()
|
|
173
|
-
// Last ditch effort to emit a runtime ID count metric
|
|
174
|
-
if (!this._emittedRuntimeId) {
|
|
175
|
-
this._emittedRuntimeId = true
|
|
176
|
-
this._runtimeIdCount.inc()
|
|
177
|
-
}
|
|
178
|
-
// So we have the metrics in the final state
|
|
179
|
-
this._profileCount.inc(0)
|
|
180
|
-
|
|
181
|
-
dc.unsubscribe('datadog:profiling:profile-submitted', this._onProfileSubmitted)
|
|
182
|
-
dc.unsubscribe('datadog:profiling:mock-profile-submitted', this._onMockProfileSubmitted)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
77
|
dc.unsubscribe('datadog:telemetry:app-closing', this._onAppClosing)
|
|
186
78
|
if (this.noSpan) {
|
|
187
79
|
dc.unsubscribe('dd-trace:span:start', this._onSpanCreated)
|
|
@@ -153,36 +153,22 @@ class Tracer extends NoopProxy {
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
if (config.profiling.enabled
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// Start a mock profiler that emits mock profile-submitted events for the telemetry.
|
|
165
|
-
// It will be stopped if the real profiler is started by the heuristics.
|
|
166
|
-
mockProfiler = require('./profiling/ssi-telemetry-mock-profiler')
|
|
167
|
-
mockProfiler.start(config)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (ssiHeuristics.heuristicsActive) {
|
|
156
|
+
if (config.profiling.enabled === 'true') {
|
|
157
|
+
this._profilerStarted = this._startProfiler(config)
|
|
158
|
+
} else {
|
|
159
|
+
this._profilerStarted = Promise.resolve(false)
|
|
160
|
+
if (config.profiling.enabled === 'auto') {
|
|
161
|
+
const { SSIHeuristics } = require('./profiling/ssi-heuristics')
|
|
162
|
+
const ssiHeuristics = new SSIHeuristics(config)
|
|
163
|
+
ssiHeuristics.start()
|
|
171
164
|
ssiHeuristics.onTriggered(() => {
|
|
172
|
-
if (mockProfiler) {
|
|
173
|
-
mockProfiler.stop()
|
|
174
|
-
}
|
|
175
165
|
this._startProfiler(config)
|
|
176
166
|
ssiHeuristics.onTriggered() // deregister this callback
|
|
177
167
|
})
|
|
178
168
|
}
|
|
179
|
-
|
|
180
|
-
if (!this._profilerStarted) {
|
|
181
|
-
this._profilerStarted = Promise.resolve(false)
|
|
182
|
-
}
|
|
183
169
|
}
|
|
184
170
|
|
|
185
|
-
if (config.runtimeMetrics) {
|
|
171
|
+
if (config.runtimeMetrics.enabled) {
|
|
186
172
|
runtimeMetrics.start(config)
|
|
187
173
|
}
|
|
188
174
|
|
|
@@ -205,8 +191,8 @@ class Tracer extends NoopProxy {
|
|
|
205
191
|
automaticLogPlugin.configure({ ...config, enabled: true })
|
|
206
192
|
} else {
|
|
207
193
|
log.warn(
|
|
208
|
-
|
|
209
|
-
'but DD_API_KEY is undefined, so no automatic log submission will be performed.'
|
|
194
|
+
// eslint-disable-next-line @stylistic/max-len
|
|
195
|
+
'DD_AGENTLESS_LOG_SUBMISSION_ENABLED is set, but DD_API_KEY is undefined, so no automatic log submission will be performed.'
|
|
210
196
|
)
|
|
211
197
|
}
|
|
212
198
|
}
|
|
@@ -229,8 +215,7 @@ class Tracer extends NoopProxy {
|
|
|
229
215
|
return require('./profiler').start(config)
|
|
230
216
|
} catch (e) {
|
|
231
217
|
log.error(
|
|
232
|
-
'Error starting profiler. For troubleshooting tips, see '
|
|
233
|
-
'<https://dtdg.co/nodejs-profiler-troubleshooting>',
|
|
218
|
+
'Error starting profiler. For troubleshooting tips, see <https://dtdg.co/nodejs-profiler-troubleshooting>',
|
|
234
219
|
e
|
|
235
220
|
)
|
|
236
221
|
}
|
|
@@ -6,7 +6,6 @@ const v8 = require('v8')
|
|
|
6
6
|
const os = require('os')
|
|
7
7
|
const { DogStatsDClient, MetricsAggregationClient } = require('../dogstatsd')
|
|
8
8
|
const log = require('../log')
|
|
9
|
-
const Histogram = require('../histogram')
|
|
10
9
|
const { performance, PerformanceObserver } = require('perf_hooks')
|
|
11
10
|
const { getEnvironmentVariable } = require('../config-helper')
|
|
12
11
|
|
|
@@ -17,11 +16,9 @@ const INTERVAL = Number.parseInt(DD_RUNTIME_METRICS_FLUSH_INTERVAL, 10)
|
|
|
17
16
|
// Node >=16 has PerformanceObserver with `gc` type, but <16.7 had a critical bug.
|
|
18
17
|
// See: https://github.com/nodejs/node/issues/39548
|
|
19
18
|
const hasGCObserver = NODE_MAJOR >= 18 || (NODE_MAJOR === 16 && NODE_MINOR >= 7)
|
|
20
|
-
const hasGCProfiler = NODE_MAJOR >= 20 || (NODE_MAJOR === 18 && NODE_MINOR >= 15)
|
|
21
19
|
|
|
22
20
|
let nativeMetrics = null
|
|
23
21
|
let gcObserver = null
|
|
24
|
-
let gcProfiler = null
|
|
25
22
|
|
|
26
23
|
let interval
|
|
27
24
|
let client
|
|
@@ -34,15 +31,23 @@ reset()
|
|
|
34
31
|
const runtimeMetrics = module.exports = {
|
|
35
32
|
start (config) {
|
|
36
33
|
const clientConfig = DogStatsDClient.generateClientConfig(config)
|
|
34
|
+
const watchers = []
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
nativeMetrics = require('@datadog/native-metrics')
|
|
40
|
-
|
|
36
|
+
if (config.runtimeMetrics.gc !== false) {
|
|
41
37
|
if (hasGCObserver) {
|
|
42
|
-
|
|
38
|
+
startGCObserver()
|
|
43
39
|
} else {
|
|
44
|
-
|
|
40
|
+
watchers.push('gc')
|
|
45
41
|
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.runtimeMetrics.eventLoop !== false) {
|
|
45
|
+
watchers.push('loop')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
nativeMetrics = require('@datadog/native-metrics')
|
|
50
|
+
nativeMetrics.start(...watchers)
|
|
46
51
|
} catch (e) {
|
|
47
52
|
log.error('Error starting native metrics', e)
|
|
48
53
|
nativeMetrics = null
|
|
@@ -52,9 +57,6 @@ const runtimeMetrics = module.exports = {
|
|
|
52
57
|
|
|
53
58
|
time = process.hrtime()
|
|
54
59
|
|
|
55
|
-
startGCObserver()
|
|
56
|
-
startGCProfiler()
|
|
57
|
-
|
|
58
60
|
if (nativeMetrics) {
|
|
59
61
|
interval = setInterval(() => {
|
|
60
62
|
captureCommonMetrics()
|
|
@@ -129,8 +131,6 @@ function reset () {
|
|
|
129
131
|
nativeMetrics = null
|
|
130
132
|
gcObserver && gcObserver.disconnect()
|
|
131
133
|
gcObserver = null
|
|
132
|
-
gcProfiler && gcProfiler.stop()
|
|
133
|
-
gcProfiler = null
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
function captureCpuUsage () {
|
|
@@ -195,29 +195,6 @@ function captureHeapSpace () {
|
|
|
195
195
|
client.gauge('runtime.node.heap.physical_size.by.space', stats[i].physical_space_size, tags)
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
function captureGCMetrics () {
|
|
199
|
-
if (!gcProfiler) return
|
|
200
|
-
|
|
201
|
-
const profile = gcProfiler.stop()
|
|
202
|
-
const pauseAll = new Histogram()
|
|
203
|
-
const pause = {}
|
|
204
|
-
|
|
205
|
-
for (const stat of profile.statistics) {
|
|
206
|
-
const type = stat.gcType.replaceAll(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
|
|
207
|
-
|
|
208
|
-
pause[type] = pause[type] || new Histogram()
|
|
209
|
-
pause[type].record(stat.cost)
|
|
210
|
-
pauseAll.record(stat.cost)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
histogram('runtime.node.gc.pause', pauseAll)
|
|
214
|
-
|
|
215
|
-
for (const type in pause) {
|
|
216
|
-
histogram('runtime.node.gc.pause.by.type', pause[type], `gc_type:${type}`)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
gcProfiler.start()
|
|
220
|
-
}
|
|
221
198
|
|
|
222
199
|
/**
|
|
223
200
|
* Gathers and reports Event Loop Utilization (ELU) since last run
|
|
@@ -242,7 +219,6 @@ function captureCommonMetrics () {
|
|
|
242
219
|
captureProcess()
|
|
243
220
|
captureHeapStats()
|
|
244
221
|
captureELU()
|
|
245
|
-
captureGCMetrics()
|
|
246
222
|
}
|
|
247
223
|
|
|
248
224
|
function captureNativeMetrics () {
|
|
@@ -293,7 +269,7 @@ function histogram (name, stats, tag) {
|
|
|
293
269
|
}
|
|
294
270
|
|
|
295
271
|
function startGCObserver () {
|
|
296
|
-
if (gcObserver
|
|
272
|
+
if (gcObserver) return
|
|
297
273
|
|
|
298
274
|
gcObserver = new PerformanceObserver(list => {
|
|
299
275
|
for (const entry of list.getEntries()) {
|
|
@@ -307,13 +283,6 @@ function startGCObserver () {
|
|
|
307
283
|
gcObserver.observe({ type: 'gc' })
|
|
308
284
|
}
|
|
309
285
|
|
|
310
|
-
function startGCProfiler () {
|
|
311
|
-
if (gcProfiler || !hasGCProfiler) return
|
|
312
|
-
|
|
313
|
-
gcProfiler = new v8.GCProfiler()
|
|
314
|
-
gcProfiler.start()
|
|
315
|
-
}
|
|
316
|
-
|
|
317
286
|
function gcType (kind) {
|
|
318
287
|
if (NODE_MAJOR >= 22) {
|
|
319
288
|
switch (kind) {
|
|
@@ -22,7 +22,7 @@ const messaging = {
|
|
|
22
22
|
opName: () => 'kafka.produce',
|
|
23
23
|
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
24
24
|
},
|
|
25
|
-
'
|
|
25
|
+
'confluentinc-kafka-javascript': {
|
|
26
26
|
opName: () => 'kafka.produce',
|
|
27
27
|
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
28
28
|
},
|
|
@@ -56,7 +56,7 @@ const messaging = {
|
|
|
56
56
|
opName: () => 'kafka.consume',
|
|
57
57
|
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
58
58
|
},
|
|
59
|
-
'
|
|
59
|
+
'confluentinc-kafka-javascript': {
|
|
60
60
|
opName: () => 'kafka.consume',
|
|
61
61
|
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
62
62
|
},
|
|
@@ -100,6 +100,10 @@ const storage = {
|
|
|
100
100
|
opName: () => 'pg.query',
|
|
101
101
|
serviceName: withSuffixFunction('postgres')
|
|
102
102
|
},
|
|
103
|
+
prisma: {
|
|
104
|
+
opName: ({ operation }) => `prisma.${operation}`,
|
|
105
|
+
serviceName: withSuffixFunction('prisma')
|
|
106
|
+
},
|
|
103
107
|
redis: redisConfig,
|
|
104
108
|
tedious: {
|
|
105
109
|
opName: () => 'tedious.request',
|
|
@@ -22,7 +22,7 @@ const messaging = {
|
|
|
22
22
|
opName: () => 'kafka.send',
|
|
23
23
|
serviceName: identityService
|
|
24
24
|
},
|
|
25
|
-
'
|
|
25
|
+
'confluentinc-kafka-javascript': {
|
|
26
26
|
opName: () => 'kafka.send',
|
|
27
27
|
serviceName: identityService
|
|
28
28
|
},
|
|
@@ -47,7 +47,7 @@ const messaging = {
|
|
|
47
47
|
opName: () => 'kafka.process',
|
|
48
48
|
serviceName: identityService
|
|
49
49
|
},
|
|
50
|
-
'
|
|
50
|
+
'confluentinc-kafka-javascript': {
|
|
51
51
|
opName: () => 'kafka.process',
|
|
52
52
|
serviceName: identityService
|
|
53
53
|
},
|
|
@@ -68,6 +68,10 @@ const storage = {
|
|
|
68
68
|
opName: () => 'postgresql.query',
|
|
69
69
|
serviceName: withFunction
|
|
70
70
|
},
|
|
71
|
+
prisma: {
|
|
72
|
+
opName: ({ operation }) => `prisma.${operation}`,
|
|
73
|
+
serviceName: configWithFallback
|
|
74
|
+
},
|
|
71
75
|
redis: redisNaming,
|
|
72
76
|
tedious: {
|
|
73
77
|
opName: () => 'mssql.query',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"supportedConfigurations": {
|
|
3
3
|
"DD_AAS_DOTNET_EXTENSION_VERSION": ["A"],
|
|
4
|
+
"DD_ACTION_EXECUTION_ID": ["A"],
|
|
4
5
|
"DD_AGENT_HOST": ["A"],
|
|
5
6
|
"DD_AGENTLESS_LOG_SUBMISSION_ENABLED": ["A"],
|
|
6
7
|
"DD_AGENTLESS_LOG_SUBMISSION_URL": ["A"],
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"DD_CODE_ORIGIN_FOR_SPANS_ENABLED": ["A"],
|
|
50
51
|
"DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED": ["A"],
|
|
51
52
|
"DD_CRASHTRACKING_ENABLED": ["A"],
|
|
53
|
+
"DD_CUSTOM_TRACE_ID": ["A"],
|
|
52
54
|
"DD_DATA_STREAMS_ENABLED": ["A"],
|
|
53
55
|
"DD_DBM_PROPAGATION_MODE": ["A"],
|
|
54
56
|
"DD_DOGSTATSD_HOST": ["A"],
|
|
@@ -72,6 +74,8 @@
|
|
|
72
74
|
"DD_GIT_PROPERTIES_FILE": ["A"],
|
|
73
75
|
"DD_GIT_REPOSITORY_URL": ["A"],
|
|
74
76
|
"DD_GIT_TAG": ["A"],
|
|
77
|
+
"DD_GIT_PULL_REQUEST_BASE_BRANCH": ["A"],
|
|
78
|
+
"DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA": ["A"],
|
|
75
79
|
"DD_GRPC_CLIENT_ERROR_STATUSES": ["A"],
|
|
76
80
|
"DD_GRPC_SERVER_ERROR_STATUSES": ["A"],
|
|
77
81
|
"DD_IAST_DB_ROWS_TO_TAINT": ["A"],
|
|
@@ -106,6 +110,7 @@
|
|
|
106
110
|
"DD_MINI_AGENT_PATH": ["A"],
|
|
107
111
|
"DD_OPENAI_LOGS_ENABLED": ["A"],
|
|
108
112
|
"DD_OPENAI_SPAN_CHAR_LIMIT": ["A"],
|
|
113
|
+
"DD_PIPELINE_EXECUTION_ID": ["A"],
|
|
109
114
|
"DD_PLAYWRIGHT_WORKER": ["A"],
|
|
110
115
|
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["A"],
|
|
111
116
|
"DD_PROFILING_CPU_ENABLED": ["A"],
|
|
@@ -126,7 +131,10 @@
|
|
|
126
131
|
"DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": ["A"],
|
|
127
132
|
"DD_REMOTE_CONFIGURATION_ENABLED": ["A"],
|
|
128
133
|
"DD_RUNTIME_METRICS_ENABLED": ["A"],
|
|
134
|
+
"DD_RUNTIME_METRICS_EVENT_LOOP_ENABLED": ["A"],
|
|
135
|
+
"DD_RUNTIME_METRICS_GC_ENABLED": ["A"],
|
|
129
136
|
"DD_RUNTIME_METRICS_FLUSH_INTERVAL": ["A"],
|
|
137
|
+
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["A"],
|
|
130
138
|
"DD_SERVICE_MAPPING": ["A"],
|
|
131
139
|
"DD_SERVICE": ["A"],
|
|
132
140
|
"DD_SITE": ["A"],
|
|
@@ -145,7 +153,6 @@
|
|
|
145
153
|
"DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES": ["A"],
|
|
146
154
|
"DD_TEST_MANAGEMENT_ENABLED": ["A"],
|
|
147
155
|
"DD_TEST_SESSION_NAME": ["A"],
|
|
148
|
-
"DD_TRACE__CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED": ["A"],
|
|
149
156
|
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
|
|
150
157
|
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
|
|
151
158
|
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
|
|
@@ -238,7 +245,6 @@
|
|
|
238
245
|
"DD_TRACE_EXPERIMENTAL_B3_ENABLED": ["A"],
|
|
239
246
|
"DD_TRACE_EXPERIMENTAL_EXPORTER": ["A"],
|
|
240
247
|
"DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED": ["A"],
|
|
241
|
-
"DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": ["A"],
|
|
242
248
|
"DD_TRACE_EXPERIMENTAL_SPAN_COUNTS": ["A"],
|
|
243
249
|
"DD_TRACE_EXPERIMENTAL_STATE_TRACKING": ["A"],
|
|
244
250
|
"DD_TRACE_EXPRESS_ENABLED": ["A"],
|
|
@@ -351,6 +357,7 @@
|
|
|
351
357
|
"DD_TRACE_PLAYWRIGHT_CORE_ENABLED": ["A"],
|
|
352
358
|
"DD_TRACE_PLAYWRIGHT_ENABLED": ["A"],
|
|
353
359
|
"DD_TRACE_PLAYWRIGHT_TEST_ENABLED": ["A"],
|
|
360
|
+
"DD_TRACE_PRISMA_ENABLED": ["A"],
|
|
354
361
|
"DD_TRACE_PROCESS_ENABLED": ["A"],
|
|
355
362
|
"DD_TRACE_PROMISE_ENABLED": ["A"],
|
|
356
363
|
"DD_TRACE_PROMISE_JS_ENABLED": ["A"],
|
|
@@ -427,6 +434,7 @@
|
|
|
427
434
|
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED"],
|
|
428
435
|
"DD_PROFILING_TIMELINE_ENABLED": ["DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED"],
|
|
429
436
|
"DD_REMOTE_CONFIGURATION_ENABLED": ["DD_REMOTE_CONFIG_ENABLED" ],
|
|
437
|
+
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED"],
|
|
430
438
|
"DD_SERVICE": ["DD_SERVICE_NAME"],
|
|
431
439
|
"DD_TRACE_AGENT_URL": ["DD_TRACE_URL"]
|
|
432
440
|
},
|
|
@@ -435,6 +443,7 @@
|
|
|
435
443
|
"DD_PROFILING_EXPERIMENTAL_CPU_ENABLED": "DD_PROFILING_CPU_ENABLED",
|
|
436
444
|
"DD_EXPERIMENTAL_PROFILING_ENABLED": "DD_PROFILING_ENABLED",
|
|
437
445
|
"DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED": "DD_PROFILING_CODEHOTSPOTS_ENABLED",
|
|
438
|
-
"DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED"
|
|
446
|
+
"DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED",
|
|
447
|
+
"DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED"
|
|
439
448
|
}
|
|
440
449
|
}
|
|
@@ -321,7 +321,11 @@ const nameMapping = {
|
|
|
321
321
|
clientIpHeader: 'DD_TRACE_CLIENT_IP_HEADER',
|
|
322
322
|
'grpc.client.error.statuses': 'DD_GRPC_CLIENT_ERROR_STATUSES',
|
|
323
323
|
'grpc.server.error.statuses': 'DD_GRPC_SERVER_ERROR_STATUSES',
|
|
324
|
-
traceId128BitLoggingEnabled: 'DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED'
|
|
324
|
+
traceId128BitLoggingEnabled: 'DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED',
|
|
325
|
+
instrumentationSource: 'instrumentation_source',
|
|
326
|
+
injectionEnabled: 'ssi_injection_enabled',
|
|
327
|
+
injectForce: 'ssi_forced_injection_enabled',
|
|
328
|
+
'runtimeMetrics.enabled': 'runtimeMetrics'
|
|
325
329
|
}
|
|
326
330
|
|
|
327
331
|
const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping', 'serviceMapping'])
|
|
@@ -24,6 +24,17 @@ class DatadogTracer extends Tracer {
|
|
|
24
24
|
this._scope = new Scope()
|
|
25
25
|
setStartupLogConfig(config)
|
|
26
26
|
flushStartupLogs(log)
|
|
27
|
+
|
|
28
|
+
if (!config._isInServerlessEnvironment()) {
|
|
29
|
+
const storeConfig = require('./tracer_metadata')
|
|
30
|
+
// Keep a reference to the handle, to keep the memfd alive in memory.
|
|
31
|
+
// It is read by the service discovery feature.
|
|
32
|
+
const metadata = storeConfig(config)
|
|
33
|
+
if (metadata === undefined) {
|
|
34
|
+
log.warn('Could not store tracer configuration for service discovery')
|
|
35
|
+
}
|
|
36
|
+
this._inmem_cfg = metadata
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
39
|
|
|
29
40
|
configure (config) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Load binding first to not import other modules if it throws
|
|
4
|
+
const libdatadog = require('@datadog/libdatadog')
|
|
5
|
+
const tracerVersion = require('../../../version').VERSION
|
|
6
|
+
|
|
7
|
+
function storeConfig (config) {
|
|
8
|
+
const processDiscovery = libdatadog.maybeLoad('process-discovery')
|
|
9
|
+
if (processDiscovery === undefined) {
|
|
10
|
+
return
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const metadata = new processDiscovery.TracerMetadata(
|
|
14
|
+
config.tags['runtime-id'],
|
|
15
|
+
tracerVersion,
|
|
16
|
+
config.hostname,
|
|
17
|
+
config.server || null,
|
|
18
|
+
config.env || null,
|
|
19
|
+
config.version || null
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return processDiscovery.storeMetadata(metadata)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = storeConfig
|
|
@@ -61,12 +61,10 @@ function globMatch (pattern, subject) {
|
|
|
61
61
|
return true
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// TODO: this adds stack traces relative to packages/
|
|
65
|
-
// shouldn't paths be relative to the root of dd-trace?
|
|
66
64
|
function calculateDDBasePath (dirname) {
|
|
67
65
|
const dirSteps = dirname.split(path.sep)
|
|
68
66
|
const packagesIndex = dirSteps.lastIndexOf('packages')
|
|
69
|
-
return dirSteps.slice(0, packagesIndex
|
|
67
|
+
return dirSteps.slice(0, packagesIndex).join(path.sep) + path.sep
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
function normalizeProfilingEnabledValue (configValue) {
|
|
@@ -77,11 +75,20 @@ function normalizeProfilingEnabledValue (configValue) {
|
|
|
77
75
|
: configValue === 'auto' ? 'auto' : undefined
|
|
78
76
|
}
|
|
79
77
|
|
|
78
|
+
function normalizePluginEnvName (envPluginName, makeLowercase = false) {
|
|
79
|
+
if (envPluginName.startsWith('@')) {
|
|
80
|
+
envPluginName = envPluginName.slice(1)
|
|
81
|
+
}
|
|
82
|
+
envPluginName = envPluginName.replaceAll(/[^a-z0-9_]/ig, '_')
|
|
83
|
+
return makeLowercase ? envPluginName.toLowerCase() : envPluginName
|
|
84
|
+
}
|
|
85
|
+
|
|
80
86
|
module.exports = {
|
|
81
87
|
isTrue,
|
|
82
88
|
isFalse,
|
|
83
89
|
isError,
|
|
84
90
|
globMatch,
|
|
85
91
|
ddBasePath: calculateDDBasePath(__dirname),
|
|
86
|
-
normalizeProfilingEnabledValue
|
|
92
|
+
normalizeProfilingEnabledValue,
|
|
93
|
+
normalizePluginEnvName
|
|
87
94
|
}
|
package/version.js
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
/* eslint-disable no-var */
|
|
4
4
|
/* eslint-disable unicorn/prefer-number-properties */
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var version = require('./package.json').version
|
|
7
|
+
var ddMatches = version.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
7
8
|
var nodeMatches = process.versions.node.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
8
9
|
|
|
9
10
|
module.exports = {
|
|
11
|
+
VERSION: version,
|
|
10
12
|
DD_MAJOR: parseInt(ddMatches[1]),
|
|
11
13
|
DD_MINOR: parseInt(ddMatches[2]),
|
|
12
14
|
DD_PATCH: parseInt(ddMatches[3]),
|