dd-trace 5.114.0 → 5.116.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 (207) hide show
  1. package/README.electron.md +7 -0
  2. package/README.md +17 -0
  3. package/ci/diagnose.js +2100 -0
  4. package/ci/init.js +23 -2
  5. package/ci/runbook.md +198 -0
  6. package/ci/test-optimization-validation/approval-artifacts.js +143 -0
  7. package/ci/test-optimization-validation/approval.js +299 -0
  8. package/ci/test-optimization-validation/artifact-id.js +20 -0
  9. package/ci/test-optimization-validation/bounded-json.js +121 -0
  10. package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
  11. package/ci/test-optimization-validation/ci-discovery.js +181 -0
  12. package/ci/test-optimization-validation/ci-remediation.js +210 -0
  13. package/ci/test-optimization-validation/cli.js +903 -0
  14. package/ci/test-optimization-validation/command-blocker.js +81 -0
  15. package/ci/test-optimization-validation/command-output-policy.js +206 -0
  16. package/ci/test-optimization-validation/command-runner.js +707 -0
  17. package/ci/test-optimization-validation/command-suitability.js +471 -0
  18. package/ci/test-optimization-validation/executable-approval.js +48 -0
  19. package/ci/test-optimization-validation/executable.js +480 -0
  20. package/ci/test-optimization-validation/generated-file-policy.js +63 -0
  21. package/ci/test-optimization-validation/generated-files.js +351 -0
  22. package/ci/test-optimization-validation/generated-verifier.js +196 -0
  23. package/ci/test-optimization-validation/init-probe-preload.js +163 -0
  24. package/ci/test-optimization-validation/init-probe.js +246 -0
  25. package/ci/test-optimization-validation/late-initialization.js +63 -0
  26. package/ci/test-optimization-validation/local-command.js +163 -0
  27. package/ci/test-optimization-validation/manifest-loader.js +133 -0
  28. package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
  29. package/ci/test-optimization-validation/manifest-schema.js +862 -0
  30. package/ci/test-optimization-validation/offline-fixtures.js +327 -0
  31. package/ci/test-optimization-validation/offline-output.js +406 -0
  32. package/ci/test-optimization-validation/payload-normalizer.js +72 -0
  33. package/ci/test-optimization-validation/plan-writer.js +1120 -0
  34. package/ci/test-optimization-validation/preflight-runner.js +114 -0
  35. package/ci/test-optimization-validation/redaction.js +331 -0
  36. package/ci/test-optimization-validation/report-writer.js +1508 -0
  37. package/ci/test-optimization-validation/safe-files.js +203 -0
  38. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
  39. package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
  40. package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
  41. package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
  42. package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
  43. package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
  44. package/ci/test-optimization-validation/setup-runner.js +97 -0
  45. package/ci/test-optimization-validation/static-diagnosis.js +159 -0
  46. package/ci/test-optimization-validation/test-output.js +129 -0
  47. package/ci/test-optimization-validation-manifest.schema.json +1 -0
  48. package/ci/validate-test-optimization.js +3 -0
  49. package/ext/exporters.js +1 -0
  50. package/index.d.ts +121 -8
  51. package/index.electron.js +3 -0
  52. package/init.js +18 -0
  53. package/initialize.mjs +1 -1
  54. package/loader-hook.mjs +28 -18
  55. package/openfeature.d.ts +1 -0
  56. package/openfeature.js +4 -0
  57. package/package.json +15 -8
  58. package/packages/datadog-instrumentations/src/ai.js +37 -26
  59. package/packages/datadog-instrumentations/src/child_process.js +1 -1
  60. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
  61. package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
  62. package/packages/datadog-instrumentations/src/cucumber.js +24 -10
  63. package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
  64. package/packages/datadog-instrumentations/src/express.js +20 -2
  65. package/packages/datadog-instrumentations/src/fastify.js +7 -11
  66. package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
  67. package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
  68. package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
  69. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
  70. package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
  71. package/packages/datadog-instrumentations/src/http2/server.js +143 -17
  72. package/packages/datadog-instrumentations/src/jest.js +36 -4
  73. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  74. package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
  75. package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
  76. package/packages/datadog-instrumentations/src/mongodb.js +3 -3
  77. package/packages/datadog-instrumentations/src/mongoose.js +3 -3
  78. package/packages/datadog-instrumentations/src/mquery.js +2 -2
  79. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  80. package/packages/datadog-instrumentations/src/next.js +24 -0
  81. package/packages/datadog-instrumentations/src/nyc.js +0 -2
  82. package/packages/datadog-instrumentations/src/oracledb.js +2 -2
  83. package/packages/datadog-instrumentations/src/pg.js +2 -2
  84. package/packages/datadog-instrumentations/src/playwright.js +159 -22
  85. package/packages/datadog-instrumentations/src/process.js +3 -0
  86. package/packages/datadog-instrumentations/src/router.js +191 -106
  87. package/packages/datadog-instrumentations/src/selenium.js +52 -26
  88. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
  89. package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
  90. package/packages/datadog-instrumentations/src/ws.js +2 -1
  91. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
  92. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
  93. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
  94. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
  95. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
  96. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -24
  97. package/packages/datadog-plugin-cucumber/src/index.js +1 -1
  98. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -62
  99. package/packages/datadog-plugin-cypress/src/index.js +6 -1
  100. package/packages/datadog-plugin-cypress/src/support.js +92 -26
  101. package/packages/datadog-plugin-electron/src/ipc.js +1 -1
  102. package/packages/datadog-plugin-graphql/src/execute.js +177 -59
  103. package/packages/datadog-plugin-graphql/src/parse.js +22 -1
  104. package/packages/datadog-plugin-graphql/src/request.js +32 -1
  105. package/packages/datadog-plugin-graphql/src/utils.js +42 -0
  106. package/packages/datadog-plugin-graphql/src/validate.js +15 -3
  107. package/packages/datadog-plugin-http2/src/client.js +1 -1
  108. package/packages/datadog-plugin-http2/src/server.js +38 -6
  109. package/packages/datadog-plugin-jest/src/util.js +21 -6
  110. package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
  111. package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
  112. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  113. package/packages/datadog-plugin-playwright/src/index.js +177 -64
  114. package/packages/datadog-plugin-router/src/index.js +11 -2
  115. package/packages/datadog-plugin-selenium/src/index.js +5 -36
  116. package/packages/datadog-plugin-vitest/src/index.js +4 -2
  117. package/packages/datadog-plugin-ws/src/close.js +2 -1
  118. package/packages/datadog-plugin-ws/src/producer.js +2 -1
  119. package/packages/datadog-plugin-ws/src/receiver.js +2 -1
  120. package/packages/datadog-plugin-ws/src/server.js +2 -1
  121. package/packages/dd-trace/index.electron.js +3 -0
  122. package/packages/dd-trace/index.js +2 -37
  123. package/packages/dd-trace/src/aiguard/sdk.js +1 -1
  124. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
  125. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
  126. package/packages/dd-trace/src/azure_metadata.js +2 -1
  127. package/packages/dd-trace/src/bootstrap.js +39 -0
  128. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
  129. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  130. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
  131. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
  132. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
  133. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
  137. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
  138. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +62 -7
  139. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -2
  140. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
  141. package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
  142. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  143. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
  144. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
  145. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +173 -9
  146. package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
  147. package/packages/dd-trace/src/config/generated-config-types.d.ts +20 -0
  148. package/packages/dd-trace/src/config/helper.js +1 -0
  149. package/packages/dd-trace/src/config/index.js +10 -0
  150. package/packages/dd-trace/src/config/supported-configurations.json +83 -0
  151. package/packages/dd-trace/src/constants.js +7 -0
  152. package/packages/dd-trace/src/datastreams/pathway.js +6 -4
  153. package/packages/dd-trace/src/exporter.js +2 -0
  154. package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
  155. package/packages/dd-trace/src/exporters/common/request.js +59 -30
  156. package/packages/dd-trace/src/exporters/common/url.js +15 -1
  157. package/packages/dd-trace/src/feature-registry.js +29 -0
  158. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  159. package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
  160. package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
  161. package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
  162. package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
  163. package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
  164. package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
  165. package/packages/dd-trace/src/llmobs/index.js +10 -2
  166. package/packages/dd-trace/src/llmobs/noop.js +6 -0
  167. package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
  168. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
  169. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  170. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
  171. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
  172. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
  173. package/packages/dd-trace/src/llmobs/sdk.js +17 -0
  174. package/packages/dd-trace/src/llmobs/tagger.js +79 -7
  175. package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
  176. package/packages/dd-trace/src/llmobs/util.js +32 -0
  177. package/packages/dd-trace/src/noop/proxy.js +5 -4
  178. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
  179. package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
  180. package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
  181. package/packages/dd-trace/src/openfeature/index.js +0 -2
  182. package/packages/dd-trace/src/openfeature/noop.js +1 -28
  183. package/packages/dd-trace/src/openfeature/register.js +35 -0
  184. package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
  185. package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
  186. package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
  187. package/packages/dd-trace/src/opentelemetry/span.js +5 -0
  188. package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
  189. package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
  190. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
  191. package/packages/dd-trace/src/opentracing/tracer.js +7 -1
  192. package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
  193. package/packages/dd-trace/src/plugins/util/git.js +3 -2
  194. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
  195. package/packages/dd-trace/src/plugins/util/test.js +65 -8
  196. package/packages/dd-trace/src/plugins/util/web.js +12 -0
  197. package/packages/dd-trace/src/proxy.js +99 -10
  198. package/packages/dd-trace/src/span_processor.js +5 -0
  199. package/packages/dd-trace/src/standalone/index.js +0 -36
  200. package/packages/dd-trace/src/telemetry/send-data.js +2 -2
  201. package/packages/dd-trace/src/util.js +26 -0
  202. package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
  203. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  204. package/vendor/dist/protobufjs/index.js +1 -1
  205. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  206. package/vendor/dist/shell-quote/index.js +1 -1
  207. package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
