dd-trace 5.130.0 → 5.131.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.
Files changed (77) hide show
  1. package/index.d.ts +163 -22
  2. package/package.json +2 -2
  3. package/packages/datadog-esbuild/index.js +9 -6
  4. package/packages/datadog-instrumentations/src/ai.js +26 -0
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +2 -2
  6. package/packages/datadog-instrumentations/src/helpers/hooks.js +0 -7
  7. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +2 -2
  8. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +25 -0
  9. package/packages/datadog-plugin-openai/src/stream-helpers.js +50 -1
  10. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
  11. package/packages/dd-trace/src/config/remote_config.js +12 -0
  12. package/packages/dd-trace/src/config/supported-configurations.json +21 -0
  13. package/packages/dd-trace/src/debugger/constants.js +13 -4
  14. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +14 -1
  15. package/packages/dd-trace/src/debugger/devtools_client/condition.js +109 -6
  16. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
  17. package/packages/dd-trace/src/debugger/devtools_client/index.js +65 -6
  18. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +22 -10
  19. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +12 -8
  20. package/packages/dd-trace/src/debugger/devtools_client/send.js +14 -0
  21. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +43 -5
  22. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -8
  23. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +2 -122
  24. package/packages/dd-trace/src/debugger/guardrail-metrics.js +0 -2
  25. package/packages/dd-trace/src/debugger/index.js +60 -28
  26. package/packages/dd-trace/src/debugger/inspect-segment.js +92 -23
  27. package/packages/dd-trace/src/debugger/pause-duration-histogram.js +74 -0
  28. package/packages/dd-trace/src/debugger/probe_sampler.js +192 -52
  29. package/packages/dd-trace/src/debugger/redaction.js +139 -0
  30. package/packages/dd-trace/src/knuth-hash.js +17 -0
  31. package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
  32. package/packages/dd-trace/src/llmobs/experiments/client.js +66 -2
  33. package/packages/dd-trace/src/llmobs/experiments/evaluator.js +138 -0
  34. package/packages/dd-trace/src/llmobs/experiments/experiment.js +213 -90
  35. package/packages/dd-trace/src/llmobs/experiments/index.js +40 -1
  36. package/packages/dd-trace/src/llmobs/experiments/noop.js +53 -2
  37. package/packages/dd-trace/src/llmobs/experiments/remote-evaluator.js +110 -0
  38. package/packages/dd-trace/src/llmobs/experiments/util.js +34 -6
  39. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +2 -2
  40. package/packages/dd-trace/src/llmobs/sdk.js +19 -3
  41. package/packages/dd-trace/src/llmobs/span_processor.js +42 -26
  42. package/packages/dd-trace/src/llmobs/tagger.js +35 -0
  43. package/packages/dd-trace/src/llmobs/writers/base.js +1 -6
  44. package/packages/dd-trace/src/openfeature/constants/constants.js +10 -0
  45. package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -1
  46. package/packages/dd-trace/src/openfeature/writers/base.js +39 -18
  47. package/packages/dd-trace/src/openfeature/writers/flag-eval-evp-hook.js +105 -0
  48. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-aggregation.js +190 -0
  49. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-consumer.js +233 -0
  50. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-context.js +262 -0
  51. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-payload.js +181 -0
  52. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-pii.js +108 -0
  53. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-telemetry.js +154 -0
  54. package/packages/dd-trace/src/openfeature/writers/flag-evaluation-worker.js +77 -0
  55. package/packages/dd-trace/src/openfeature/writers/flag-evaluations.js +398 -0
  56. package/packages/dd-trace/src/openfeature/writers/util.js +5 -4
  57. package/packages/dd-trace/src/opentelemetry/context_manager.js +3 -0
  58. package/packages/dd-trace/src/opentelemetry/span_context.js +6 -2
  59. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +6 -0
  60. package/packages/dd-trace/src/opentelemetry/tracer.js +16 -18
  61. package/packages/dd-trace/src/opentracing/propagation/text_map.js +116 -25
  62. package/packages/dd-trace/src/opentracing/propagation/tracestate.js +80 -16
  63. package/packages/dd-trace/src/opentracing/span.js +14 -9
  64. package/packages/dd-trace/src/opentracing/tracer.js +10 -3
  65. package/packages/dd-trace/src/otel-sampling.js +171 -0
  66. package/packages/dd-trace/src/plugins/index.js +0 -1
  67. package/packages/dd-trace/src/priority_sampler.js +155 -33
  68. package/packages/dd-trace/src/remote_config/capabilities.js +9 -0
  69. package/packages/dd-trace/src/sampler.js +2 -5
  70. package/packages/dd-trace/src/sampling_rule.js +4 -8
  71. package/packages/dd-trace/src/span_format.js +6 -0
  72. package/packages/dd-trace/src/span_processor.js +26 -2
  73. package/packages/dd-trace/src/standalone/index.js +5 -4
  74. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +25 -5
  75. package/packages/dd-trace/src/telemetry/metrics.js +4 -3
  76. package/packages/datadog-instrumentations/src/postgres.js +0 -7
  77. package/packages/datadog-instrumentations/src/supabase.js +0 -15
