dd-trace 5.101.0 → 5.103.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 (235) hide show
  1. package/ext/exporters.js +1 -0
  2. package/package.json +20 -17
  3. package/packages/datadog-esbuild/src/utils.js +2 -2
  4. package/packages/datadog-instrumentations/src/aerospike.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +9 -9
  6. package/packages/datadog-instrumentations/src/amqplib.js +6 -7
  7. package/packages/datadog-instrumentations/src/anthropic.js +10 -10
  8. package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
  9. package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
  10. package/packages/datadog-instrumentations/src/avsc.js +6 -6
  11. package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
  12. package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
  13. package/packages/datadog-instrumentations/src/bluebird.js +2 -2
  14. package/packages/datadog-instrumentations/src/body-parser.js +2 -2
  15. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  16. package/packages/datadog-instrumentations/src/child_process.js +12 -12
  17. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +41 -24
  18. package/packages/datadog-instrumentations/src/connect.js +7 -7
  19. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  20. package/packages/datadog-instrumentations/src/cookie.js +2 -2
  21. package/packages/datadog-instrumentations/src/couchbase.js +73 -238
  22. package/packages/datadog-instrumentations/src/crypto.js +4 -4
  23. package/packages/datadog-instrumentations/src/cucumber.js +78 -17
  24. package/packages/datadog-instrumentations/src/dns.js +0 -3
  25. package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
  26. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  27. package/packages/datadog-instrumentations/src/electron.js +240 -0
  28. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
  29. package/packages/datadog-instrumentations/src/express-session.js +4 -4
  30. package/packages/datadog-instrumentations/src/express.js +10 -11
  31. package/packages/datadog-instrumentations/src/fastify.js +2 -2
  32. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  33. package/packages/datadog-instrumentations/src/fs.js +14 -14
  34. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
  35. package/packages/datadog-instrumentations/src/google-genai.js +4 -4
  36. package/packages/datadog-instrumentations/src/graphql.js +13 -12
  37. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  38. package/packages/datadog-instrumentations/src/hapi.js +2 -2
  39. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +9 -9
  40. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  41. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  42. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  43. package/packages/datadog-instrumentations/src/helpers/kafka.js +41 -0
  44. package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
  45. package/packages/datadog-instrumentations/src/hono.js +2 -2
  46. package/packages/datadog-instrumentations/src/http/client.js +6 -6
  47. package/packages/datadog-instrumentations/src/http/server.js +9 -9
  48. package/packages/datadog-instrumentations/src/ioredis.js +16 -12
  49. package/packages/datadog-instrumentations/src/jest.js +382 -81
  50. package/packages/datadog-instrumentations/src/kafkajs.js +165 -174
  51. package/packages/datadog-instrumentations/src/knex.js +17 -17
  52. package/packages/datadog-instrumentations/src/koa.js +12 -12
  53. package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
  54. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  55. package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
  56. package/packages/datadog-instrumentations/src/lodash.js +4 -4
  57. package/packages/datadog-instrumentations/src/mariadb.js +13 -13
  58. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  59. package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
  60. package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
  61. package/packages/datadog-instrumentations/src/mocha/main.js +85 -11
  62. package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
  63. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
  64. package/packages/datadog-instrumentations/src/mongodb-core.js +42 -30
  65. package/packages/datadog-instrumentations/src/mongodb.js +5 -5
  66. package/packages/datadog-instrumentations/src/mongoose.js +21 -21
  67. package/packages/datadog-instrumentations/src/mquery.js +5 -5
  68. package/packages/datadog-instrumentations/src/multer.js +4 -4
  69. package/packages/datadog-instrumentations/src/mysql.js +16 -16
  70. package/packages/datadog-instrumentations/src/mysql2.js +4 -4
  71. package/packages/datadog-instrumentations/src/net.js +14 -8
  72. package/packages/datadog-instrumentations/src/nyc.js +5 -5
  73. package/packages/datadog-instrumentations/src/openai.js +19 -19
  74. package/packages/datadog-instrumentations/src/oracledb.js +6 -6
  75. package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
  76. package/packages/datadog-instrumentations/src/pg.js +39 -25
  77. package/packages/datadog-instrumentations/src/pino.js +6 -10
  78. package/packages/datadog-instrumentations/src/playwright.js +445 -68
  79. package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
  80. package/packages/datadog-instrumentations/src/redis.js +20 -12
  81. package/packages/datadog-instrumentations/src/restify.js +2 -2
  82. package/packages/datadog-instrumentations/src/router.js +12 -12
  83. package/packages/datadog-instrumentations/src/stripe.js +12 -12
  84. package/packages/datadog-instrumentations/src/vitest.js +107 -26
  85. package/packages/datadog-instrumentations/src/winston.js +4 -4
  86. package/packages/datadog-instrumentations/src/ws.js +7 -7
  87. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  88. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -28
  89. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  90. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +20 -13
  91. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +46 -36
  92. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +34 -23
  93. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  94. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  95. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +14 -15
  96. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +74 -55
  97. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +20 -18
  98. package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
  99. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
  100. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  101. package/packages/datadog-plugin-cucumber/src/index.js +5 -0
  102. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +215 -26
  103. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  104. package/packages/datadog-plugin-electron/src/index.js +17 -0
  105. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  106. package/packages/datadog-plugin-electron/src/net.js +82 -0
  107. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
  108. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  109. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
  110. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  111. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  112. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  113. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  114. package/packages/datadog-plugin-graphql/src/utils.js +29 -0
  115. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  116. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  117. package/packages/datadog-plugin-http/src/client.js +3 -7
  118. package/packages/datadog-plugin-jest/src/index.js +92 -50
  119. package/packages/datadog-plugin-jest/src/util.js +1 -2
  120. package/packages/datadog-plugin-mocha/src/index.js +5 -0
  121. package/packages/datadog-plugin-mongodb-core/src/index.js +36 -69
  122. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  123. package/packages/datadog-plugin-openai/src/services.js +2 -1
  124. package/packages/datadog-plugin-openai/src/tracing.js +12 -23
  125. package/packages/datadog-plugin-pg/src/index.js +3 -3
  126. package/packages/datadog-plugin-playwright/src/index.js +5 -1
  127. package/packages/datadog-plugin-redis/src/index.js +18 -23
  128. package/packages/datadog-plugin-vitest/src/index.js +8 -1
  129. package/packages/datadog-shimmer/src/shimmer.js +7 -1
  130. package/packages/dd-trace/src/aiguard/index.js +3 -1
  131. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  132. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  133. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
  134. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
  135. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
  136. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
  137. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +4 -4
  138. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
  139. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
  140. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
  141. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
  142. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  143. package/packages/dd-trace/src/appsec/index.js +21 -24
  144. package/packages/dd-trace/src/appsec/reporter.js +3 -1
  145. package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
  146. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
  147. package/packages/dd-trace/src/azure_metadata.js +17 -6
  148. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  149. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  150. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  151. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  152. package/packages/dd-trace/src/config/defaults.js +3 -14
  153. package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -1
  154. package/packages/dd-trace/src/config/git_properties.js +2 -2
  155. package/packages/dd-trace/src/config/helper.js +4 -0
  156. package/packages/dd-trace/src/config/index.js +2 -2
  157. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  158. package/packages/dd-trace/src/config/parsers.js +7 -1
  159. package/packages/dd-trace/src/config/supported-configurations.json +51 -38
  160. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  161. package/packages/dd-trace/src/datastreams/index.js +2 -1
  162. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  163. package/packages/dd-trace/src/datastreams/processor.js +3 -4
  164. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  165. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
  166. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  167. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  168. package/packages/dd-trace/src/debugger/index.js +7 -7
  169. package/packages/dd-trace/src/dogstatsd.js +2 -2
  170. package/packages/dd-trace/src/encode/0.4.js +748 -232
  171. package/packages/dd-trace/src/encode/0.5.js +47 -10
  172. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  173. package/packages/dd-trace/src/exporter.js +2 -0
  174. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  175. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  176. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  177. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  178. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  179. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  180. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  181. package/packages/dd-trace/src/git_metadata.js +10 -8
  182. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  183. package/packages/dd-trace/src/lambda/index.js +62 -14
  184. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  185. package/packages/dd-trace/src/llmobs/index.js +13 -2
  186. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
  187. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  188. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
  189. package/packages/dd-trace/src/llmobs/sdk.js +24 -26
  190. package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
  191. package/packages/dd-trace/src/llmobs/util.js +1 -0
  192. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  193. package/packages/dd-trace/src/msgpack/chunk.js +6 -3
  194. package/packages/dd-trace/src/openfeature/noop.js +40 -36
  195. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  196. package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
  197. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  198. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
  199. package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
  200. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  201. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
  202. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  203. package/packages/dd-trace/src/plugins/ci_plugin.js +49 -4
  204. package/packages/dd-trace/src/plugins/database.js +54 -12
  205. package/packages/dd-trace/src/plugins/index.js +1 -0
  206. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  207. package/packages/dd-trace/src/plugins/util/ci.js +9 -9
  208. package/packages/dd-trace/src/plugins/util/git-cache.js +23 -23
  209. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  210. package/packages/dd-trace/src/plugins/util/test.js +56 -12
  211. package/packages/dd-trace/src/plugins/util/url.js +1 -3
  212. package/packages/dd-trace/src/plugins/util/user-provided-git.js +18 -16
  213. package/packages/dd-trace/src/plugins/util/web.js +5 -7
  214. package/packages/dd-trace/src/priority_sampler.js +1 -1
  215. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  216. package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
  217. package/packages/dd-trace/src/profiling/profilers/wall.js +5 -6
  218. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  219. package/packages/dd-trace/src/rate_limiter.js +1 -1
  220. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  221. package/packages/dd-trace/src/ritm.js +2 -1
  222. package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
  223. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  224. package/packages/dd-trace/src/scope.js +3 -10
  225. package/packages/dd-trace/src/serverless.js +6 -6
  226. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +27 -1
  227. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  228. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +24 -0
  229. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  230. package/packages/dd-trace/src/span_stats.js +1 -1
  231. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  232. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  233. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  234. package/packages/dd-trace/src/tracer.js +7 -7
  235. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
