dd-trace 6.19.0 → 6.20.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;
@@ -1245,6 +1301,16 @@ declare namespace tracer {
1245
1301
  */
1246
1302
  captureTimeoutMs?: number
1247
1303
 
1304
+ /**
1305
+ * Time budget in milliseconds for evaluating a probe's condition, log message template and capture expressions.
1306
+ * An evaluation that exceeds the budget is reported as an evaluation error and the probe is not evaluated again
1307
+ * for a while.
1308
+ * @default 50
1309
+ * @env DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS
1310
+ * Programmatic configuration takes precedence over the environment variables listed above.
1311
+ */
1312
+ evaluationTimeoutMs?: number
1313
+
1248
1314
  /**
1249
1315
  * Interval in seconds between uploads of probe data.
1250
1316
  * @default 1
@@ -4052,6 +4118,74 @@ declare namespace tracer {
4052
4118
 
4053
4119
  type ReadonlyJSONType = string | number | boolean | null | ReadonlyArray<ReadonlyJSONType> | { readonly [key: string]: ReadonlyJSONType }
4054
4120
 
4121
+ /** Context passed to a record-level class evaluator. */
4122
+ interface EvaluatorContext {
4123
+ inputData: JSONType
4124
+ outputData: JSONType
4125
+ expectedOutput?: JSONType
4126
+ metadata: Record<string, JSONType>
4127
+ spanId?: string
4128
+ traceId?: string
4129
+ }
4130
+
4131
+ /** Context passed to a summary class evaluator. */
4132
+ interface SummaryEvaluatorContext {
4133
+ inputs: JSONType[]
4134
+ outputs: JSONType[]
4135
+ expectedOutputs: JSONType[]
4136
+ evaluationResults: Record<string, JSONType[]>
4137
+ metadata: Array<Record<string, JSONType>>
4138
+ }
4139
+
4140
+ interface EvaluatorResultOptions {
4141
+ reasoning?: string
4142
+ assessment?: 'pass' | 'fail'
4143
+ metadata?: Record<string, JSONType>
4144
+ tags?: Record<string, JSONType>
4145
+ }
4146
+
4147
+ /** A metric value with optional evaluation details. */
4148
+ interface EvaluatorResult {
4149
+ value: JSONType
4150
+ reasoning?: string
4151
+ assessment?: 'pass' | 'fail'
4152
+ metadata?: Record<string, JSONType>
4153
+ tags?: Record<string, JSONType>
4154
+ }
4155
+
4156
+ /** A result that emits several named metrics from one evaluator invocation. */
4157
+ interface MultiEvaluatorResult {
4158
+ values: Record<string, JSONType | EvaluatorResult>
4159
+ prefix: boolean
4160
+ }
4161
+
4162
+ /** Error returned by a managed evaluator configured in Datadog. */
4163
+ interface RemoteEvaluatorError extends Error {
4164
+ status: string
4165
+ backendError: Record<string, JSONType>
4166
+ }
4167
+
4168
+ /** Evaluator that references an LLM-as-a-judge evaluator configured in Datadog. */
4169
+ interface RemoteEvaluator extends BaseEvaluator {}
4170
+ interface ExperimentSummaryEvaluation extends EvaluatorResultOptions {
4171
+ value: any
4172
+ error: string | null
4173
+ }
4174
+
4175
+ /** Base class for reusable synchronous or asynchronous record-level evaluators. */
4176
+ interface BaseEvaluator {
4177
+ readonly [baseEvaluatorBrand]: never
4178
+ name: string
4179
+ evaluate (context: EvaluatorContext): JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4180
+ }
4181
+
4182
+ /** Base class for reusable synchronous or asynchronous summary evaluators. */
4183
+ interface BaseSummaryEvaluator {
4184
+ readonly [baseSummaryEvaluatorBrand]: never
4185
+ name: string
4186
+ evaluate (context: SummaryEvaluatorContext): JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4187
+ }
4188
+
4055
4189
  /**
4056
4190
  * A task run over each dataset record during an experiment.
4057
4191
  */
@@ -4061,26 +4195,25 @@ declare namespace tracer {
4061
4195
  metadata?: Record<string, JSONType>
4062
4196
  ) => JSONType | Promise<JSONType>
4063
4197
 
4064
- /**
4065
- * Scores a single task output. The return type selects the metric:
4066
- * `boolean` -> boolean, `number` -> score, `string` -> categorical, anything else -> json.
4067
- */
4068
- type ExperimentEvaluator = (
4198
+ /** Scores a single task output. */
4199
+ type ExperimentEvaluatorFunction = (
4069
4200
  input: JSONType,
4070
4201
  output: JSONType,
4071
4202
  expectedOutput: JSONType
4072
- ) => JSONType | Promise<JSONType>
4203
+ ) => JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4073
4204
 
4074
- /**
4075
- * Scores all rows in an experiment run and emits a summary metric.
4076
- */
4077
- type ExperimentSummaryEvaluator = (
4078
- inputs: any[],
4079
- outputs: any[],
4080
- expectedOutputs: any[],
4081
- evaluatorResults: Record<string, any[]>,
4082
- metadata?: Array<Record<string, any>>
4083
- ) => any | Promise<any>
4205
+ type ExperimentEvaluator = ExperimentEvaluatorFunction | BaseEvaluator
4206
+
4207
+ /** Scores all rows in an experiment run and emits a summary metric. */
4208
+ type ExperimentSummaryEvaluatorFunction = (
4209
+ inputs: JSONType[],
4210
+ outputs: JSONType[],
4211
+ expectedOutputs: JSONType[],
4212
+ evaluatorResults: Record<string, JSONType[]>,
4213
+ metadata?: Array<Record<string, JSONType>>
4214
+ ) => JSONType | EvaluatorResult | MultiEvaluatorResult | Promise<JSONType | EvaluatorResult | MultiEvaluatorResult>
4215
+
4216
+ type ExperimentSummaryEvaluator = ExperimentSummaryEvaluatorFunction | BaseSummaryEvaluator
4084
4217
 
4085
4218
  interface DatasetRecord {
4086
4219
  id: string | null
@@ -4111,9 +4244,9 @@ declare namespace tracer {
4111
4244
  task: ExperimentTask
4112
4245
  /** Override the configured project for this experiment. */
4113
4246
  projectName?: string
4114
- /** Evaluators keyed by metric label, or named functions. */
4247
+ /** Evaluators keyed by metric label, or named functions or class instances. */
4115
4248
  evaluators?: Record<string, ExperimentEvaluator> | ExperimentEvaluator[]
4116
- /** Summary evaluators keyed by metric label, or named functions. */
4249
+ /** Summary evaluators keyed by metric label, or named functions or class instances. */
4117
4250
  summaryEvaluators?: Record<string, ExperimentSummaryEvaluator> | ExperimentSummaryEvaluator[]
4118
4251
  description?: string
4119
4252
  config?: Record<string, JSONType>
@@ -4169,7 +4302,7 @@ declare namespace tracer {
4169
4302
  /** Whether this run had a task, row-evaluator, or summary-evaluator error. */
4170
4303
  hasError: boolean
4171
4304
  rows: ExperimentResultRow[]
4172
- summaryEvaluations: Record<string, { value: any, error: string | null }>
4305
+ summaryEvaluations: Record<string, ExperimentSummaryEvaluation>
4173
4306
  }
4174
4307
 
4175
4308
  interface ExperimentResult {
@@ -4177,7 +4310,7 @@ declare namespace tracer {
4177
4310
  /** Rows from the first run, kept as a compatibility alias. */
4178
4311
  rows: ExperimentResultRow[]
4179
4312
  /** Summary evaluator results from the first run, kept as a compatibility alias. */
4180
- summaryEvaluations: Record<string, { value: any, error: string | null }>
4313
+ summaryEvaluations: Record<string, ExperimentSummaryEvaluation>
4181
4314
  /** All experiment runs. */
4182
4315
  runs: ExperimentRun[]
4183
4316
  /** Dashboard URL for the experiment. */
@@ -4312,6 +4445,14 @@ declare namespace tracer {
4312
4445
  }
4313
4446
 
4314
4447
  interface Experiments {
4448
+ BaseEvaluator: typeof BaseEvaluator
4449
+ BaseSummaryEvaluator: typeof BaseSummaryEvaluator
4450
+ EvaluatorContext: typeof EvaluatorContext
4451
+ SummaryEvaluatorContext: typeof SummaryEvaluatorContext
4452
+ EvaluatorResult: typeof EvaluatorResult
4453
+ MultiEvaluatorResult: typeof MultiEvaluatorResult
4454
+ RemoteEvaluator: typeof RemoteEvaluator
4455
+ RemoteEvaluatorError: typeof RemoteEvaluatorError
4315
4456
  /** Create a local dataset buffer; pushed on the first experiment run. */
4316
4457
  createDataset (name: string, description?: string): Dataset
4317
4458
  createDataset (name: string, options?: CreateDatasetOptions): Dataset
@@ -4332,12 +4473,12 @@ declare namespace tracer {
4332
4473
  /**
4333
4474
  * The input content associated with the span.
4334
4475
  */
4335
- input: { content: string, role?: string }[]
4476
+ input: { content: JSONType, role?: string }[]
4336
4477
 
4337
4478
  /**
4338
4479
  * The output content associated with the span.
4339
4480
  */
4340
- output: { content: string, role?: string }[]
4481
+ output: { content: JSONType, role?: string }[]
4341
4482
 
4342
4483
  /**
4343
4484
  * Get a tag from the span.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "6.19.0",
3
+ "version": "6.20.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)