package/index.d.ts CHANGED
@@ -3,6 +3,61 @@ import { LookupFunction } from 'net';
3
3
  import * as opentracing from "opentracing";
4
4
  import * as otel from "@opentelemetry/api";
5
5
 
6
+ declare const baseEvaluatorBrand: unique symbol
7
+ declare const baseSummaryEvaluatorBrand: unique symbol
8
+
9
+ declare const EvaluatorContext: {
10
+ new (options: {
11
+ inputData: tracer.llmobs.JSONType
12
+ outputData: tracer.llmobs.JSONType
13
+ expectedOutput?: tracer.llmobs.JSONType
14
+ metadata?: Record<string, tracer.llmobs.JSONType>
15
+ spanId?: string
16
+ traceId?: string
17
+ }): tracer.llmobs.EvaluatorContext
18
+ }
19
+
20
+ declare const SummaryEvaluatorContext: {
21
+ new (options: {
22
+ inputs: tracer.llmobs.JSONType[]
23
+ outputs: tracer.llmobs.JSONType[]
24
+ expectedOutputs: tracer.llmobs.JSONType[]
25
+ evaluationResults: Record<string, tracer.llmobs.JSONType[]>
26
+ metadata?: Array<Record<string, tracer.llmobs.JSONType>>
27
+ }): tracer.llmobs.SummaryEvaluatorContext
28
+ }
29
+
30
+ declare const EvaluatorResult: {
31
+ new (value: tracer.llmobs.JSONType, options?: tracer.llmobs.EvaluatorResultOptions): tracer.llmobs.EvaluatorResult
32
+ }
33
+
34
+ declare const MultiEvaluatorResult: {
35
+ new (values: Record<string, tracer.llmobs.JSONType | tracer.llmobs.EvaluatorResult>, prefix?: boolean): tracer.llmobs.MultiEvaluatorResult
36
+ }
37
+
38
+ declare const BaseEvaluator: {
39
+ new (name?: string): tracer.llmobs.BaseEvaluator
40
+ }
41
+
42
+ declare const BaseSummaryEvaluator: {
43
+ new (name?: string): tracer.llmobs.BaseSummaryEvaluator
44
+ }
45
+
46
+ declare const RemoteEvaluatorError: {
47
+ new (message: string, options?: {
48
+ status?: string
49
+ backendError?: Record<string, tracer.llmobs.JSONType>
50
+ }): tracer.llmobs.RemoteEvaluatorError
51
+ }
52
+
53
+ declare const RemoteEvaluator: {
54
+ new (options: {
55
+ evalName: string
56
+ transformFn?: (context: tracer.llmobs.EvaluatorContext) => Record<string, tracer.llmobs.JSONType>
57
+ }): tracer.llmobs.RemoteEvaluator
58
+ }
59
+
60
+
6
61
  /**
7
62
  * Tracer is the entry-point of the Datadog tracing implementation.
8
63
  */