@@ -560,9 +560,8 @@ function createResponseResponseExtraction (tags, body, openaiStore) {
560
560
 
561
561
  // The server almost always responds with JSON
562
562
  function coerceResponseBody (body, methodName) {
563
- switch (methodName) {
564
- case 'downloadFile':
565
- return { file: body }
563
+ if (methodName === 'downloadFile') {
564
+ return { file: body }
566
565
  }
567
566
 
568
567
  const type = typeof body
@@ -574,9 +573,8 @@ function coerceResponseBody (body, methodName) {
574
573
  }
575
574
  } else if (type === 'object') {
576
575
  return body
577
- } else {
578
- return {}
579
576
  }
577
+ return {}
580
578
  }
581
579
 
582
580
  // This method is used to replace a dynamic URL segment with an asterisk
@@ -594,28 +592,19 @@ function lookupOperationEndpoint (operationId, methodName, url) {
594
592
  return '/v1/files/*/content'
595
593
 
596
594
  case 'retrieveFineTune':
597
- switch (methodName) {
598
- case 'fine_tuning.jobs.retrieve':
599
- return '/v1/fine_tuning/jobs/*'
600
- default:
601
- return '/v1/fine-tunes/*'
602
- }
595
+ return methodName === 'fine_tuning.jobs.retrieve'
596
+ ? '/v1/fine_tuning/jobs/*'
597
+ : '/v1/fine-tunes/*'
603
598
 
604
599
  case 'listFineTuneEvents':
605
- switch (methodName) {
606
- case 'fine_tuning.jobs.listEvents':
607
- return '/v1/fine_tuning/jobs/*/events'
608
- default:
609
- return '/v1/fine-tunes/*/events'
610
- }
600
+ return methodName === 'fine_tuning.jobs.listEvents'
601
+ ? '/v1/fine_tuning/jobs/*/events'
602
+ : '/v1/fine-tunes/*/events'
611
603
 
612
604
  case 'cancelFineTune':
613
- switch (methodName) {
614
- case 'fine_tuning.jobs.cancel':
615
- return '/v1/fine_tuning/jobs/*/cancel'
616
- default:
617
- return '/v1/fine-tunes/*/cancel'
618
- }
605
+ return methodName === 'fine_tuning.jobs.cancel'
606
+ ? '/v1/fine_tuning/jobs/*/cancel'
607
+ : '/v1/fine-tunes/*/cancel'
619
608
  }
620
609
 
621
610
  return url
@@ -9,9 +9,9 @@ class PGPlugin extends DatabasePlugin {
9
9
  static system = 'postgres'
10
10
 
11
11
  bindStart (ctx) {
12
- const { params = {}, query, processId, stream } = ctx
12
+ const { params = {}, query, originalText, processId, stream } = ctx
13
13
  const service = this.serviceName({ pluginConfig: this.config, params })
14
- const originalStatement = this.maybeTruncate(query.text)
14
+ const originalStatement = this.maybeTruncate(originalText)
15
15
 
16
16
  const span = this.startSpan(this.operationName(), {
17
17
  service,
@@ -32,7 +32,7 @@ class PGPlugin extends DatabasePlugin {
32
32
  span.setTag('db.stream', 1)
33
33
  }
34
34
 
35
- query.__ddInjectableQuery = this.injectDbmQuery(span, query.text, service.name, !!query.name)
35
+ ctx.injected = this.injectDbmQuery(span, originalText, service.name, !!query.name)
36
36
 
37
37
  return ctx.currentStore
38
38
  }
@@ -321,6 +321,7 @@ class PlaywrightPlugin extends CiPlugin {
321
321
  isAtrRetry,
322
322
  isModified,
323
323
  finalStatus,
324
+ earlyFlakeAbortReason,
324
325
  onDone,
325
326
  }) => {
326
327
  if (!span) return
@@ -384,6 +385,9 @@ class PlaywrightPlugin extends CiPlugin {
384
385
  if (finalStatus) {
385
386
  span.setTag(TEST_FINAL_STATUS, finalStatus)
386
387
  }
388
+ if (earlyFlakeAbortReason) {
389
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
390
+ }
387
391
  for (const step of steps) {
388
392
  const stepStartTime = step.startTime.getTime()
389
393
  const stepSpan = this.tracer.startSpan('playwright.step', {
@@ -491,7 +495,7 @@ class PlaywrightPlugin extends CiPlugin {
491
495
  [TEST_SOURCE_START]: testSourceLine,
492
496
  }
493
497
  if (testSourceFile) {
494
- extraTags[TEST_SOURCE_FILE] = testSourceFile || testSuite
498
+ extraTags[TEST_SOURCE_FILE] = testSourceFile
495
499
  }
496
500
  if (browserName) {
497
501
  // Added as parameter too because it should affect the test fingerprint
@@ -4,6 +4,9 @@ const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
4
  const CachePlugin = require('../../dd-trace/src/plugins/cache')
5
5
  const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
6
6
 
7
+ const MAX_ARG_LENGTH = 100
8
+ const MAX_COMMAND_LENGTH = 1000
9
+
7
10
  class RedisPlugin extends CachePlugin {
8
11
  static id = 'redis'
9
12
  static system = 'redis'
@@ -14,7 +17,7 @@ class RedisPlugin extends CachePlugin {
14
17
  }
15
18
 
16
19
  bindStart (ctx) {
17
- const { db, command, args, connectionOptions, connectionName } = ctx
20
+ const { db, command, args, argsStartIndex, connectionOptions, connectionName } = ctx
18
21
 
19
22
  const resource = command
20
23
  const normalizedCommand = command.toUpperCase()
@@ -29,7 +32,7 @@ class RedisPlugin extends CachePlugin {
29
32
  meta: {
30
33
  'db.type': this._spanType,
31
34
  'db.name': db || '0',
32
- [`${this._spanType}.raw_command`]: formatCommand(normalizedCommand, args),
35
+ [`${this._spanType}.raw_command`]: formatCommand(normalizedCommand, args, argsStartIndex),
33
36
  'out.host': connectionOptions.host,
34
37
  [CLIENT_PORT_KEY]: connectionOptions.port,
35
38
  },
@@ -43,36 +46,28 @@ class RedisPlugin extends CachePlugin {
43
46
  }
44
47
  }
45
48
 
46
- function formatCommand (command, args) {
49
+ function formatCommand (command, args, argsStartIndex = 0) {
47
50
  if (!args || command === 'AUTH') return command
48
51
 
49
- for (let i = 0, l = args.length; i < l; i++) {
50
- if (typeof args[i] === 'function') continue
51
-
52
- command = `${command} ${formatArg(args[i])}`
52
+ let result = command
53
+ for (let i = argsStartIndex, l = args.length; i < l; i++) {
54
+ const arg = args[i]
55
+ if (typeof arg === 'function') continue
53
56
 
54
- if (command.length > 1000) return trim(command, 1000)
57
+ result = `${result} ${formatArg(arg)}`
58
+ if (result.length > MAX_COMMAND_LENGTH) return result.slice(0, MAX_COMMAND_LENGTH - 3) + '...'
55
59
  }
56
60
 
57
- return command
61
+ return result
58
62
  }
59
63
 
60
64
  function formatArg (arg) {
61
- switch (typeof arg) {
62
- case 'string':
63
- case 'number':
64
- return trim(String(arg), 100)
65
- default:
66
- return '?'
67
- }
68
- }
69
-
70
- function trim (str, maxlen) {
71
- if (str.length > maxlen) {
72
- str = str.slice(0, maxlen - 3) + '...'
65
+ if (typeof arg === 'string') {
66
+ return arg.length > MAX_ARG_LENGTH ? arg.slice(0, MAX_ARG_LENGTH - 3) + '...' : arg
73
67
  }
74
-
75
- return str
68
+ // Number stringification is bounded (~23 chars max), so it never hits MAX_ARG_LENGTH.
69
+ if (typeof arg === 'number') return String(arg)
70
+ return '?'
76
71
  }
77
72
 
78
73
  function normalizeConfig (config) {
@@ -213,13 +213,16 @@ class VitestPlugin extends CiPlugin {
213
213
  return ctx.currentStore
214
214
  })
215
215
 
216
- this.addSub('ci:vitest:test:pass', ({ span, task, finalStatus }) => {
216
+ this.addSub('ci:vitest:test:pass', ({ span, task, finalStatus, earlyFlakeAbortReason }) => {
217
217
  if (span) {
218
218
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', this.getTestTelemetryTags(span))
219
219
  span.setTag(TEST_STATUS, 'pass')
220
220
  if (finalStatus) {
221
221
  span.setTag(TEST_FINAL_STATUS, finalStatus)
222
222
  }
223
+ if (earlyFlakeAbortReason) {
224
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
225
+ }
223
226
  span.finish(this.taskToFinishTime.get(task))
224
227
  finishAllTraceSpans(span)
225
228
  }
@@ -234,6 +237,7 @@ class VitestPlugin extends CiPlugin {
234
237
  hasFailedAllRetries,
235
238
  attemptToFixFailed,
236
239
  finalStatus,
240
+ earlyFlakeAbortReason,
237
241
  }) => {
238
242
  if (!span) {
239
243
  return
@@ -262,6 +266,9 @@ class VitestPlugin extends CiPlugin {
262
266
  if (finalStatus) {
263
267
  span.setTag(TEST_FINAL_STATUS, finalStatus)
264
268
  }
269
+ if (earlyFlakeAbortReason) {
270
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
271
+ }
265
272
  if (duration) {
266
273
  span.finish(span._startTime + duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION) // milliseconds
267
274
  } else {
@@ -267,7 +267,13 @@ function assertMethod (target, name, method) {
267
267
  * @throws {Error} If the target is a class constructor.
268
268
  */
269
269
  function assertNotClass (target) {
270
- if (Function.prototype.toString.call(target).startsWith('class')) {
270
+ // Class constructors have a non-writable `prototype` property; functions have a
271
+ // writable one and arrows / async / method-shorthand have none at all. The
272
+ // `'prototype' in target` gate skips the descriptor lookup for the no-prototype
273
+ // shapes; the `in` operator is cheaper than reading `target.prototype` since
274
+ // it returns a boolean instead of materialising the prototype reference.
275
+ if ('prototype' in target &&
276
+ Object.getOwnPropertyDescriptor(target, 'prototype').writable === false) {
271
277
  throw new TypeError('Target is a native class constructor and cannot be wrapped.')
272
278
  }
273
279
  }
@@ -3,6 +3,7 @@
3
3
  const log = require('../log')
4
4
  const { incomingHttpRequestStart, aiguardChannel } = require('./channels')
5
5
  const AIGuard = require('./sdk')
6
+ const { SOURCE_AUTO, INTEGRATION_NONE } = require('./tags')
6
7
 
7
8
  let isEnabled = false
8
9
  let aiguard
@@ -51,7 +52,8 @@ function onEvaluate (ctx) {
51
52
  return
52
53
  }
53
54
 
54
- aiguard.evaluate(ctx.messages, { block })
55
+ const opts = { block, source: SOURCE_AUTO, integration: ctx.integration || INTEGRATION_NONE }
56
+ aiguard.evaluate(ctx.messages, opts)
55
57
  .then(() => {
56
58
  ctx.resolve()
57
59
  })
@@ -11,23 +11,23 @@ const { keepTrace } = require('../priority_sampler')
11
11
  const { AI_GUARD } = require('../standalone/product')
12
12
  const NoopAIGuard = require('./noop')
13
13
  const executeRequest = require('./client')
14
- const {
15
- AI_GUARD_RESOURCE,
16
- AI_GUARD_TARGET_TAG_KEY,
17
- AI_GUARD_REASON_TAG_KEY,
18
- AI_GUARD_ACTION_TAG_KEY,
19
- AI_GUARD_EVENT_TAG_KEY,
20
- AI_GUARD_BLOCKED_TAG_KEY,
21
- AI_GUARD_META_STRUCT_KEY,
22
- AI_GUARD_TOOL_NAME_TAG_KEY,
23
- AI_GUARD_TELEMETRY_REQUESTS,
24
- AI_GUARD_TELEMETRY_TRUNCATED,
25
- } = require('./tags')
14
+ const TAGS = require('./tags')
26
15
 
27
- const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
16
+ const aiguardMetrics = telemetryMetrics.manager.namespace('ai_guard')
28
17
 
29
18
  const ALLOW = 'ALLOW'
30
19
 
20
+ /**
21
+ * Reports a telemetry error
22
+ *
23
+ * @param {string} errorType - The error type constant (client_error, bad_status, bad_response)
24
+ * @param {{ source: string, integration: string }} telemetryTags - Source and integration tags
25
+ */
26
+ function reportTelemetryError (errorType, telemetryTags) {
27
+ aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, { error: true, ...telemetryTags }).inc(1)
28
+ aiguardMetrics.count(TAGS.TELEMETRY_ERROR, { type: errorType, ...telemetryTags }).inc(1)
29
+ }
30
+
31
31
  class AIGuardAbortError extends Error {
32
32
  constructor (reason, tags, tagProbs, sds) {
33
33
  super(reason)
@@ -99,10 +99,10 @@ class AIGuard extends NoopAIGuard {
99
99
  * - Clones each message so callers cannot mutate the data set in the meta struct.
100
100
  * - Truncates the list of messages and `content` fields emitting metrics accordingly.
101
101
  */
102
- #buildMessagesForMetaStruct (messages) {
102
+ #buildMessagesForMetaStruct (messages, telemetryTags) {
103
103
  const size = Math.min(messages.length, this.#maxMessagesLength)
104
104
  if (messages.length > size) {
105
- appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'messages' }).inc(1)
105
+ aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'messages', ...telemetryTags }).inc(1)
106
106
  }
107
107
  const result = []
108
108
  let contentTruncated = false
@@ -115,7 +115,7 @@ class AIGuard extends NoopAIGuard {
115
115
  result.push(message)
116
116
  }
117
117
  if (contentTruncated) {
118
- appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'content' }).inc(1)
118
+ aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'content', ...telemetryTags }).inc(1)
119
119
  }
120
120
  return result
121
121
  }
@@ -185,22 +185,23 @@ class AIGuard extends NoopAIGuard {
185
185
  if (!this.#initialized) {
186
186
  return super.evaluate(messages, opts)
187
187
  }
188
- const { block = true } = opts ?? {}
189
- return this.#tracer.trace(AI_GUARD_RESOURCE, {}, async (span) => {
188
+ const { block = true, source = TAGS.SOURCE_SDK, integration = TAGS.INTEGRATION_NONE } = opts ?? {}
189
+ const telemetryTags = { source, integration }
190
+ return this.#tracer.trace(TAGS.RESOURCE, {}, async (span) => {
190
191
  const last = messages[messages.length - 1]
191
192
  const target = this.#isToolCall(last) ? 'tool' : 'prompt'
192
- span.setTag(AI_GUARD_TARGET_TAG_KEY, target)
193
+ span.setTag(TAGS.TARGET_TAG_KEY, target)
193
194
  if (target === 'tool') {
194
195
  const name = this.#getToolName(last, messages)
195
196
  if (name) {
196
- span.setTag(AI_GUARD_TOOL_NAME_TAG_KEY, name)
197
+ span.setTag(TAGS.TOOL_NAME_TAG_KEY, name)
197
198
  }
198
199
  }
199
200
  const metaStruct = {
200
- messages: this.#buildMessagesForMetaStruct(messages),
201
+ messages: this.#buildMessagesForMetaStruct(messages, telemetryTags),
201
202
  }
202
203
  span.meta_struct = {
203
- [AI_GUARD_META_STRUCT_KEY]: metaStruct,
204
+ [TAGS.META_STRUCT_KEY]: metaStruct,
204
205
  }
205
206
  const rootSpan = span.context()?._trace?.started?.[0]
206
207
  if (rootSpan) {
@@ -208,7 +209,7 @@ class AIGuard extends NoopAIGuard {
208
209
  // keepTrace must be called before executeRequest so the sampling decision
209
210
  // is propagated correctly to outgoing HTTP client calls.
210
211
  keepTrace(rootSpan, AI_GUARD)
211
- rootSpan.setTag(AI_GUARD_EVENT_TAG_KEY, 'true')
212
+ rootSpan.setTag(TAGS.EVENT_TAG_KEY, 'true')
212
213
  }
213
214
  let response
214
215
  try {
@@ -224,18 +225,18 @@ class AIGuard extends NoopAIGuard {
224
225
  payload,
225
226
  { url: this.#evaluateUrl, headers: this.#headers, timeout: this.#timeout })
226
227
  } catch (e) {
227
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
228
+ reportTelemetryError(TAGS.ERROR_TYPE_CLIENT, telemetryTags)
228
229
  throw new AIGuardClientError(`Unexpected error calling AI Guard service: ${e.message}`, { cause: e })
229
230
  }
230
231
  if (response.status !== 200) {
231
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
232
+ reportTelemetryError(TAGS.ERROR_TYPE_STATUS, telemetryTags)
232
233
  throw new AIGuardClientError(
233
234
  `AI Guard service call failed, status ${response.status}`,
234
235
  { errors: response.body?.errors })
235
236
  }
236
237
  const attr = response.body?.data?.attributes
237
238
  if (!attr?.action) {
238
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
239
+ reportTelemetryError(TAGS.ERROR_TYPE_RESPONSE, telemetryTags)
239
240
  throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}`)
240
241
  }
241
242
  const action = attr.action
@@ -254,13 +255,18 @@ class AIGuard extends NoopAIGuard {
254
255
  }
255
256
  const blockingEnabled = attr.is_blocking_enabled ?? false
256
257
  const shouldBlock = block && blockingEnabled && action !== ALLOW
257
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { action, error: false, block: shouldBlock }).inc(1)
258
- span.setTag(AI_GUARD_ACTION_TAG_KEY, action)
258
+ aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, {
259
+ action,
260
+ error: false,
261
+ block: shouldBlock,
262
+ ...telemetryTags,
263
+ }).inc(1)
264
+ span.setTag(TAGS.ACTION_TAG_KEY, action)
259
265
  if (reason) {
260
- span.setTag(AI_GUARD_REASON_TAG_KEY, reason)
266
+ span.setTag(TAGS.REASON_TAG_KEY, reason)
261
267
  }
262
268
  if (shouldBlock) {
263
- span.setTag(AI_GUARD_BLOCKED_TAG_KEY, 'true')
269
+ span.setTag(TAGS.BLOCKED_TAG_KEY, 'true')
264
270
  throw new AIGuardAbortError(reason, tags, tagProbabilities, sdsFindings)
265
271
  }
266
272
  return { action, reason, tags, tagProbabilities, sds: sdsFindings }
@@ -1,15 +1,24 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = {
4
- AI_GUARD_RESOURCE: 'ai_guard',
5
- AI_GUARD_TARGET_TAG_KEY: 'ai_guard.target',
6
- AI_GUARD_TOOL_NAME_TAG_KEY: 'ai_guard.tool_name',
7
- AI_GUARD_ACTION_TAG_KEY: 'ai_guard.action',
8
- AI_GUARD_REASON_TAG_KEY: 'ai_guard.reason',
9
- AI_GUARD_BLOCKED_TAG_KEY: 'ai_guard.blocked',
10
- AI_GUARD_EVENT_TAG_KEY: 'ai_guard.event',
11
- AI_GUARD_META_STRUCT_KEY: 'ai_guard',
12
-
13
- AI_GUARD_TELEMETRY_REQUESTS: 'ai_guard.requests',
14
- AI_GUARD_TELEMETRY_TRUNCATED: 'ai_guard.truncated',
4
+ RESOURCE: 'ai_guard',
5
+ TARGET_TAG_KEY: 'ai_guard.target',
6
+ TOOL_NAME_TAG_KEY: 'ai_guard.tool_name',
7
+ ACTION_TAG_KEY: 'ai_guard.action',
8
+ REASON_TAG_KEY: 'ai_guard.reason',
9
+ BLOCKED_TAG_KEY: 'ai_guard.blocked',
10
+ EVENT_TAG_KEY: 'ai_guard.event',
11
+ META_STRUCT_KEY: 'ai_guard',
12
+
13
+ TELEMETRY_REQUESTS: 'requests',
14
+ TELEMETRY_TRUNCATED: 'truncated',
15
+ TELEMETRY_ERROR: 'error',
16
+
17
+ SOURCE_SDK: 'sdk',
18
+ SOURCE_AUTO: 'auto',
19
+ INTEGRATION_NONE: 'none',
20
+
21
+ ERROR_TYPE_CLIENT: 'client_error',
22
+ ERROR_TYPE_STATUS: 'bad_status',
23
+ ERROR_TYPE_RESPONSE: 'bad_response',
15
24
  }
@@ -5,7 +5,7 @@ const { NameAndValue } = require('./hardcoded-rule-type')
5
5
  module.exports = [
6
6
  {
7
7
  id: 'hardcoded-password',
8
- regex: /(?:pwd|pswd|pass|secret)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['"\s\x60;]|$)/i,
8
+ regex: /(?:pwd|pswd|pass|secret)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['"\s\x60;]|$)/i,
9
9
  type: NameAndValue,
10
10
  },
11
11
  ]