package/index.d.ts CHANGED
@@ -156,12 +156,12 @@ interface Tracer extends opentracing.Tracer {
156
156
  llmobs: tracer.llmobs.LLMObs;
157
157
 
158
158
  /**
159
- * OpenFeature Provider with Remote Config integration.
159
+ * OpenFeature Provider with agentless and Agent Remote Config delivery.
160
160
  *
161
- * Extends DatadogNodeServerProvider with Remote Config integration for dynamic flag configuration.
162
- * Enable with DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true.
161
+ * Agentless delivery is enabled by default and starts when the provider is first accessed.
163
162
  *
164
- * @env DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED
163
+ * @env DD_FEATURE_FLAGS_ENABLED
164
+ * @env DD_FEATURE_FLAGS_CONFIGURATION_SOURCE
165
165
  * @beta This feature is in preview and not ready for production use
166
166
  */
167
167
  openfeature: tracer.OpenFeatureProvider;
@@ -869,9 +869,9 @@ declare namespace tracer {
869
869
  */
870
870
  flaggingProvider?: {
871
871
  /**
872
- * Whether to enable the feature flagging provider.
873
- * Requires Remote Config to be properly configured.
874
- * Can be configured via DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED environment variable.
872
+ * Legacy feature flagging provider switch.
873
+ * When the stable Feature Flags configuration is unset, true selects Agent Remote Config and false disables
874
+ * the provider.
875
875
  *
876
876
  * @default false
877
877
  * @env DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED
@@ -1732,7 +1732,7 @@ declare namespace tracer {
1732
1732
  /**
1733
1733
  * Flagging Provider (OpenFeature-compatible).
1734
1734
  *
1735
- * Wraps @datadog/openfeature-node-server with Remote Config integration for dynamic flag configuration.
1735
+ * Wraps @datadog/openfeature-node-server with agentless and Agent Remote Config delivery.
1736
1736
  * Implements the OpenFeature Provider interface for flag evaluation.
1737
1737
  *
1738
1738
  * @beta This feature is in preview and not ready for production use
@@ -3774,6 +3774,12 @@ declare namespace tracer {
3774
3774
  */
3775
3775
  enabled: boolean,
3776
3776
 
3777
+ /**
3778
+ * Datasets & Experiments API. Requires LLM Observability to be enabled and
3779
+ * `DD_API_KEY` / `DD_APP_KEY` to be set.
3780
+ */
3781
+ experiments: Experiments,
3782
+
3777
3783
  /**
3778
3784
  * Enable LLM Observability tracing.
3779
3785
  *
@@ -3918,6 +3924,93 @@ declare namespace tracer {
3918
3924
  flush (): void
3919
3925
  }
3920
3926
 
3927
+ /**
3928
+ * A task run over each dataset record during an experiment.
3929
+ */
3930
+ type ExperimentTask = (input: any, config: Record<string, any>) => any | Promise<any>
3931
+
3932
+ /**
3933
+ * Scores a single task output. The return type selects the metric:
3934
+ * `boolean` -> boolean, `number` -> score, anything else -> categorical.
3935
+ */
3936
+ type ExperimentEvaluator = (input: any, output: any, expectedOutput: any) => any | Promise<any>
3937
+
3938
+ interface ExperimentOptions {
3939
+ name: string
3940
+ dataset: Dataset
3941
+ task: ExperimentTask
3942
+ /** Evaluators keyed by metric label. */
3943
+ evaluators?: Record<string, ExperimentEvaluator>
3944
+ description?: string
3945
+ config?: Record<string, any>
3946
+ tags?: Record<string, string>
3947
+ }
3948
+
3949
+ interface PullDatasetOptions {
3950
+ /** Wait until at least this many records are readable (absorbs write lag). */
3951
+ expectedRecordCount?: number
3952
+ /** Maximum total time to wait, in ms. Default 30000. */
3953
+ maxWaitMs?: number
3954
+ }
3955
+
3956
+ interface ExperimentResultRow {
3957
+ index: number
3958
+ spanId: string
3959
+ traceId: string
3960
+ startNs: number
3961
+ durationNs: number
3962
+ input: any
3963
+ output: any
3964
+ expectedOutput: any
3965
+ readonly isError: boolean
3966
+ errorType: string | null
3967
+ errorMessage: string | null
3968
+ evaluations: Record<string, any>
3969
+ evaluationErrors: Record<string, string>
3970
+ }
3971
+
3972
+ interface ExperimentResult {
3973
+ experimentId: string
3974
+ rows: ExperimentResultRow[]
3975
+ /** Dashboard URL for the experiment. */
3976
+ url: string
3977
+ }
3978
+
3979
+ interface DatasetPushResult {
3980
+ /** Number of records from this push that were confirmed with a record id. */
3981
+ pushedCount: number
3982
+ /** Number of records attempted in this push. */
3983
+ totalCount: number
3984
+ }
3985
+
3986
+ interface Dataset {
3987
+ addRecord (input: any, expectedOutput?: any, metadata?: Record<string, any>): Dataset
3988
+ /** Creates the dataset remotely if needed and pushes any unpushed records. */
3989
+ push (): Promise<DatasetPushResult>
3990
+ name (): string
3991
+ id (): string | null
3992
+ projectId (): string | null
3993
+ records (): Array<{ input: any, expectedOutput: any, metadata: Record<string, any> }>
3994
+ /** Dashboard URL for the dataset, or null until pushed. */
3995
+ url (): string | null
3996
+ }
3997
+
3998
+ interface Experiment {
3999
+ name (): string
4000
+ experimentId (): string | null
4001
+ url (): string | null
4002
+ run (): Promise<ExperimentResult>
4003
+ }
4004
+
4005
+ interface Experiments {
4006
+ /** Create a local dataset buffer; pushed on the first experiment run. */
4007
+ createDataset (name: string, description?: string): Dataset
4008
+ /** Pull an existing dataset (with records) by name. */
4009
+ pullDataset (name: string, options?: PullDatasetOptions): Promise<Dataset>
4010
+ /** Build an experiment to run over a dataset. */
4011
+ experiment (options: ExperimentOptions): Experiment
4012
+ }
4013
+
3921
4014
  interface LLMObservabilitySpan {
3922
4015
  /**
3923
4016
  * The span kind
@@ -4030,6 +4123,26 @@ declare namespace tracer {
4030
4123
  * Tool calls of the message
4031
4124
  */
4032
4125
  toolCalls?: ToolCall[],
4126
+
4127
+ /**
4128
+ * Audio segments attached to the message (e.g. speech input/output)
4129
+ */
4130
+ audioParts?: AudioPart[],
4131
+ }
4132
+
4133
+ /**
4134
+ * Represents an audio segment attached to an LLM chat model message.
4135
+ */
4136
+ interface AudioPart {
4137
+ /**
4138
+ * The MIME type of the audio (e.g. "audio/wav", "audio/mpeg")
4139
+ */
4140
+ mimeType: string,
4141
+
4142
+ /**
4143
+ * The audio content as a base64-encoded string
4144
+ */
4145
+ content: string,
4033
4146
  }
4034
4147
 
4035
4148
  /**
@@ -0,0 +1,3 @@
1
+ 'use strict'
2
+
3
+ module.exports = require('./packages/dd-trace/index.electron')
package/init.js CHANGED
@@ -1,5 +1,23 @@
1
1
  'use strict'
2
2
 
3
+ // In PM2 cluster mode, per-app env vars arrive as a `pm2_env`
4
+ // JSON string after --require has already run so we extract them
5
+ // manually if present.
6
+ var pm2EnvStr = process.env.pm2_env
7
+ if (typeof pm2EnvStr === 'string') {
8
+ try {
9
+ var pm2Config = JSON.parse(pm2EnvStr)
10
+ var pm2Keys = Object.keys(pm2Config)
11
+ for (var i = 0; i < pm2Keys.length; i++) {
12
+ var k = pm2Keys[i]
13
+ var v = pm2Config[k]
14
+ if (v != null) {
15
+ process.env[k] = String(v)
16
+ }
17
+ }
18
+ } catch (e) {}
19
+ }
20
+
3
21
  var guard = require('./packages/dd-trace/src/guardrails')
4
22
 
5
23
  module.exports = guard(function () {
package/initialize.mjs CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  iitmExclusionRegExp,
23
23
  load as hookLoad,
24
24
  resolve as hookResolve,
25
- } from './loader-hook.mjs'
25
+ } from './loader-hook.mjs?initialize'
26
26
 
27
27
  let hasInsertedInit = false
28
28
  const initJsUrl = new URL('init.js', import.meta.url).href
package/loader-hook.mjs CHANGED
@@ -2,24 +2,22 @@
2
2
 
3
3
  import * as Module from 'node:module'
4
4
  import { pathToFileURL } from 'node:url'
5
+ import { isMainThread } from 'node:worker_threads'
5
6
 
6
7
  import { createHook, supportsSyncHooks } from 'import-in-the-middle/create-hook.mjs'
7
- import { initialize as origInitialize, load as origLoad, resolve } from 'import-in-the-middle/hook.mjs'
8
- import regexpEscapeModule from './vendor/dist/escape-string-regexp/index.js'
9
- import hooks from './packages/datadog-instrumentations/src/helpers/hooks.js'
10
- import configHelper from './packages/dd-trace/src/config/helper.js'
8
+ import { initialize as origInitialize, load as origLoad } from 'import-in-the-middle/hook.mjs'
11
9
  import * as rewriterLoader from './packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs'
12
- import { isRelativeRequire } from './packages/datadog-instrumentations/src/helpers/shared-utils.js'
13
10
 
14
11
  // This file must support Node.js 12.0.0 syntax
15
12
 
16
13
  const { builtinModules } = Module
17
- const regexpEscape = regexpEscapeModule.default
18
14
  const require = Module.createRequire(import.meta.url)
15
+ // The query marks initialize.mjs's application-thread preload; loader workers use the full graph.
16
+ const isInitializeMainThread = isMainThread && import.meta.url.endsWith('?initialize')
19
17
  let syncImportInTheMiddleHook
20
18
 
21
- // The config helper's named exports aren't visible to ESM; destructure the default.
22
- const { getValueFromEnvSources } = configHelper
19
+ let getValueFromEnvSources
20
+ let regexpEscape
23
21
 
24
22
  // Substrings of resolved URLs that import-in-the-middle must never wrap: re-export
25
23
  // shims and internal helper graphs that break when proxied, plus iitm's own files
@@ -32,15 +30,26 @@ export const iitmExclusionRegExp = /middle|langsmith|openai\/_shims|openai\/reso
32
30
  // against a regex metacharacter entering a package name.
33
31
  const includeModuleNames = new Set()
34
32
  let moduleNameAlternation = ''
35
- for (const moduleName of Object.keys(hooks)) {
36
- // Relative hooks resolve outside node_modules and are not instrumented here.
37
- if (isRelativeRequire(moduleName)) continue
38
- includeModuleNames.add(moduleName)
39
- // iitm matches a built-in by its node: specifier too, so mirror that and
40
- // wrap `import 'node:crypto'` as well as `import 'crypto'`.
41
- if (builtinModules.includes(moduleName)) includeModuleNames.add(`node:${moduleName}`)
42
- if (moduleNameAlternation !== '') moduleNameAlternation += '|'
43
- moduleNameAlternation += regexpEscape(moduleName)
33
+
34
+ if (!isInitializeMainThread) {
35
+ const regexpEscapeModule = require('./vendor/dist/escape-string-regexp/index.js')
36
+ const hooks = require('./packages/datadog-instrumentations/src/helpers/hooks.js')
37
+ const configHelper = require('./packages/dd-trace/src/config/helper.js')
38
+ const { isRelativeRequire } = require('./packages/datadog-instrumentations/src/helpers/shared-utils.js')
39
+
40
+ regexpEscape = regexpEscapeModule.default
41
+ getValueFromEnvSources = configHelper.getValueFromEnvSources
42
+
43
+ for (const moduleName of Object.keys(hooks)) {
44
+ // Relative hooks resolve outside node_modules and are not instrumented here.
45
+ if (isRelativeRequire(moduleName)) continue
46
+ includeModuleNames.add(moduleName)
47
+ // iitm matches a built-in by its node: specifier too, so mirror that and
48
+ // wrap `import 'node:crypto'` as well as `import 'crypto'`.
49
+ if (builtinModules.includes(moduleName)) includeModuleNames.add(`node:${moduleName}`)
50
+ if (moduleNameAlternation !== '') moduleNameAlternation += '|'
51
+ moduleNameAlternation += regexpEscape(moduleName)
52
+ }
44
53
  }
45
54
 
46
55
  const nodeModulesIncludeSource = `node_modules/(?:${moduleNameAlternation})/(?!node_modules).+`
@@ -181,4 +190,5 @@ function registerSyncLoaderHooks (data = {}) {
181
190
  return true
182
191
  }
183
192
 
184
- export { initialize, load, registerSyncLoaderHooks, resolve }
193
+ export { resolve } from 'import-in-the-middle/hook.mjs'
194
+ export { initialize, load, registerSyncLoaderHooks }
@@ -0,0 +1 @@
1
+ export {};
package/openfeature.js ADDED
@@ -0,0 +1,4 @@
1
+ 'use strict'
2
+
3
+ // Static fallback for file tracers that do not recognize the optional-peer wrapper.
4
+ require('@datadog/openfeature-node-server')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.114.0",
3
+ "version": "5.116.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -12,7 +12,9 @@
12
12
  "bench:e2e:test-optimization": "node benchmark/e2e-test-optimization/benchmark-run.js",
13
13
  "dependencies:dedupe": "yarn-deduplicate yarn.lock",
14
14
  "generate:config:types": "node scripts/generate-config-types.js",
15
+ "generate:electron-package": "node scripts/generate-electron-package.js",
15
16
  "verify:config:types": "node scripts/generate-config-types.js --check",
17
+ "verify:electron-package": "node scripts/generate-electron-package.js --check",
16
18
  "generate:supported-integrations": "node scripts/generate-supported-integrations.js",
17
19
  "verify:supported-integrations": "node scripts/generate-supported-integrations.js --check",
18
20
  "type:check": "tsc --noEmit -p tsconfig.dev.json",
@@ -142,6 +144,7 @@
142
144
  "webpack.js",
143
145
  "ext/**/*",
144
146
  "index.d.ts",
147
+ "index.electron.js",
145
148
  "index.js",
146
149
  "init.js",
147
150
  "initialize.mjs",
@@ -150,7 +153,10 @@
150
153
  "LICENSE.Apache",
151
154
  "LICENSE.BSD3",
152
155
  "loader-hook.mjs",
156
+ "openfeature.d.ts",
157
+ "openfeature.js",
153
158
  "packages/*/index.js",
159
+ "packages/*/index.electron.js",
154
160
  "packages/*/lib/**/*",
155
161
  "packages/*/src/**/*",
156
162
  "packages/datadog-instrumentations/orchestrion.yml",
@@ -164,7 +170,7 @@
164
170
  ],
165
171
  "dependencies": {
166
172
  "dc-polyfill": "^0.1.11",
167
- "import-in-the-middle": "^3.3.1",
173
+ "import-in-the-middle": "^3.3.2",
168
174
  "opentracing": ">=0.14.7"
169
175
  },
170
176
  "optionalDependencies": {
@@ -184,7 +190,7 @@
184
190
  "@actions/github": "^9.1.1",
185
191
  "@babel/helpers": "^8.0.0",
186
192
  "@eslint/eslintrc": "^3.3.5",
187
- "@eslint/js": "^9.39.2",
193
+ "@eslint/js": "^10.0.1",
188
194
  "@msgpack/msgpack": "^3.1.3",
189
195
  "@openfeature/core": "^1.11.0",
190
196
  "@openfeature/server-sdk": "~1.22.0",
@@ -192,21 +198,22 @@
192
198
  "@types/mocha": "^10.0.10",
193
199
  "@types/node": "^18.19.106",
194
200
  "@types/sinon": "^22.0.0",
201
+ "@vercel/nft": "^0.29.4",
195
202
  "axios": "^1.18.1",
196
203
  "benchmark": "^2.1.4",
197
204
  "body-parser": "^2.3.0",
198
205
  "bun": "1.3.14",
199
- "c8": "^11.0.0",
206
+ "c8": "^12.0.0",
200
207
  "codeowners-audit": "^2.9.0",
201
- "eslint": "^9.39.2",
208
+ "eslint": "^10.5.0",
202
209
  "eslint-plugin-cypress": "^6.4.2",
203
- "eslint-plugin-import": "^2.32.0",
210
+ "eslint-plugin-import-x": "^4.16.2",
204
211
  "eslint-plugin-jsdoc": "^63.0.12",
205
212
  "eslint-plugin-mocha": "^11.3.0",
206
213
  "eslint-plugin-n": "^18.2.1",
207
214
  "eslint-plugin-promise": "^7.3.0",
208
- "eslint-plugin-sonarjs": "^4.1.0",
209
- "eslint-plugin-unicorn": "^64.0.0",
215
+ "eslint-plugin-sonarjs": "^4.2.0",
216
+ "eslint-plugin-unicorn": "^68.0.0",
210
217
  "express": "^5.1.0",
211
218
  "glob": "^10.4.5",
212
219
  "globals": "^17.7.0",
@@ -127,7 +127,7 @@ function wrapTracer (tracer) {
127
127
  return function (...args) {
128
128
  const name = args[0]
129
129
  const options = args.length > 2 ? (args[1] ?? {}) : {} // startActiveSpan(name, fn)
130
- const cb = args[args.length - 1]
130
+ const cb = args.at(-1)
131
131
 
132
132
  const ctx = {
133
133
  name,
@@ -136,33 +136,38 @@ function wrapTracer (tracer) {
136
136
 
137
137
  args[args.length - 1] = shimmer.wrapFunction(cb, function (originalCb) {
138
138
  return function (span) {
139
- // the below is necessary in the case that the span is vercel ai's noopSpan.
140
- // while we don't want to patch the noopSpan more than once, we do want to treat each as a
141
- // fresh instance. However, this is really not necessary for non-noop spans, but not sure
142
- // how to differentiate.
143
- const freshSpan = Object.create(span) // TODO: does this cause memory leaks?
144
-
145
- shimmer.wrap(freshSpan, 'end', function (spanEnd) {
146
- return function (...args) {
147
- vercelAiTracingChannel.asyncEnd.publish(ctx)
148
- return spanEnd.apply(this, args)
149
- }
150
- })
151
-
152
- shimmer.wrap(freshSpan, 'setAttributes', function (setAttributes) {
153
- return function (attributes) {
139
+ // A plain delegating wrapper is used instead of Object.create(span) because
140
+ // Object.create (and Proxy) cannot cross private-field brand checks any span
141
+ // method that reads a private field (e.g. BridgeSpanBase#statusCode) would throw
142
+ // "Cannot read private member" on a prototype clone. Every method here calls
143
+ // through to the real span instance so private fields always resolve correctly.
144
+ const freshSpan = {
145
+ spanContext () { return span.spanContext() },
146
+ setAttribute (key, value) { span.setAttribute(key, value); return freshSpan },
147
+ setAttributes (attributes) {
154
148
  vercelAiSpanSetAttributesChannel.publish({ ctx, attributes })
155
- return setAttributes.apply(this, arguments)
156
- }
157
- })
158
-
159
- shimmer.wrap(freshSpan, 'recordException', function (recordException) {
160
- return function (exception) {
149
+ span.setAttributes(attributes)
150
+ return freshSpan
151
+ },
152
+ addEvent (name, attributesOrStartTime, startTime) {
153
+ span.addEvent(name, attributesOrStartTime, startTime)
154
+ return freshSpan
155
+ },
156
+ addLink (link, attrs) { span.addLink(link, attrs); return freshSpan },
157
+ addLinks (links) { span.addLinks(links); return freshSpan },
158
+ setStatus (status) { span.setStatus(status); return freshSpan },
159
+ updateName (spanName) { span.updateName(spanName); return freshSpan },
160
+ isRecording () { return span.isRecording() },
161
+ recordException (exception, timeInput) {
161
162
  ctx.error = exception
162
163
  vercelAiTracingChannel.error.publish(ctx)
163
- return recordException.apply(this, arguments)
164
- }
165
- })
164
+ span.recordException(exception, timeInput)
165
+ },
166
+ end (...endArgs) {
167
+ vercelAiTracingChannel.asyncEnd.publish(ctx)
168
+ span.end(...endArgs)
169
+ },
170
+ }
166
171
 
167
172
  return originalCb.call(this, freshSpan)
168
173
  }
@@ -225,7 +230,13 @@ for (const hook of getHooks('ai')) {
225
230
  // generateObject, streamObject)
226
231
  tracingChannel('orchestrion:ai:resolveLanguageModel').subscribe({
227
232
  end (ctx) {
228
- wrapModelWithLifecycle(ctx.result)
233
+ const model = ctx.arguments[0]
234
+ if (typeof model !== 'string' && model !== ctx.result) {
235
+ wrapModelWithLifecycle(model)
236
+ wrappedModels.add(ctx.result)
237
+ } else {
238
+ wrapModelWithLifecycle(ctx.result)
239
+ }
229
240
  },
230
241
  })
231
242
 
@@ -190,7 +190,7 @@ function wrapChildProcessAsyncMethod (ChildProcess, shell = false) {
190
190
  const error = context.abortController.signal.reason || new Error('Aborted')
191
191
  childProcess.emit('error', error)
192
192
 
193
- const cb = context.callArgs[context.callArgs.length - 1]
193
+ const cb = context.callArgs.at(-1)
194
194
  if (typeof cb === 'function') {
195
195
  cb(error)
196
196
  }
@@ -496,7 +496,7 @@ function finishStream (chunks, ctx, error) {
496
496
 
497
497
  let processError
498
498
  if (chunks.length > 0) {
499
- const lastChunk = chunks[chunks.length - 1]
499
+ const lastChunk = chunks.at(-1)
500
500
  if (lastChunk?.type === 'result') ctx.output = lastChunk.result
501
501
 
502
502
  try {
@@ -9,11 +9,17 @@ const appRequire = createRequire(path.join(process.cwd(), 'package.json'))
9
9
 
10
10
  try {
11
11
  // Cucumber v13 parallel workers start from an ESM worker.mjs entrypoint, which
12
- // statically imports the internal runtime Worker before it runs support-code
12
+ // statically imports the internal runtime Worker/Executor before it runs support-code
13
13
  // requireModules. The regular module hook does not patch that internal worker
14
- // import, so this preload is injected into requireModules to patch the cached Worker
14
+ // import, so this preload is injected into requireModules to patch the cached class
15
15
  // prototype before Cucumber constructs the worker instance.
16
- patchCucumberWorkerRunTestCase(appRequire('@cucumber/cucumber/lib/runtime/worker'), true)
16
+ let runtimeExecutorPackage
17
+ try {
18
+ runtimeExecutorPackage = appRequire('@cucumber/cucumber/lib/runtime/executor')
19
+ } catch {
20
+ runtimeExecutorPackage = appRequire('@cucumber/cucumber/lib/runtime/worker')
21
+ }
22
+ patchCucumberWorkerRunTestCase(runtimeExecutorPackage, true)
17
23
  } catch {
18
24
  // Ignore preload failures so cucumber can keep running if its internals change.
19
25
  }
@@ -180,7 +180,7 @@ function getSuiteStatusFromTestStatuses (testStatuses) {
180
180
 
181
181
  function getConfiguredEfdRetryCount () {
182
182
  const maxSlowTestRetryCount = getMaxEfdRetryCount(earlyFlakeDetectionSlowTestRetries)
183
- return maxSlowTestRetryCount || earlyFlakeDetectionNumRetries
183
+ return maxSlowTestRetryCount ?? earlyFlakeDetectionNumRetries
184
184
  }
185
185
 
186
186
  function publishWorkerEfdRetryCount (pickle, retryCount) {
@@ -1036,7 +1036,9 @@ function testCaseHook (TestCaseRunner, version) {
1036
1036
  // Valid for old and new cucumber versions
1037
1037
  function getCucumberOptions (adapterOrCoordinator) {
1038
1038
  if (adapterOrCoordinator.adapter) {
1039
- return adapterOrCoordinator.adapter.worker?.options || adapterOrCoordinator.adapter.options
1039
+ return adapterOrCoordinator.adapter.worker?.options ||
1040
+ adapterOrCoordinator.adapter.executor?.options ||
1041
+ adapterOrCoordinator.adapter.options
1040
1042
  }
1041
1043
  return adapterOrCoordinator.options
1042
1044
  }
@@ -1178,7 +1180,8 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
1178
1180
  itrSkippedSuitesCh.publish({ skippedSuites, frameworkVersion })
1179
1181
  }
1180
1182
 
1181
- const success = await start.apply(this, arguments)
1183
+ const result = await start.apply(this, arguments)
1184
+ const success = satisfies(frameworkVersion, '>=13.1.0') ? result.success : result
1182
1185
 
1183
1186
  let untestedCoverage
1184
1187
  if (getCodeCoverageCh.hasSubscribers) {
@@ -1228,7 +1231,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
1228
1231
  logTestOptimizationSummary({ attemptToFixExecutions })
1229
1232
  loggedAttemptToFixTests.clear()
1230
1233
  eventDataCollector = null
1231
- return success
1234
+ return result
1232
1235
  }
1233
1236
  }
1234
1237
 
@@ -1433,13 +1436,14 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
1433
1436
  }
1434
1437
  }
1435
1438
 
1436
- function patchCucumberWorkerRunTestCase (workerPackage, isWorker) {
1437
- const workerPrototype = workerPackage?.Worker?.prototype
1438
- if (!workerPrototype || patchedCucumberWorkers.has(workerPrototype)) return
1439
+ function patchCucumberWorkerRunTestCase (runtimeExecutorPackage, isWorker) {
1440
+ const runtimeExecutorPrototype =
1441
+ runtimeExecutorPackage?.Worker?.prototype || runtimeExecutorPackage?.Executor?.prototype
1442
+ if (!runtimeExecutorPrototype || patchedCucumberWorkers.has(runtimeExecutorPrototype)) return
1439
1443
 
1440
- patchedCucumberWorkers.add(workerPrototype)
1444
+ patchedCucumberWorkers.add(runtimeExecutorPrototype)
1441
1445
  shimmer.wrap(
1442
- workerPrototype,
1446
+ runtimeExecutorPrototype,
1443
1447
  'runTestCase',
1444
1448
  runTestCase => getWrappedRunTestCase(runTestCase, true, isWorker)
1445
1449
  )
@@ -1571,15 +1575,25 @@ addHook({
1571
1575
  // `getWrappedRunTestCase` does two things:
1572
1576
  // - generates suite start and finish events in the main process,
1573
1577
  // - handles EFD in both the main process and the worker process.
1578
+ // Shimmer is required because this wrapper may invoke the original test case multiple times and mutate runtime options.
1574
1579
  addHook({
1575
1580
  name: '@cucumber/cucumber',
1576
- versions: ['>=11.0.0'],
1581
+ versions: ['>=11.0.0 <13.2.0'],
1577
1582
  file: 'lib/runtime/worker.js',
1578
1583
  }, (workerPackage) => {
1579
1584
  patchCucumberWorkerRunTestCase(workerPackage, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
1580
1585
  return workerPackage
1581
1586
  })
1582
1587
 
1588
+ addHook({
1589
+ name: '@cucumber/cucumber',
1590
+ versions: ['>=13.2.0'],
1591
+ file: 'lib/runtime/executor.js',
1592
+ }, (executorPackage) => {
1593
+ patchCucumberWorkerRunTestCase(executorPackage, !!getEnvironmentVariable('CUCUMBER_WORKER_ID'))
1594
+ return executorPackage
1595
+ })
1596
+
1583
1597
  // `getWrappedStart` generates session start and finish events
1584
1598
  addHook({
1585
1599
  name: '@cucumber/cucumber',