@@ -162,6 +217,7 @@ interface Tracer extends opentracing.Tracer {
162
217
  *
163
218
  * @env DD_FEATURE_FLAGS_ENABLED
164
219
  * @env DD_FEATURE_FLAGS_CONFIGURATION_SOURCE
220
+ * @env DD_FLAGGING_EVALUATION_COUNTS_ENABLED
165
221
  * @beta This feature is in preview and not ready for production use
166
222
  */
167
223
  openfeature: tracer.OpenFeatureProvider;
@@ -1357,6 +1413,16 @@ declare namespace tracer {
1357
1413
  */
1358
1414
  captureTimeoutMs?: number
1359
1415
 
1416
+ /**
1417
+ * Time budget in milliseconds for evaluating a probe's condition, log message template and capture expressions.
1418
+ * An evaluation that exceeds the budget is reported as an evaluation error and the probe is not evaluated again
1419
+ * for a while.
1420
+ * @default 50
1421
+ * @env DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS
1422
+ * Programmatic configuration takes precedence over the environment variables listed above.
1423
+ */
1424
+ evaluationTimeoutMs?: number
1425
+
1360
1426
  /**
1361
1427
  * Interval in seconds between uploads of probe data.
1362
1428
  * @default 1
@@ -4249,6 +4315,74 @@ declare namespace tracer {
4249
4315
 
4250
4316
  type ReadonlyJSONType = string | number | boolean | null | ReadonlyArray<ReadonlyJSONType> | { readonly [key: string]: ReadonlyJSONType }
4251
4317
 
4318
+ /** Context passed to a record-level class evaluator. */
4319
+ interface EvaluatorContext {
4320
+ inputData: JSONType
4321
+ outputData: JSONType
4322
+ expectedOutput?: JSONType
4323
+ metadata: Record<string, JSONType>
4324
+ spanId?: string
4325
+ traceId?: string
4326
+ }
4327
+
4328
+ /** Context passed to a summary class evaluator. */
4329
+ interface SummaryEvaluatorContext {
4330
+ inputs: JSONType[]
4331
+ outputs: JSONType[]
4332
+ expectedOutputs: JSONType[]
4333
+ evaluationResults: Record<string, JSONType[]>
4334
+ metadata: Array<Record<string, JSONType>>
4335
+ }
4336
+
4337
+ interface EvaluatorResultOptions {
4338
+ reasoning?: string
4339
+ assessment?: 'pass' | 'fail'
4340
+ metadata?: Record<string, JSONType>
4341
+ tags?: Record<string, JSONType>
4342
+ }
4343
+
4344
+ /** A metric value with optional evaluation details. */
4345
+ interface EvaluatorResult {
4346
+ value: JSONType
4347
+ reasoning?: string
4348
+ assessment?: 'pass' | 'fail'
4349
+ metadata?: Record<string, JSONType>
4350
+ tags?: Record<string, JSONType>
4351
+ }
4352
+
4353
+ /** A result that emits several named metrics from one evaluator invocation. */
4354
+ interface MultiEvaluatorResult {
4355
+ values: Record<string, JSONType | EvaluatorResult>
4356
+ prefix: boolean
4357
+ }
4358
+
4359
+ /** Error returned by a managed evaluator configured in Datadog. */
4360
+ interface RemoteEvaluatorError extends Error {
4361
+ status: string
4362
+ backendError: Record<string, JSONType>
4363
+ }
4364
+
4365
+ /** Evaluator that references an LLM-as-a-judge evaluator configured in Datadog. */
4366
+ interface RemoteEvaluator extends BaseEvaluator {}
4367
+ interface ExperimentSummaryEvaluation extends EvaluatorResultOptions {
4368
+ value: any
4369
+ error: string | null
4370
+ }
4371
+
4372
+ /** Base class for reusable synchronous or asynchronous record-level evaluators. */
4373
+ interface BaseEvaluator {
4374
+ readonly [baseEvaluatorBrand]: never
4375
+ name: string
4376
+ evaluate (context: EvaluatorContext): JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4377
+ }
4378
+
4379
+ /** Base class for reusable synchronous or asynchronous summary evaluators. */
4380
+ interface BaseSummaryEvaluator {
4381
+ readonly [baseSummaryEvaluatorBrand]: never
4382
+ name: string
4383
+ evaluate (context: SummaryEvaluatorContext): JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4384
+ }
4385
+
4252
4386
  /**
4253
4387
  * A task run over each dataset record during an experiment.
4254
4388
  */
@@ -4258,26 +4392,25 @@ declare namespace tracer {
4258
4392
  metadata?: Record<string, JSONType>
4259
4393
  ) => JSONType | Promise<JSONType>
4260
4394
 
4261
- /**
4262
- * Scores a single task output. The return type selects the metric:
4263
- * `boolean` -> boolean, `number` -> score, `string` -> categorical, anything else -> json.
4264
- */
4265
- type ExperimentEvaluator = (
4395
+ /** Scores a single task output. */
4396
+ type ExperimentEvaluatorFunction = (
4266
4397
  input: JSONType,
4267
4398
  output: JSONType,
4268
4399
  expectedOutput: JSONType
4269
- ) => JSONType | Promise<JSONType>
4400
+ ) => JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4270
4401
 
4271
- /**
4272
- * Scores all rows in an experiment run and emits a summary metric.
4273
- */
4274
- type ExperimentSummaryEvaluator = (
4275
- inputs: any[],
4276
- outputs: any[],
4277
- expectedOutputs: any[],
4278
- evaluatorResults: Record<string, any[]>,
4279
- metadata?: Array<Record<string, any>>
4280
- ) => any | Promise<any>
4402
+ type ExperimentEvaluator = ExperimentEvaluatorFunction | BaseEvaluator
4403
+
4404
+ /** Scores all rows in an experiment run and emits a summary metric. */
4405
+ type ExperimentSummaryEvaluatorFunction = (
4406
+ inputs: JSONType[],
4407
+ outputs: JSONType[],
4408
+ expectedOutputs: JSONType[],
4409
+ evaluatorResults: Record<string, JSONType[]>,
4410
+ metadata?: Array<Record<string, JSONType>>
4411
+ ) => JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4412
+
4413
+ type ExperimentSummaryEvaluator = ExperimentSummaryEvaluatorFunction | BaseSummaryEvaluator
4281
4414
 
4282
4415
  interface DatasetRecord {
4283
4416
  id: string | null
@@ -4308,9 +4441,9 @@ declare namespace tracer {
4308
4441
  task: ExperimentTask
4309
4442
  /** Override the configured project for this experiment. */
4310
4443
  projectName?: string
4311
- /** Evaluators keyed by metric label, or named functions. */
4444
+ /** Evaluators keyed by metric label, or named functions or class instances. */
4312
4445
  evaluators?: Record<string, ExperimentEvaluator> | ExperimentEvaluator[]
4313
- /** Summary evaluators keyed by metric label, or named functions. */
4446
+ /** Summary evaluators keyed by metric label, or named functions or class instances. */
4314
4447
  summaryEvaluators?: Record<string, ExperimentSummaryEvaluator> | ExperimentSummaryEvaluator[]
4315
4448
  description?: string
4316
4449
  config?: Record<string, JSONType>
@@ -4366,7 +4499,7 @@ declare namespace tracer {
4366
4499
  /** Whether this run had a task, row-evaluator, or summary-evaluator error. */
4367
4500
  hasError: boolean
4368
4501
  rows: ExperimentResultRow[]
4369
- summaryEvaluations: Record<string, { value: any, error: string | null }>
4502
+ summaryEvaluations: Record<string, ExperimentSummaryEvaluation>
4370
4503
  }
4371
4504
 
4372
4505
  interface ExperimentResult {
@@ -4374,7 +4507,7 @@ declare namespace tracer {
4374
4507
  /** Rows from the first run, kept as a compatibility alias. */
4375
4508
  rows: ExperimentResultRow[]
4376
4509
  /** Summary evaluator results from the first run, kept as a compatibility alias. */
4377
- summaryEvaluations: Record<string, { value: any, error: string | null }>
4510
+ summaryEvaluations: Record<string, ExperimentSummaryEvaluation>
4378
4511
  /** All experiment runs. */
4379
4512
  runs: ExperimentRun[]
4380
4513
  /** Dashboard URL for the experiment. */
@@ -4509,6 +4642,14 @@ declare namespace tracer {
4509
4642
  }
4510
4643
 
4511
4644
  interface Experiments {
4645
+ BaseEvaluator: typeof BaseEvaluator
4646
+ BaseSummaryEvaluator: typeof BaseSummaryEvaluator
4647
+ EvaluatorContext: typeof EvaluatorContext
4648
+ SummaryEvaluatorContext: typeof SummaryEvaluatorContext
4649
+ EvaluatorResult: typeof EvaluatorResult
4650
+ MultiEvaluatorResult: typeof MultiEvaluatorResult
4651
+ RemoteEvaluator: typeof RemoteEvaluator
4652
+ RemoteEvaluatorError: typeof RemoteEvaluatorError
4512
4653
  /** Create a local dataset buffer; pushed on the first experiment run. */
4513
4654
  createDataset (name: string, description?: string): Dataset
4514
4655
  createDataset (name: string, options?: CreateDatasetOptions): Dataset
@@ -4529,12 +4670,12 @@ declare namespace tracer {
4529
4670
  /**
4530
4671
  * The input content associated with the span.
4531
4672
  */
4532
- input: { content: string, role?: string }[]
4673
+ input: { content: JSONType, role?: string }[]
4533
4674
 
4534
4675
  /**
4535
4676
  * The output content associated with the span.
4536
4677
  */
4537
- output: { content: string, role?: string }[]
4678
+ output: { content: JSONType, role?: string }[]
4538
4679
 
4539
4680
  /**
4540
4681
  * Get a tag from the span.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.130.0",
3
+ "version": "5.131.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -190,7 +190,7 @@
190
190
  "optionalDependencies": {
191
191
  "@datadog/libdatadog": "^0.21.0",
192
192
  "@datadog/libdatadog-extras": "^0.21.0",
193
- "@datadog/native-appsec": "11.0.2",
193
+ "@datadog/native-appsec": "11.0.3",
194
194
  "@datadog/native-iast-taint-tracking": "4.2.1",
195
195
  "@datadog/native-metrics": "4.0.0",
196
196
  "@datadog/pprof": "5.19.0",
@@ -165,8 +165,6 @@ ${build.initialOptions.banner.js}`
165
165
  log.warn('No git metadata available - skipping injection')
166
166
  }
167
167
 
168
- // first time is intercepted, proxy should be created, next time the original should be loaded
169
- const interceptedESMModules = new Set()
170
168
  let resolver
171
169
 
172
170
  build.onEnd(async () => {
@@ -217,11 +215,18 @@ ${build.initialOptions.banner.js}`
217
215
 
218
216
  const internal = builtins.has(args.path)
219
217
 
218
+ // Only the generated wrapper module, and the real module importing itself, must reach the real module unwrapped.
219
+ // Every other importer must get the wrapper regardless of whether it has already been loaded: onLoad runs
220
+ // concurrently with onResolve, so tracking loaded modules makes which importer sees the wrapper depend on timing,
221
+ // leaving some bindings uninstrumented. Routing a self-import to the wrapper would create a wrapper -> original ->
222
+ // wrapper cycle that can hit the wrapper's exports in their temporal dead zone.
223
+ const isInterceptedImporter = args.importer.endsWith(ESM_INTERCEPTED_SUFFIX) || args.importer === fullPathToModule
224
+
220
225
  if (args.namespace === 'file' && (
221
226
  modulesOfInterest.has(args.path) || modulesOfInterest.has(`${extracted.pkg}/${extracted.path}`))
222
227
  ) {
223
228
  // Internal module like http/fs is imported and the build output is ESM
224
- if (internal && args.kind === 'import-statement' && esmBuild && !interceptedESMModules.has(fullPathToModule)) {
229
+ if (internal && args.kind === 'import-statement' && esmBuild && !isInterceptedImporter) {
225
230
  fullPathToModule = `${INTERNAL_ESM_INTERCEPTED_PREFIX}${fullPathToModule}${ESM_INTERCEPTED_SUFFIX}`
226
231
 
227
232
  return {
@@ -263,7 +268,7 @@ ${build.initialOptions.banner.js}`
263
268
  const packageJson = JSON.parse(fs.readFileSync(/** @type {string} */(pathToPackageJson)).toString())
264
269
 
265
270
  const isESM = isESMFile(fullPathToModule, pathToPackageJson, packageJson)
266
- if (isESM && !interceptedESMModules.has(fullPathToModule)) {
271
+ if (isESM && !isInterceptedImporter) {
267
272
  fullPathToModule += ESM_INTERCEPTED_SUFFIX
268
273
  }
269
274
 
@@ -322,8 +327,6 @@ ${build.initialOptions.banner.js}`
322
327
  args.path = args.path.slice(INTERNAL_ESM_INTERCEPTED_PREFIX.length)
323
328
  }
324
329
 
325
- interceptedESMModules.add(args.path)
326
-
327
330
  resolver ??= createEsmResolver()
328
331
  const setters = await processModule({
329
332
  path: args.path,
@@ -194,6 +194,32 @@ for (const hook of getHooks('ai').values()) {
194
194
  },
195
195
  })
196
196
 
197
+ tracingChannel('orchestrion:ai:includeRuntimeContext').subscribe({
198
+ start (ctx) {
199
+ const options = ctx.arguments[0]
200
+ const runtimeContext = options?.runtimeContext
201
+ const telemetry = options?.telemetry ?? options?.experimental_telemetry
202
+
203
+ if (!runtimeContext || typeof runtimeContext !== 'object' || telemetry?.isEnabled === false) return
204
+
205
+ const keys = Object.keys(runtimeContext)
206
+ if (!keys.length) return
207
+
208
+ const includeRuntimeContext = { ...telemetry?.includeRuntimeContext }
209
+ for (const key of keys) {
210
+ if (includeRuntimeContext[key] === undefined) includeRuntimeContext[key] = true
211
+ }
212
+
213
+ ctx.arguments[0] = {
214
+ ...options,
215
+ telemetry: {
216
+ ...telemetry,
217
+ includeRuntimeContext,
218
+ },
219
+ }
220
+ },
221
+ })
222
+
197
223
  // resolveLanguageModel is called by all LLM entry points (generateText, streamText,
198
224
  // generateObject, streamObject)
199
225
  tracingChannel('orchestrion:ai:resolveLanguageModel').subscribe({
@@ -198,11 +198,11 @@ function wrapSmithySend (send) {
198
198
  }
199
199
 
200
200
  return channels.start.runStores(ctx, () => {
201
- // When the region is not set this never resolves so we can't await.
201
+ // Resolve region tags independently; send reports provider failures through its promise or callback.
202
202
  this.config.region().then(region => {
203
203
  ctx.region = region
204
204
  channels.region.publish(ctx)
205
- })
205
+ }, () => {})
206
206
 
207
207
  if (cbExists) {
208
208
  args[args.length - 1] = shimmer.wrapCallback(cb, cb => function (err, result) {
@@ -2,12 +2,6 @@
2
2
 
3
3
  module.exports = {
4
4
  // Only list unprefixed node modules. They will automatically be instrumented as prefixed and unprefixed.
5
- '@supabase/auth-js': { esmFirst: true, fn: () => require('../supabase') },
6
- '@supabase/functions-js': { esmFirst: true, fn: () => require('../supabase') },
7
- '@supabase/postgrest-js': { esmFirst: true, fn: () => require('../supabase') },
8
- '@supabase/realtime-js': { esmFirst: true, fn: () => require('../supabase') },
9
- '@supabase/storage-js': { esmFirst: true, fn: () => require('../supabase') },
10
- '@supabase/supabase-js': { esmFirst: true, fn: () => require('../supabase') },
11
5
  child_process: () => require('../child_process'),
12
6
  crypto: () => require('../crypto'),
13
7
  dns: () => require('../dns'),
@@ -142,7 +136,6 @@ module.exports = {
142
136
  'pino-pretty': () => require('../pino'),
143
137
  playwright: () => require('../playwright'),
144
138
  'playwright-core': () => require('../playwright'),
145
- postgres: { esmFirst: true, fn: () => require('../postgres') },
146
139
  'promise-js': () => require('../promise-js'),
147
140
  promise: () => require('../promise'),
148
141
  protobufjs: () => require('../protobufjs'),
@@ -17,10 +17,10 @@ const registry = [
17
17
  { instrumentations: require('./instrumentations/modelcontextprotocol-sdk') },
18
18
  { instrumentations: require('./instrumentations/openai-agents') },
19
19
  { instrumentations: require('./instrumentations/playwright') },
20
- { instrumentations: require('./instrumentations/postgres') },
20
+ { activate: true, instrumentations: require('./instrumentations/postgres') },
21
21
  { instrumentations: require('./instrumentations/webdriverio') },
22
22
  { instrumentations: require('./instrumentations/aws-durable-execution-sdk-js') },
23
- { instrumentations: require('./instrumentations/supabase') },
23
+ { activate: true, instrumentations: require('./instrumentations/supabase') },
24
24
  ]
25
25
 
26
26
  const activatedModules = new Set()
@@ -88,6 +88,31 @@ module.exports = [
88
88
  },
89
89
  channelName: 'resolveLanguageModel',
90
90
  },
91
+ // AI SDK v7 filters runtime context from tracing channel events unless each key is included.
92
+ {
93
+ module: {
94
+ name: 'ai',
95
+ versionRange: '>=7.0.0',
96
+ filePath: 'dist/index.js',
97
+ },
98
+ functionQuery: {
99
+ functionName: 'generateText',
100
+ kind: 'Async',
101
+ },
102
+ channelName: 'includeRuntimeContext',
103
+ },
104
+ {
105
+ module: {
106
+ name: 'ai',
107
+ versionRange: '>=7.0.0',
108
+ filePath: 'dist/index.js',
109
+ },
110
+ functionQuery: {
111
+ functionName: 'streamText',
112
+ kind: 'Sync',
113
+ },
114
+ channelName: 'includeRuntimeContext',
115
+ },
91
116
  {
92
117
  module: {
93
118
  name: 'ai',
@@ -17,7 +17,13 @@
17
17
  * @typedef {JsonObject & { choices: Array<StreamChoice | undefined>, usage?: unknown }} StreamResponseBody
18
18
  *
19
19
  * @typedef {JsonObject & { status?: string }} ResponsesApiResponse
20
- * @typedef {JsonObject & { response?: ResponsesApiResponse }} ResponsesApiChunk
20
+ * @typedef {JsonObject & {
21
+ * type?: string,
22
+ * response?: ResponsesApiResponse,
23
+ * output_index?: number,
24
+ * item?: JsonObject,
25
+ * delta?: string
26
+ * }} ResponsesApiChunk
21
27
  */
22
28
 
23
29
  /**
@@ -143,12 +149,55 @@ function constructResponseResponseFromStreamedChunks (chunks) {
143
149
  // Find the last chunk with a complete response object (status: done, incomplete, or completed)
144
150
  const responseStatusSet = new Set(['done', 'incomplete', 'completed'])
145
151
 
152
+ let latestResponse
146
153
  for (let i = chunks.length - 1; i >= 0; i--) {
147
154
  const chunk = chunks[i]
148
155
  if (chunk.response && responseStatusSet.has(chunk.response.status)) {
149
156
  return chunk.response
150
157
  }
158
+ latestResponse ??= chunk.response
151
159
  }
160
+
161
+ // A stream that ends early (e.g. aborted by the caller) never sends a final response,
162
+ // so rebuild a partial one from the output streamed so far, as the chat helpers do.
163
+ if (latestResponse) {
164
+ return { ...latestResponse, output: constructPartialResponseOutput(chunks) }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Rebuilds the output items of a Responses API stream that ended before its final response.
170
+ * Items are shallow-copied so the chunks handed to the application are not mutated.
171
+ * @param {ResponsesApiChunk[]} chunks
172
+ * @returns {JsonObject[]}
173
+ */
174
+ function constructPartialResponseOutput (chunks) {
175
+ const output = []
176
+
177
+ for (const chunk of chunks) {
178
+ const index = chunk.output_index
179
+ if (index === undefined) continue
180
+
181
+ const item = output[index]
182
+
183
+ switch (chunk.type) {
184
+ case 'response.output_item.added':
185
+ case 'response.output_item.done':
186
+ output[index] = { ...chunk.item }
187
+ break
188
+ case 'response.output_text.delta':
189
+ if (item) {
190
+ const text = (item.content?.[0]?.text ?? '') + (chunk.delta ?? '')
191
+ item.content = [{ type: 'output_text', text }]
192
+ }
193
+ break
194
+ case 'response.function_call_arguments.delta':
195
+ if (item) item.arguments = (item.arguments ?? '') + (chunk.delta ?? '')
196
+ break
197
+ }
198
+ }
199
+
200
+ return output.filter(Boolean)
152
201
  }
153
202
 
154
203
  module.exports = {
@@ -416,6 +416,7 @@ export interface GeneratedConfig {
416
416
  dynamicInstrumentation: {
417
417
  DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS: number;
418
418
  DD_DYNAMIC_INSTRUMENTATION_ENABLED: boolean;
419
+ DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS: number;
419
420
  DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE: string | undefined;
420
421
  DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS: string[];
421
422
  DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS: string[];
@@ -434,6 +435,7 @@ export interface GeneratedConfig {
434
435
  DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
435
436
  DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
436
437
  DD_FEATURE_FLAGS_ENABLED: boolean;
438
+ DD_FLAGGING_EVALUATION_COUNTS_ENABLED: boolean;
437
439
  };
438
440
  flushInterval: number;
439
441
  flushMinSpans: number;
@@ -690,6 +692,7 @@ export interface GeneratedEnvVarConfig {
690
692
  DD_DURABLE_CROSS_INVOCATION_TRACING_ENABLED: boolean;
691
693
  DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS: number;
692
694
  DD_DYNAMIC_INSTRUMENTATION_ENABLED: boolean;
695
+ DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS: number;
693
696
  DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE: string | undefined;
694
697
  DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS: string[];
695
698
  DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS: string[];
@@ -715,6 +718,7 @@ export interface GeneratedEnvVarConfig {
715
718
  DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
716
719
  DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
717
720
  DD_FEATURE_FLAGS_ENABLED: boolean;
721
+ DD_FLAGGING_EVALUATION_COUNTS_ENABLED: boolean;
718
722
  DD_GIT_BRANCH: string | undefined;
719
723
  DD_GIT_COMMIT_AUTHOR_DATE: string | undefined;
720
724
  DD_GIT_COMMIT_AUTHOR_EMAIL: string | undefined;
@@ -148,6 +148,18 @@ function enable (rc, config, onConfigUpdated) {
148
148
  // APM_TRACING product (e.g. an org-level and a service-level config) and merges them by priority.
149
149
  rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_MULTICONFIG, true)
150
150
 
151
+ // Keep advertising the legacy per-setting capabilities while the backend and UI still use them
152
+ // to determine which settings are editable. Values are delivered through sdk_config below.
153
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLED, true)
154
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
155
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RULES, true)
156
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)
157
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_HTTP_HEADER_TAGS, true)
158
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_LOGS_INJECTION, true)
159
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_DYNAMIC_INSTRUMENTATION, true)
160
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_LIVE_DEBUGGING, true)
161
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_CODE_ORIGIN, true)
162
+
151
163
  // This tracer supports receiving the full SDK_CONFIGURATION settings map, env-var-keyed.
152
164
  rc.updateCapabilities(RemoteConfigCapabilities.SDK_CONFIGURATION, true)
153
165
 
@@ -820,6 +820,18 @@
820
820
  "default": "false"
821
821
  }
822
822
  ],
823
+ "DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS": [
824
+ {
825
+ "implementation": "A",
826
+ "type": "int",
827
+ "namespace": "dynamicInstrumentation",
828
+ "configurationNames": [
829
+ "dynamicInstrumentation.evaluationTimeoutMs"
830
+ ],
831
+ "default": "50",
832
+ "allowed": "\\d+"
833
+ }
834
+ ],
823
835
  "DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE": [
824
836
  {
825
837
  "implementation": "B",
@@ -973,6 +985,15 @@
973
985
  "namespace": "featureFlags"
974
986
  }
975
987
  ],
988
+ "DD_FLAGGING_EVALUATION_COUNTS_ENABLED": [
989
+ {
990
+ "implementation": "A",
991
+ "type": "boolean",
992
+ "default": "true",
993
+ "description": "Enable aggregated Feature Flagging evaluation telemetry.",
994
+ "namespace": "featureFlags"
995
+ }
996
+ ],
976
997
  "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": [
977
998
  {
978
999
  "implementation": "B",
@@ -1,5 +1,13 @@
1
1
  'use strict'
2
2
 
3
+ const WORKER_ERROR_REASON = Object.freeze({
4
+ UNEXPECTED_PAUSE_REASON: 'unexpected_pause_reason',
5
+ UNSUPPORTED_PROBE_TYPE: 'unsupported_probe_type',
6
+ UNSUPPORTED_INSERTION_POINT: 'unsupported_insertion_point',
7
+ CONFLICTING_CAPTURE_OPTIONS: 'conflicting_capture_options',
8
+ UNKNOWN_REMOTE_CONFIG_ACTION: 'unknown_remote_config_action',
9
+ })
10
+
3
11
  module.exports = {
4
12
  DEFAULT_QUEUE_MAX_BYTES: 10 * 1024 * 1024,
5
13
  DIAGNOSTICS_QUEUE_MAX_BYTES: 1024 * 1024,
@@ -10,10 +18,11 @@ module.exports = {
10
18
  DEBUGGER_INPUT_V1: '/debugger/v1/input',
11
19
  DEBUGGER_INPUT_V2: '/debugger/v2/input',
12
20
 
13
- // Guardrail counters are aggregated in shared memory and only converted into telemetry metrics at this interval, so
14
- // the interval bounds the delay before a guardrail hit becomes visible, not the cost of recording it. Tests wait on
15
- // it, so it is shared rather than duplicated.
16
- GUARDRAIL_METRICS_FLUSH_INTERVAL_MS: 10_000,
21
+ // Guardrail counters and pause durations are aggregated in shared memory and only converted into telemetry metrics
22
+ // at this interval, so the interval bounds the delay before they become visible, not the cost of recording them.
23
+ // Tests wait on it, so it is shared rather than duplicated.
24
+ METRICS_FLUSH_INTERVAL_MS: 10_000,
17
25
 
18
26
  INSPECT_SEGMENT_GLOBAL_PROPERTY: 'debuggerInspectSegment',
27
+ WORKER_ERROR_REASON,
19
28
  }
@@ -4,7 +4,13 @@ const createMutex = require('../../../../../vendor/dist/mutexify/promise')
4
4
  const mutex = createMutex()
5
5
  const { getGeneratedPosition } = require('./source-maps')
6
6
  const session = require('./session')
7
- const { compile, compileSegments, templateRequiresEvaluation } = require('./condition')
7
+ const {
8
+ compile,
9
+ compileSegments,
10
+ getRedactionError,
11
+ getSegmentRedactionErrors,
12
+ templateRequiresEvaluation,
13
+ } = require('./condition')
8
14
  const { MAX_SNAPSHOTS_PER_SECOND_PER_PROBE, MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE } = require('./defaults')
9
15
  const {
10
16
  compileBreakpointCondition,
@@ -78,6 +84,7 @@ async function addBreakpoint (probe) {
78
84
  probe.templateRequiresEvaluation = templateRequiresEvaluation(probe.segments)
79
85
  if (probe.templateRequiresEvaluation) {
80
86
  probe.template = compileSegments(probe.segments)
87
+ probe.templateRedactionErrors = getSegmentRedactionErrors(probe.segments)
81
88
  }
82
89
  delete probe.segments
83
90
 
@@ -128,6 +135,12 @@ async function addBreakpoint (probe) {
128
135
  if (probe.captureExpressions?.length > 0) {
129
136
  probe.compiledCaptureExpressions = []
130
137
  for (const captureExpr of probe.captureExpressions) {
138
+ const redactionError = getRedactionError(captureExpr.name, captureExpr.expr.json)
139
+ if (redactionError !== undefined) {
140
+ probe.compiledCaptureExpressions.push({ name: captureExpr.name, redactionError })
141
+ continue
142
+ }
143
+
131
144
  let expression
132
145
  try {
133
146
  expression = compile(captureExpr.expr.json)