dd-trace 5.109.0 → 5.111.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/README.md +13 -8
- package/ci/init.js +25 -5
- package/ci/vitest-no-worker-init-setup.mjs +430 -0
- package/ext/tags.js +2 -0
- package/index.d.ts +79 -24
- package/initialize.mjs +5 -6
- package/loader-hook.mjs +154 -47
- package/package.json +20 -16
- package/packages/datadog-esbuild/index.js +26 -0
- package/packages/datadog-esbuild/src/utils.js +46 -3
- package/packages/datadog-instrumentations/src/connect.js +4 -3
- package/packages/datadog-instrumentations/src/fastify.js +4 -12
- package/packages/datadog-instrumentations/src/fs.js +8 -6
- package/packages/datadog-instrumentations/src/graphql.js +26 -484
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +81 -8
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -2
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +65 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +6 -4
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +17 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +201 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +18 -2
- package/packages/datadog-instrumentations/src/koa.js +3 -2
- package/packages/datadog-instrumentations/src/mariadb.js +4 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +14 -2
- package/packages/datadog-instrumentations/src/next.js +10 -10
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +7 -6
- package/packages/datadog-instrumentations/src/playwright.js +1 -1
- package/packages/datadog-instrumentations/src/restify.js +4 -3
- package/packages/datadog-instrumentations/src/router.js +18 -5
- package/packages/datadog-instrumentations/src/selenium.js +1 -2
- package/packages/datadog-instrumentations/src/tedious.js +28 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +1293 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +1567 -0
- package/packages/datadog-instrumentations/src/vitest-util.js +249 -0
- package/packages/datadog-instrumentations/src/vitest-worker.js +753 -0
- package/packages/datadog-instrumentations/src/vitest.js +11 -1598
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/client.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +18 -10
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +47 -11
- package/packages/datadog-plugin-aws-sdk/src/base.js +13 -9
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +43 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +83 -91
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -5
- package/packages/datadog-plugin-cypress/src/support.js +45 -1
- package/packages/datadog-plugin-express/src/code_origin.js +1 -1
- package/packages/datadog-plugin-fastify/src/code_origin.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +627 -11
- package/packages/datadog-plugin-graphql/src/index.js +20 -8
- package/packages/datadog-plugin-graphql/src/parse.js +24 -4
- package/packages/datadog-plugin-graphql/src/validate.js +16 -5
- package/packages/datadog-plugin-http/src/client.js +8 -3
- package/packages/datadog-plugin-http/src/index.js +6 -8
- package/packages/datadog-plugin-http2/src/client.js +5 -2
- package/packages/datadog-plugin-jest/src/index.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-mysql/src/index.js +7 -2
- package/packages/datadog-plugin-openai/src/services.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +2 -2
- package/packages/datadog-plugin-undici/src/index.js +5 -2
- package/packages/datadog-plugin-vitest/src/index.js +76 -64
- package/packages/datadog-shimmer/src/shimmer.js +37 -16
- package/packages/datadog-webpack/index.js +17 -1
- package/packages/datadog-webpack/src/optional-peer-loader.js +17 -0
- package/packages/dd-trace/src/aiguard/sdk.js +15 -3
- package/packages/dd-trace/src/appsec/api_security/index.js +55 -0
- package/packages/dd-trace/src/appsec/api_security/sampler.js +147 -0
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- package/packages/dd-trace/src/appsec/downstream_requests.js +4 -4
- package/packages/dd-trace/src/appsec/graphql.js +5 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +26 -19
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/index.js +2 -1
- package/packages/dd-trace/src/appsec/index.js +20 -7
- package/packages/dd-trace/src/appsec/lambda.js +135 -0
- package/packages/dd-trace/src/appsec/reporter.js +50 -10
- package/packages/dd-trace/src/appsec/telemetry/api_security.js +34 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +27 -1
- package/packages/dd-trace/src/appsec/waf/index.js +16 -4
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +4 -4
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +21 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +2 -2
- 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/index.js +3 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +17 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +47 -26
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +64 -53
- package/packages/dd-trace/src/ci-visibility/requests/request.js +1 -17
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +3 -3
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +23 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +128 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +287 -0
- package/packages/dd-trace/src/config/defaults.js +25 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +596 -58
- package/packages/dd-trace/src/config/helper.js +134 -33
- package/packages/dd-trace/src/config/index.js +39 -23
- package/packages/dd-trace/src/config/major-overrides.js +4 -2
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +109 -57
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/processor.js +11 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +47 -35
- package/packages/dd-trace/src/debugger/devtools_client/index.js +31 -66
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +83 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -0
- package/packages/dd-trace/src/debugger/index.js +5 -0
- package/packages/dd-trace/src/debugger/probe_sampler.js +112 -0
- package/packages/dd-trace/src/debugger/probe_sampler_constants.js +19 -0
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +77 -26
- package/packages/dd-trace/src/exporters/agent/index.js +1 -1
- package/packages/dd-trace/src/exporters/agentless/writer.js +4 -4
- package/packages/dd-trace/src/exporters/common/request.js +1 -20
- package/packages/dd-trace/src/exporters/common/url.js +34 -0
- package/packages/dd-trace/src/exporters/span-stats/writer.js +1 -3
- package/packages/dd-trace/src/guardrails/index.js +8 -5
- package/packages/dd-trace/src/index.js +6 -4
- package/packages/dd-trace/src/llmobs/constants/tags.js +6 -0
- package/packages/dd-trace/src/llmobs/index.js +17 -6
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -4
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +3 -3
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +8 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +5 -1
- package/packages/dd-trace/src/llmobs/tagger.js +58 -3
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
- package/packages/dd-trace/src/log/index.js +18 -20
- package/packages/dd-trace/src/openfeature/flagging_provider.js +2 -7
- package/packages/dd-trace/src/opentelemetry/bridge-span-base.js +5 -4
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +54 -5
- package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +2 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +40 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +169 -0
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +4 -3
- package/packages/dd-trace/src/opentelemetry/metrics/time.js +19 -0
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +2 -2
- package/packages/dd-trace/src/opentelemetry/otlp/logs.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/logs_service.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/metrics.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/metrics_service.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +44 -38
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +29 -13
- package/packages/dd-trace/src/opentelemetry/span.js +14 -3
- package/packages/dd-trace/src/opentelemetry/span_context.js +1 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +26 -13
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +3 -3
- package/packages/dd-trace/src/opentracing/span_context.js +17 -0
- package/packages/dd-trace/src/opentracing/tracer.js +6 -1
- package/packages/dd-trace/src/plugin_manager.js +14 -8
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +276 -0
- package/packages/dd-trace/src/plugins/util/llm.js +6 -1
- package/packages/dd-trace/src/plugins/util/test.js +91 -9
- package/packages/dd-trace/src/plugins/util/url.js +68 -1
- package/packages/dd-trace/src/plugins/util/web.js +19 -36
- package/packages/dd-trace/src/priority_sampler.js +1 -13
- package/packages/dd-trace/src/profiling/config.js +129 -198
- package/packages/dd-trace/src/profiling/constants.js +4 -7
- package/packages/dd-trace/src/profiling/exporter_cli.js +10 -10
- package/packages/dd-trace/src/profiling/exporters/agent.js +23 -16
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +45 -14
- package/packages/dd-trace/src/profiling/exporters/file.js +16 -5
- package/packages/dd-trace/src/profiling/oom.js +71 -0
- package/packages/dd-trace/src/profiling/profiler.js +35 -23
- package/packages/dd-trace/src/profiling/profilers/events.js +14 -7
- package/packages/dd-trace/src/profiling/profilers/space.js +27 -18
- package/packages/dd-trace/src/profiling/profilers/wall.js +35 -25
- package/packages/dd-trace/src/proxy.js +8 -8
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +1 -2
- package/packages/dd-trace/src/service-naming/schemas/util.js +36 -5
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +5 -3
- package/packages/dd-trace/src/span_format.js +2 -1
- package/packages/dd-trace/src/span_processor.js +11 -6
- package/packages/dd-trace/src/span_stats.js +96 -78
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +6 -4
- package/packages/dd-trace/src/telemetry/index.js +2 -2
- package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/telemetry/send-data.js +20 -18
- package/packages/dd-trace/src/telemetry/session-propagation.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +9 -9
- package/packages/dd-trace/src/tracer.js +15 -1
- package/packages/dd-trace/src/util.js +14 -0
- package/register.js +58 -1
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +0 -170
- package/packages/dd-trace/src/appsec/api_security_sampler.js +0 -117
|
@@ -5,6 +5,7 @@ const { getGeneratedPosition } = require('./source-maps')
|
|
|
5
5
|
const session = require('./session')
|
|
6
6
|
const { compile, compileSegments, templateRequiresEvaluation } = require('./condition')
|
|
7
7
|
const { MAX_SNAPSHOTS_PER_SECOND_PER_PROBE, MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE } = require('./defaults')
|
|
8
|
+
const { compileBreakpointCondition, getRemoveProbeExpression } = require('./probe_sampler')
|
|
8
9
|
const {
|
|
9
10
|
DEFAULT_MAX_REFERENCE_DEPTH,
|
|
10
11
|
DEFAULT_MAX_COLLECTION_SIZE,
|
|
@@ -17,6 +18,7 @@ const {
|
|
|
17
18
|
locationToBreakpoint,
|
|
18
19
|
breakpointToProbes,
|
|
19
20
|
probeToLocation,
|
|
21
|
+
samplingIndexToProbe,
|
|
20
22
|
} = require('./state')
|
|
21
23
|
const log = require('./log')
|
|
22
24
|
|
|
@@ -26,6 +28,7 @@ const log = require('./log')
|
|
|
26
28
|
|
|
27
29
|
let sessionStarted = false
|
|
28
30
|
const probes = new Map()
|
|
31
|
+
let nextSamplingIndex = 0
|
|
29
32
|
let scriptLoadingStabilizedResolve
|
|
30
33
|
const scriptLoadingStabilized = new Promise((resolve) => { scriptLoadingStabilizedResolve = resolve })
|
|
31
34
|
|
|
@@ -55,6 +58,8 @@ async function addBreakpoint (probe) {
|
|
|
55
58
|
if (!sessionStarted) await start()
|
|
56
59
|
|
|
57
60
|
probes.set(probe.id, probe)
|
|
61
|
+
probe.samplingIndex = nextSamplingIndex++
|
|
62
|
+
samplingIndexToProbe.set(probe.samplingIndex, probe)
|
|
58
63
|
|
|
59
64
|
const file = probe.where.sourceFile
|
|
60
65
|
let lineNumber = Number(probe.where.lines[0]) // Tracer doesn't support multiple-line breakpoints
|
|
@@ -75,8 +80,6 @@ async function addBreakpoint (probe) {
|
|
|
75
80
|
? MAX_SNAPSHOTS_PER_SECOND_PER_PROBE
|
|
76
81
|
: MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE)
|
|
77
82
|
probe.nsBetweenSampling = BigInt(Math.trunc(1 / snapshotsPerSecond * 1e9))
|
|
78
|
-
// Initialize to a large negative value to ensure first probe hit is always captured
|
|
79
|
-
probe.lastCaptureNs = BigInt(Number.MIN_SAFE_INTEGER)
|
|
80
83
|
|
|
81
84
|
// Warning: The code below relies on undocumented behavior of the inspector!
|
|
82
85
|
// It expects that `await session.post('Debugger.enable')` will wait for all loaded scripts to be emitted as
|
|
@@ -174,7 +177,7 @@ async function addBreakpoint (probe) {
|
|
|
174
177
|
try {
|
|
175
178
|
result = /** @type {SetBreakpointResponse} */ (await session.post('Debugger.setBreakpoint', {
|
|
176
179
|
location,
|
|
177
|
-
condition: probe
|
|
180
|
+
condition: compileBreakpointCondition([probe]),
|
|
178
181
|
}))
|
|
179
182
|
} catch (err) {
|
|
180
183
|
throw new Error(`Error setting breakpoint for probe ${probe.id} (version: ${probe.version})`, { cause: err })
|
|
@@ -195,11 +198,14 @@ async function removeBreakpoint ({ id }) {
|
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
probes.delete(id)
|
|
201
|
+
await removeProbeFromSampler(id)
|
|
198
202
|
|
|
199
203
|
const locationKey = probeToLocation.get(id)
|
|
200
204
|
const breakpoint = locationToBreakpoint.get(locationKey)
|
|
201
205
|
const probesAtLocation = breakpointToProbes.get(breakpoint.id)
|
|
206
|
+
const probe = probesAtLocation.get(id)
|
|
202
207
|
|
|
208
|
+
samplingIndexToProbe.delete(probe.samplingIndex)
|
|
203
209
|
probesAtLocation.delete(id)
|
|
204
210
|
probeToLocation.delete(id)
|
|
205
211
|
|
|
@@ -229,35 +235,37 @@ async function modifyBreakpoint (probe) {
|
|
|
229
235
|
|
|
230
236
|
async function updateBreakpointInternal (breakpoint, probe) {
|
|
231
237
|
const probesAtLocation = breakpointToProbes.get(breakpoint.id)
|
|
232
|
-
const conditionBeforeNewProbe = compileCompoundCondition([...probesAtLocation.values()])
|
|
233
238
|
|
|
234
|
-
// If a probe is provided, add it to the breakpoint. If not, it's because we're removing a probe
|
|
235
|
-
//
|
|
239
|
+
// If a probe is provided, add it to the breakpoint. If not, it's because we're removing a probe. In both cases the
|
|
240
|
+
// breakpoint condition must be rebuilt to match the remaining probes at the location.
|
|
236
241
|
if (probe) {
|
|
237
242
|
probesAtLocation.set(probe.id, probe)
|
|
238
243
|
probeToLocation.set(probe.id, breakpoint.locationKey)
|
|
239
244
|
}
|
|
240
245
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
246
|
+
try {
|
|
247
|
+
await session.post('Debugger.removeBreakpoint', { breakpointId: breakpoint.id })
|
|
248
|
+
} catch (err) {
|
|
249
|
+
const message = probe
|
|
250
|
+
? `Error replacing breakpoint while adding probe ${probe.id} (version: ${probe.version})`
|
|
251
|
+
: `Error replacing breakpoint after removing probe from ${breakpoint.locationKey}`
|
|
252
|
+
throw new Error(message, { cause: err })
|
|
253
|
+
}
|
|
254
|
+
breakpointToProbes.delete(breakpoint.id)
|
|
255
|
+
let result
|
|
256
|
+
try {
|
|
257
|
+
result = /** @type {SetBreakpointResponse} */ (await session.post('Debugger.setBreakpoint', {
|
|
258
|
+
location: breakpoint.location,
|
|
259
|
+
condition: compileBreakpointCondition([...probesAtLocation.values()]),
|
|
260
|
+
}))
|
|
261
|
+
} catch (err) {
|
|
262
|
+
const message = probe
|
|
263
|
+
? `Error setting breakpoint while adding probe ${probe.id} (version: ${probe.version})`
|
|
264
|
+
: `Error setting breakpoint after removing probe from ${breakpoint.locationKey}`
|
|
265
|
+
throw new Error(message, { cause: err })
|
|
260
266
|
}
|
|
267
|
+
breakpoint.id = result.breakpointId
|
|
268
|
+
breakpointToProbes.set(result.breakpointId, probesAtLocation)
|
|
261
269
|
}
|
|
262
270
|
|
|
263
271
|
async function reEvaluateProbe (probe) {
|
|
@@ -305,16 +313,20 @@ function lock (fn) {
|
|
|
305
313
|
}
|
|
306
314
|
}
|
|
307
315
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
/**
|
|
317
|
+
* Remove cached sampling state for a probe from the runtime sampler.
|
|
318
|
+
*
|
|
319
|
+
* @param {string} id - The probe id.
|
|
320
|
+
* @returns {Promise<void>}
|
|
321
|
+
*/
|
|
322
|
+
async function removeProbeFromSampler (id) {
|
|
323
|
+
try {
|
|
324
|
+
await session.post('Runtime.evaluate', {
|
|
325
|
+
expression: getRemoveProbeExpression(id),
|
|
326
|
+
})
|
|
327
|
+
} catch (err) {
|
|
328
|
+
log.error('[debugger:devtools_client] Error removing probe %s from sampler', id, err)
|
|
329
|
+
}
|
|
318
330
|
}
|
|
319
331
|
|
|
320
332
|
function generateLocationKey (scriptId, lineNumber, columnNumber) {
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { randomUUID } = require('crypto')
|
|
4
|
+
const { workerData: { probeSamplerBuffer } } = require('worker_threads')
|
|
4
5
|
const { version } = require('../../../../../package.json')
|
|
5
|
-
const { NODE_MAJOR } = require('../../../../../version')
|
|
6
6
|
const processTags = require('../../process-tags')
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
MAX_SAMPLED_PROBES_PER_PAUSE,
|
|
9
|
+
SAMPLED_PROBE_COUNT_INDEX,
|
|
10
|
+
SAMPLED_PROBE_INDEXES_START,
|
|
11
|
+
SAMPLED_PROBE_OVERFLOW_INDEX,
|
|
12
|
+
} = require('../probe_sampler_constants')
|
|
13
|
+
const { breakpointToProbes, samplingIndexToProbe } = require('./state')
|
|
8
14
|
const session = require('./session')
|
|
9
15
|
const { getLocalStateForCallFrame, evaluateCaptureExpressions } = require('./snapshot')
|
|
10
16
|
const send = require('./send')
|
|
11
17
|
const { getStackFromCallFrames } = require('./state')
|
|
12
18
|
const { ackEmitting } = require('./status')
|
|
13
19
|
const config = require('./config')
|
|
14
|
-
const { MAX_SNAPSHOTS_PER_SECOND_GLOBALLY } = require('./defaults')
|
|
15
20
|
const log = require('./log')
|
|
16
21
|
|
|
17
22
|
require('./remote_config')
|
|
@@ -38,25 +43,7 @@ const getDDTagsExpression = `(() => {
|
|
|
38
43
|
// something that should be useful to a Node.js developer.
|
|
39
44
|
const threadId = config.parentThreadId === 0 ? `pid:${process.pid}` : `pid:${process.pid};tid:${config.parentThreadId}`
|
|
40
45
|
const threadName = config.parentThreadId === 0 ? 'MainThread' : `WorkerThread:${config.parentThreadId}`
|
|
41
|
-
|
|
42
|
-
const SUPPORT_ARRAY_BUFFER_RESIZE = NODE_MAJOR >= 20
|
|
43
|
-
const oneSecondNs = 1_000_000_000n
|
|
44
|
-
let globalSnapshotSamplingRateWindowStart = 0n
|
|
45
|
-
let snapshotsSampledWithinTheLastSecond = 0
|
|
46
|
-
|
|
47
|
-
// TODO: Change to const once we drop support for Node.js 18
|
|
48
|
-
let snapshotProbeIndexBuffer, snapshotProbeIndex
|
|
49
|
-
|
|
50
|
-
if (SUPPORT_ARRAY_BUFFER_RESIZE) {
|
|
51
|
-
// TODO: Is a limit of 256 snapshots ever going to be a problem?
|
|
52
|
-
// @ts-ignore - ArrayBuffer constructor with maxByteLength is available in Node.js 20+ but not in @types/node@18
|
|
53
|
-
// eslint-disable-next-line n/no-unsupported-features/es-syntax
|
|
54
|
-
snapshotProbeIndexBuffer = new ArrayBuffer(1, { maxByteLength: 256 })
|
|
55
|
-
// TODO: Is a limit of 256 probes ever going to be a problem?
|
|
56
|
-
snapshotProbeIndex = new Uint8Array(snapshotProbeIndexBuffer)
|
|
57
|
-
} else {
|
|
58
|
-
snapshotProbeIndex = new Uint8Array(1)
|
|
59
|
-
}
|
|
46
|
+
const sampledProbeIndexes = new Int32Array(probeSamplerBuffer)
|
|
60
47
|
|
|
61
48
|
// WARNING: The code above the line `await session.post('Debugger.resume')` is highly optimized. Please edit with care!
|
|
62
49
|
session.on('Debugger.paused', async ({ params }) => {
|
|
@@ -71,7 +58,6 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
71
58
|
let maxCollectionSize = 0
|
|
72
59
|
let maxFieldCount = 0
|
|
73
60
|
let maxLength = 0
|
|
74
|
-
let sampled = false
|
|
75
61
|
let numberOfProbesWithSnapshots = 0
|
|
76
62
|
let probesWithCaptureExpressions = false
|
|
77
63
|
const probes = []
|
|
@@ -80,7 +66,15 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
80
66
|
// V8 doesn't allow setting more than one breakpoint at a specific location, however, it's possible to set two
|
|
81
67
|
// breakpoints just next to each other that will "snap" to the same logical location, which in turn will be hit at the
|
|
82
68
|
// same time. E.g. index.js:1:1 and index.js:1:2.
|
|
83
|
-
|
|
69
|
+
const numberOfSampledProbeIndexes = Math.min(
|
|
70
|
+
Atomics.exchange(sampledProbeIndexes, SAMPLED_PROBE_COUNT_INDEX, 0),
|
|
71
|
+
MAX_SAMPLED_PROBES_PER_PAUSE
|
|
72
|
+
)
|
|
73
|
+
if (Atomics.exchange(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 0) === 1) {
|
|
74
|
+
log.error(
|
|
75
|
+
'[debugger:devtools_client] Too many probes sampled at the same breakpoint location; skipping excess probes'
|
|
76
|
+
)
|
|
77
|
+
}
|
|
84
78
|
|
|
85
79
|
// TODO: Investigate if it will improve performance to create a fast-path for when there's only a single breakpoint
|
|
86
80
|
for (let i = 0; i < params.hitBreakpoints.length; i++) {
|
|
@@ -92,36 +86,23 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
92
86
|
continue
|
|
93
87
|
}
|
|
94
88
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (SUPPORT_ARRAY_BUFFER_RESIZE) {
|
|
99
|
-
snapshotProbeIndexBuffer.resize(numberOfProbesOnBreakpoint)
|
|
100
|
-
} else {
|
|
101
|
-
snapshotProbeIndex = new Uint8Array(numberOfProbesOnBreakpoint)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
89
|
+
for (let j = 0; j < numberOfSampledProbeIndexes; j++) {
|
|
90
|
+
const samplingIndex = Atomics.load(sampledProbeIndexes, SAMPLED_PROBE_INDEXES_START + j)
|
|
91
|
+
const probe = samplingIndexToProbe.get(samplingIndex)
|
|
105
92
|
|
|
106
|
-
|
|
107
|
-
|
|
93
|
+
if (probe === undefined) {
|
|
94
|
+
log.error('[debugger:devtools_client] No probe found for sampled probe index %d', samplingIndex)
|
|
95
|
+
continue
|
|
96
|
+
}
|
|
97
|
+
if (!probesAtLocation.has(probe.id)) {
|
|
98
|
+
log.error('[debugger:devtools_client] Sampled probe %s was not found at breakpoint %s',
|
|
99
|
+
probe.id, params.hitBreakpoints[i])
|
|
108
100
|
continue
|
|
109
101
|
}
|
|
110
102
|
|
|
111
103
|
if (probe.captureSnapshot === true || probe.compiledCaptureExpressions !== undefined) {
|
|
112
|
-
// This algorithm to calculate number of sampled snapshots within the last second is not perfect, as it's not a
|
|
113
|
-
// sliding window. But it's quick and easy :)
|
|
114
|
-
if (i === 0 && start - globalSnapshotSamplingRateWindowStart > oneSecondNs) {
|
|
115
|
-
snapshotsSampledWithinTheLastSecond = 1
|
|
116
|
-
globalSnapshotSamplingRateWindowStart = start
|
|
117
|
-
} else if (snapshotsSampledWithinTheLastSecond >= MAX_SNAPSHOTS_PER_SECOND_GLOBALLY) {
|
|
118
|
-
continue
|
|
119
|
-
} else {
|
|
120
|
-
snapshotsSampledWithinTheLastSecond++
|
|
121
|
-
}
|
|
122
|
-
|
|
123
104
|
if (probe.captureSnapshot === true) {
|
|
124
|
-
|
|
105
|
+
numberOfProbesWithSnapshots++
|
|
125
106
|
maxReferenceDepth = Math.max(probe.capture.maxReferenceDepth, maxReferenceDepth)
|
|
126
107
|
maxCollectionSize = Math.max(probe.capture.maxCollectionSize, maxCollectionSize)
|
|
127
108
|
maxFieldCount = Math.max(probe.capture.maxFieldCount, maxFieldCount)
|
|
@@ -131,23 +112,6 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
131
112
|
}
|
|
132
113
|
}
|
|
133
114
|
|
|
134
|
-
if (probe.condition !== undefined) {
|
|
135
|
-
// TODO: Bundle all conditions and evaluate them in a single call
|
|
136
|
-
// TODO: Handle errors
|
|
137
|
-
const { result } = /** @type {EvaluateOnCallFrameResult} */ (
|
|
138
|
-
// eslint-disable-next-line no-await-in-loop
|
|
139
|
-
await session.post('Debugger.evaluateOnCallFrame', {
|
|
140
|
-
callFrameId: params.callFrames[0].callFrameId,
|
|
141
|
-
expression: probe.condition,
|
|
142
|
-
returnByValue: true,
|
|
143
|
-
})
|
|
144
|
-
)
|
|
145
|
-
if (result.value !== true) continue
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
sampled = true
|
|
149
|
-
probe.lastCaptureNs = start
|
|
150
|
-
|
|
151
115
|
if (probe.templateRequiresEvaluation) {
|
|
152
116
|
templateExpressions += `,${probe.template}`
|
|
153
117
|
}
|
|
@@ -156,7 +120,8 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
156
120
|
}
|
|
157
121
|
}
|
|
158
122
|
|
|
159
|
-
if
|
|
123
|
+
// This can happen if sampled probe indexes are inconsistent with the worker state. Those cases are logged above.
|
|
124
|
+
if (probes.length === 0) {
|
|
160
125
|
return session.post('Debugger.resume')
|
|
161
126
|
}
|
|
162
127
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { DD_TRACE_SYMBOL, PROBE_SAMPLER_SYMBOL } = require('../probe_sampler_constants')
|
|
4
|
+
|
|
5
|
+
const SAMPLER_EXPRESSION = `globalThis[Symbol.for(${JSON.stringify(DD_TRACE_SYMBOL)})]?.` +
|
|
6
|
+
`[Symbol.for(${JSON.stringify(PROBE_SAMPLER_SYMBOL)})]`
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
compileBreakpointCondition,
|
|
10
|
+
getRemoveProbeExpression,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the expression that removes a probe from runtime sampler state. Called by the devtools worker and evaluated on
|
|
15
|
+
* the debuggee.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} id - The probe id.
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
function getRemoveProbeExpression (id) {
|
|
21
|
+
return `${SAMPLER_EXPRESSION}?.remove(${JSON.stringify(id)})`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build a Chrome DevTools breakpoint condition that samples all matching probes at a location. Called by the devtools
|
|
26
|
+
* worker.
|
|
27
|
+
*
|
|
28
|
+
* @param {{
|
|
29
|
+
* id: string,
|
|
30
|
+
* samplingIndex: number,
|
|
31
|
+
* nsBetweenSampling: bigint,
|
|
32
|
+
* condition?: string,
|
|
33
|
+
* captureSnapshot?: boolean,
|
|
34
|
+
* compiledCaptureExpressions?: object[]
|
|
35
|
+
* }[]} probes - The probes at the breakpoint location.
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
function compileBreakpointCondition (probes) {
|
|
39
|
+
const probeConditions = []
|
|
40
|
+
for (const probe of probes) {
|
|
41
|
+
probeConditions.push(compileProbeCondition(probe))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// NOTE: $dd_sampler is read from the realm-local `globalThis` where it was installed (the main
|
|
45
|
+
// realm). A probe whose code runs in a different V8 realm (e.g. a `vm.createContext` script with a
|
|
46
|
+
// file-path filename) won't see it and will silently never fire. Known limitation: a breakpoint
|
|
47
|
+
// condition has no realm-independent handle to reach, so we degrade rather than crash.
|
|
48
|
+
return `(() => {
|
|
49
|
+
const $dd_sampler = ${SAMPLER_EXPRESSION}
|
|
50
|
+
if ($dd_sampler === undefined) return false
|
|
51
|
+
let $dd_sampled = false
|
|
52
|
+
${probeConditions.join('\n ')}
|
|
53
|
+
return $dd_sampled
|
|
54
|
+
})()`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Build the condition fragment for a single probe. Called by the devtools worker while building breakpoint conditions.
|
|
59
|
+
*
|
|
60
|
+
* @param {{
|
|
61
|
+
* id: string,
|
|
62
|
+
* samplingIndex: number,
|
|
63
|
+
* nsBetweenSampling: bigint,
|
|
64
|
+
* condition?: string,
|
|
65
|
+
* captureSnapshot?: boolean,
|
|
66
|
+
* compiledCaptureExpressions?: object[]
|
|
67
|
+
* }} probe - The probe to sample.
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
function compileProbeCondition (probe) {
|
|
71
|
+
const sample = `$dd_sampler.makeSampleDecision(${probe.samplingIndex}, ${JSON.stringify(probe.id)}, ` +
|
|
72
|
+
`${probe.nsBetweenSampling}n, ${probe.captureSnapshot === true || probe.compiledCaptureExpressions !== undefined})`
|
|
73
|
+
|
|
74
|
+
if (probe.condition === undefined) {
|
|
75
|
+
return `$dd_sampled = ${sample} || $dd_sampled`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return `try {
|
|
79
|
+
if ((${probe.condition}) === true) {
|
|
80
|
+
$dd_sampled = ${sample} || $dd_sampled
|
|
81
|
+
}
|
|
82
|
+
} catch {}`
|
|
83
|
+
}
|
|
@@ -33,6 +33,7 @@ module.exports = {
|
|
|
33
33
|
locationToBreakpoint: new Map(),
|
|
34
34
|
breakpointToProbes: new Map(),
|
|
35
35
|
probeToLocation: new Map(),
|
|
36
|
+
samplingIndexToProbe: new Map(),
|
|
36
37
|
|
|
37
38
|
_loadedScripts: loadedScripts, // Only exposed for testing
|
|
38
39
|
_scriptUrls: scriptUrls, // Only exposed for testing
|
|
@@ -8,6 +8,7 @@ const log = require('../log')
|
|
|
8
8
|
const { fetchAgentInfo } = require('../agent/info')
|
|
9
9
|
const getDebuggerConfig = require('./config')
|
|
10
10
|
const { DEBUGGER_DIAGNOSTICS_V1, DEBUGGER_INPUT_V2 } = require('./constants')
|
|
11
|
+
const { installProbeSampler, uninstallProbeSampler } = require('./probe_sampler')
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @typedef {ReturnType<import('../config')>} Config
|
|
@@ -65,6 +66,8 @@ function start (config, rcInstance) {
|
|
|
65
66
|
|
|
66
67
|
globalThis[Symbol.for('dd-trace')].utilTypes = types
|
|
67
68
|
|
|
69
|
+
const probeSamplerBuffer = installProbeSampler()
|
|
70
|
+
|
|
68
71
|
readProbeFile(config.dynamicInstrumentation.probeFile, (probes) => {
|
|
69
72
|
const action = 'apply'
|
|
70
73
|
for (const probe of probes) {
|
|
@@ -110,6 +113,7 @@ function start (config, rcInstance) {
|
|
|
110
113
|
probePort: probeChannel.port1,
|
|
111
114
|
logPort: logChannel.port1,
|
|
112
115
|
configPort: configChannel.port1,
|
|
116
|
+
probeSamplerBuffer,
|
|
113
117
|
},
|
|
114
118
|
transferList: [probeChannel.port1, logChannel.port1, configChannel.port1],
|
|
115
119
|
}
|
|
@@ -187,6 +191,7 @@ function cleanup (error) {
|
|
|
187
191
|
worker.removeAllListeners()
|
|
188
192
|
worker = null
|
|
189
193
|
}
|
|
194
|
+
uninstallProbeSampler()
|
|
190
195
|
configChannel = null
|
|
191
196
|
inputPath = null
|
|
192
197
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { MAX_SNAPSHOTS_PER_SECOND_GLOBALLY } = require('./devtools_client/defaults')
|
|
4
|
+
const {
|
|
5
|
+
DD_TRACE_SYMBOL,
|
|
6
|
+
MAX_SAMPLED_PROBES_PER_PAUSE,
|
|
7
|
+
PROBE_SAMPLER_SYMBOL,
|
|
8
|
+
SAMPLED_PROBE_COUNT_INDEX,
|
|
9
|
+
SAMPLED_PROBE_INDEXES_START,
|
|
10
|
+
SAMPLED_PROBE_OVERFLOW_INDEX,
|
|
11
|
+
} = require('./probe_sampler_constants')
|
|
12
|
+
|
|
13
|
+
const ddTraceGlobal = /** @type {Record<symbol, SharedArrayBuffer | object | undefined>} */ (
|
|
14
|
+
/** @type {Record<symbol, unknown>} */ (globalThis)[Symbol.for(DD_TRACE_SYMBOL)]
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
installProbeSampler,
|
|
19
|
+
uninstallProbeSampler,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Install the runtime sampler in the debuggee context.
|
|
24
|
+
*
|
|
25
|
+
* @returns {SharedArrayBuffer} The shared sampler buffer to pass to the debugger worker.
|
|
26
|
+
*/
|
|
27
|
+
function installProbeSampler () {
|
|
28
|
+
const buffer = createProbeSamplerBuffer()
|
|
29
|
+
|
|
30
|
+
const lastCaptureNsByProbeId = new Map()
|
|
31
|
+
const sampledProbeIndexes = new Int32Array(buffer)
|
|
32
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_COUNT_INDEX, 0)
|
|
33
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 0)
|
|
34
|
+
|
|
35
|
+
const oneSecondNs = 1_000_000_000n
|
|
36
|
+
let globalSnapshotSamplingRateWindowStart = 0n
|
|
37
|
+
let snapshotsSampledWithinTheLastSecond = 0
|
|
38
|
+
|
|
39
|
+
ddTraceGlobal[Symbol.for(PROBE_SAMPLER_SYMBOL)] = {
|
|
40
|
+
/**
|
|
41
|
+
* Decide if a probe should be sampled and store sampled probe indexes for the debugger worker.
|
|
42
|
+
*
|
|
43
|
+
* @param {number} probeIndex - The worker-side probe sampling index.
|
|
44
|
+
* @param {string} probeId - The probe id.
|
|
45
|
+
* @param {bigint} nsBetweenSampling - Minimum nanoseconds between samples for this probe.
|
|
46
|
+
* @param {boolean} isSnapshotProducingProbe - Whether this probe counts toward the global snapshot sample limit.
|
|
47
|
+
* @returns {boolean} Whether this probe should make the breakpoint condition pause.
|
|
48
|
+
*/
|
|
49
|
+
makeSampleDecision (probeIndex, probeId, nsBetweenSampling, isSnapshotProducingProbe) {
|
|
50
|
+
const now = process.hrtime.bigint()
|
|
51
|
+
const lastCaptureNs = lastCaptureNsByProbeId.get(probeId)
|
|
52
|
+
if (lastCaptureNs !== undefined && now - lastCaptureNs < nsBetweenSampling) return false
|
|
53
|
+
|
|
54
|
+
let shouldResetGlobalSnapshotRateWindow = false
|
|
55
|
+
if (isSnapshotProducingProbe === true) {
|
|
56
|
+
if (now - globalSnapshotSamplingRateWindowStart > oneSecondNs) {
|
|
57
|
+
shouldResetGlobalSnapshotRateWindow = true
|
|
58
|
+
} else if (snapshotsSampledWithinTheLastSecond >= MAX_SNAPSHOTS_PER_SECOND_GLOBALLY) {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const sampledProbeCount = Atomics.add(sampledProbeIndexes, SAMPLED_PROBE_COUNT_INDEX, 1)
|
|
64
|
+
if (sampledProbeCount >= MAX_SAMPLED_PROBES_PER_PAUSE) {
|
|
65
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 1)
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (isSnapshotProducingProbe === true) {
|
|
70
|
+
if (shouldResetGlobalSnapshotRateWindow === true) {
|
|
71
|
+
snapshotsSampledWithinTheLastSecond = 1
|
|
72
|
+
globalSnapshotSamplingRateWindowStart = now
|
|
73
|
+
} else {
|
|
74
|
+
snapshotsSampledWithinTheLastSecond++
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
lastCaptureNsByProbeId.set(probeId, now)
|
|
79
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_INDEXES_START + sampledProbeCount, probeIndex)
|
|
80
|
+
return true
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Remove cached sampling state for a probe.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} probeId - The probe id.
|
|
87
|
+
*/
|
|
88
|
+
remove (probeId) {
|
|
89
|
+
lastCaptureNsByProbeId.delete(probeId)
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return buffer
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Remove the runtime sampler from the debuggee context.
|
|
98
|
+
*/
|
|
99
|
+
function uninstallProbeSampler () {
|
|
100
|
+
delete ddTraceGlobal[Symbol.for(PROBE_SAMPLER_SYMBOL)]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create the shared buffer used to hand sampled probe indexes from breakpoint conditions to the debugger worker.
|
|
105
|
+
*
|
|
106
|
+
* @returns {SharedArrayBuffer}
|
|
107
|
+
*/
|
|
108
|
+
function createProbeSamplerBuffer () {
|
|
109
|
+
return new SharedArrayBuffer(
|
|
110
|
+
(SAMPLED_PROBE_INDEXES_START + MAX_SAMPLED_PROBES_PER_PAUSE) * Int32Array.BYTES_PER_ELEMENT
|
|
111
|
+
)
|
|
112
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const DD_TRACE_SYMBOL = 'dd-trace'
|
|
4
|
+
const PROBE_SAMPLER_SYMBOL = 'dd-trace.debugger.probeSampler'
|
|
5
|
+
|
|
6
|
+
// Shared sampler contract used by the main debugger bootstrap and the devtools worker.
|
|
7
|
+
const MAX_SAMPLED_PROBES_PER_PAUSE = 256
|
|
8
|
+
const SAMPLED_PROBE_COUNT_INDEX = 0
|
|
9
|
+
const SAMPLED_PROBE_OVERFLOW_INDEX = 1
|
|
10
|
+
const SAMPLED_PROBE_INDEXES_START = 2
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
DD_TRACE_SYMBOL,
|
|
14
|
+
MAX_SAMPLED_PROBES_PER_PAUSE,
|
|
15
|
+
PROBE_SAMPLER_SYMBOL,
|
|
16
|
+
SAMPLED_PROBE_COUNT_INDEX,
|
|
17
|
+
SAMPLED_PROBE_INDEXES_START,
|
|
18
|
+
SAMPLED_PROBE_OVERFLOW_INDEX,
|
|
19
|
+
}
|