dd-trace 5.61.0 → 5.62.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 (192) hide show
  1. package/package.json +1 -1
  2. package/packages/datadog-instrumentations/src/apollo-server.js +50 -8
  3. package/packages/datadog-instrumentations/src/aws-sdk.js +49 -60
  4. package/packages/datadog-instrumentations/src/fastify.js +61 -55
  5. package/packages/datadog-instrumentations/src/graphql.js +90 -122
  6. package/packages/datadog-instrumentations/src/http2/server.js +14 -20
  7. package/packages/datadog-instrumentations/src/microgateway-core.js +16 -15
  8. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -29
  9. package/packages/datadog-instrumentations/src/mongodb.js +9 -13
  10. package/packages/datadog-instrumentations/src/mongoose.js +25 -29
  11. package/packages/datadog-instrumentations/src/openai.js +0 -2
  12. package/packages/datadog-instrumentations/src/oracledb.js +39 -33
  13. package/packages/datadog-instrumentations/src/router.js +1 -1
  14. package/packages/datadog-plugin-aerospike/src/index.js +5 -9
  15. package/packages/datadog-plugin-amqp10/src/consumer.js +2 -2
  16. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  17. package/packages/datadog-plugin-amqp10/src/producer.js +3 -3
  18. package/packages/datadog-plugin-amqplib/src/client.js +3 -3
  19. package/packages/datadog-plugin-amqplib/src/consumer.js +2 -2
  20. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  21. package/packages/datadog-plugin-amqplib/src/producer.js +2 -2
  22. package/packages/datadog-plugin-apollo/src/gateway/execute.js +2 -4
  23. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +2 -4
  24. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  25. package/packages/datadog-plugin-apollo/src/gateway/plan.js +2 -4
  26. package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +2 -4
  27. package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -4
  28. package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -4
  29. package/packages/datadog-plugin-apollo/src/index.js +1 -1
  30. package/packages/datadog-plugin-avsc/src/index.js +2 -2
  31. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -46
  32. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -3
  33. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -3
  34. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
  35. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  36. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -3
  37. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  38. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +22 -20
  39. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  40. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  41. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -3
  42. package/packages/datadog-plugin-aws-sdk/src/services/sfn.js +1 -1
  43. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -3
  44. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +17 -15
  45. package/packages/datadog-plugin-aws-sdk/src/services/states.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  47. package/packages/datadog-plugin-azure-functions/src/index.js +5 -5
  48. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  49. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  50. package/packages/datadog-plugin-bunyan/src/index.js +3 -5
  51. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -3
  52. package/packages/datadog-plugin-child_process/src/index.js +2 -2
  53. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -3
  54. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -3
  55. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  56. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -3
  57. package/packages/datadog-plugin-connect/src/index.js +1 -3
  58. package/packages/datadog-plugin-couchbase/src/index.js +2 -2
  59. package/packages/datadog-plugin-cucumber/src/index.js +1 -3
  60. package/packages/datadog-plugin-cypress/src/index.js +1 -3
  61. package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
  62. package/packages/datadog-plugin-dns/src/index.js +1 -1
  63. package/packages/datadog-plugin-dns/src/lookup.js +2 -2
  64. package/packages/datadog-plugin-dns/src/lookup_service.js +2 -2
  65. package/packages/datadog-plugin-dns/src/resolve.js +2 -2
  66. package/packages/datadog-plugin-dns/src/reverse.js +2 -2
  67. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  68. package/packages/datadog-plugin-express/src/code_origin.js +1 -3
  69. package/packages/datadog-plugin-express/src/index.js +1 -1
  70. package/packages/datadog-plugin-express/src/tracing.js +1 -3
  71. package/packages/datadog-plugin-fastify/src/code_origin.js +1 -3
  72. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  73. package/packages/datadog-plugin-fastify/src/tracing.js +18 -3
  74. package/packages/datadog-plugin-fetch/src/index.js +2 -2
  75. package/packages/datadog-plugin-find-my-way/src/index.js +1 -3
  76. package/packages/datadog-plugin-fs/src/index.js +2 -2
  77. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -3
  78. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  79. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  80. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +2 -2
  81. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  82. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +2 -4
  83. package/packages/datadog-plugin-graphql/src/execute.js +16 -9
  84. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  85. package/packages/datadog-plugin-graphql/src/parse.js +12 -7
  86. package/packages/datadog-plugin-graphql/src/resolve.js +50 -16
  87. package/packages/datadog-plugin-graphql/src/validate.js +13 -7
  88. package/packages/datadog-plugin-grpc/src/client.js +4 -4
  89. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  90. package/packages/datadog-plugin-grpc/src/server.js +3 -3
  91. package/packages/datadog-plugin-hapi/src/index.js +1 -3
  92. package/packages/datadog-plugin-hono/src/index.js +1 -3
  93. package/packages/datadog-plugin-http/src/client.js +2 -2
  94. package/packages/datadog-plugin-http/src/index.js +1 -1
  95. package/packages/datadog-plugin-http/src/server.js +3 -7
  96. package/packages/datadog-plugin-http2/src/client.js +2 -2
  97. package/packages/datadog-plugin-http2/src/index.js +1 -1
  98. package/packages/datadog-plugin-http2/src/server.js +22 -11
  99. package/packages/datadog-plugin-ioredis/src/index.js +1 -3
  100. package/packages/datadog-plugin-iovalkey/src/index.js +2 -4
  101. package/packages/datadog-plugin-jest/src/index.js +1 -3
  102. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -2
  103. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -2
  104. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  105. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -3
  106. package/packages/datadog-plugin-koa/src/index.js +1 -3
  107. package/packages/datadog-plugin-langchain/src/index.js +2 -2
  108. package/packages/datadog-plugin-langchain/src/tracing.js +30 -48
  109. package/packages/datadog-plugin-mariadb/src/index.js +2 -2
  110. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  111. package/packages/datadog-plugin-microgateway-core/src/index.js +4 -4
  112. package/packages/datadog-plugin-mocha/src/index.js +1 -3
  113. package/packages/datadog-plugin-moleculer/src/client.js +2 -2
  114. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  115. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  116. package/packages/datadog-plugin-mongodb-core/src/index.js +9 -5
  117. package/packages/datadog-plugin-mongoose/src/index.js +20 -0
  118. package/packages/datadog-plugin-mysql/src/index.js +2 -2
  119. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  120. package/packages/datadog-plugin-net/src/index.js +1 -1
  121. package/packages/datadog-plugin-net/src/ipc.js +2 -2
  122. package/packages/datadog-plugin-net/src/tcp.js +2 -2
  123. package/packages/datadog-plugin-next/src/index.js +1 -3
  124. package/packages/datadog-plugin-nyc/src/index.js +1 -3
  125. package/packages/datadog-plugin-openai/src/index.js +1 -1
  126. package/packages/datadog-plugin-openai/src/tracing.js +7 -411
  127. package/packages/datadog-plugin-opensearch/src/index.js +1 -3
  128. package/packages/datadog-plugin-oracledb/src/index.js +9 -5
  129. package/packages/datadog-plugin-pg/src/index.js +3 -3
  130. package/packages/datadog-plugin-pino/src/index.js +3 -5
  131. package/packages/datadog-plugin-playwright/src/index.js +1 -3
  132. package/packages/datadog-plugin-prisma/src/client.js +4 -6
  133. package/packages/datadog-plugin-prisma/src/engine.js +3 -3
  134. package/packages/datadog-plugin-prisma/src/index.js +1 -1
  135. package/packages/datadog-plugin-protobufjs/src/index.js +2 -6
  136. package/packages/datadog-plugin-redis/src/index.js +2 -2
  137. package/packages/datadog-plugin-restify/src/index.js +1 -3
  138. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  139. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  140. package/packages/datadog-plugin-rhea/src/producer.js +2 -2
  141. package/packages/datadog-plugin-router/src/index.js +1 -3
  142. package/packages/datadog-plugin-selenium/src/index.js +1 -3
  143. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  144. package/packages/datadog-plugin-tedious/src/index.js +3 -3
  145. package/packages/datadog-plugin-undici/src/index.js +2 -4
  146. package/packages/datadog-plugin-vitest/src/index.js +1 -3
  147. package/packages/datadog-plugin-web/src/index.js +1 -3
  148. package/packages/datadog-plugin-winston/src/index.js +3 -5
  149. package/packages/dd-trace/src/appsec/channels.js +1 -0
  150. package/packages/dd-trace/src/appsec/graphql.js +14 -12
  151. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  152. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  153. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -3
  154. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -3
  155. package/packages/dd-trace/src/config.js +1 -1
  156. package/packages/dd-trace/src/datastreams/checkpointer.js +23 -2
  157. package/packages/dd-trace/src/datastreams/processor.js +4 -3
  158. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +30 -50
  159. package/packages/dd-trace/src/llmobs/plugins/openai.js +3 -5
  160. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +3 -5
  161. package/packages/dd-trace/src/opentracing/propagation/text_map.js +25 -2
  162. package/packages/dd-trace/src/plugins/apollo.js +3 -3
  163. package/packages/dd-trace/src/plugins/cache.js +1 -1
  164. package/packages/dd-trace/src/plugins/client.js +3 -3
  165. package/packages/dd-trace/src/plugins/consumer.js +3 -3
  166. package/packages/dd-trace/src/plugins/database.js +2 -2
  167. package/packages/dd-trace/src/plugins/index.js +1 -0
  168. package/packages/dd-trace/src/plugins/log_plugin.js +1 -5
  169. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  170. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  171. package/packages/dd-trace/src/plugins/producer.js +3 -3
  172. package/packages/dd-trace/src/plugins/server.js +3 -3
  173. package/packages/dd-trace/src/plugins/storage.js +1 -1
  174. package/packages/dd-trace/src/plugins/tracing.js +24 -6
  175. package/packages/dd-trace/src/plugins/util/ci.js +11 -7
  176. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +15 -19
  177. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  178. package/packages/dd-trace/src/plugins/util/web.js +26 -7
  179. package/packages/dd-trace/src/profiling/config.js +2 -0
  180. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -21
  181. package/packages/dd-trace/src/profiling/libuv-size.js +49 -0
  182. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -6
  183. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -3
  184. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -3
  185. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +1 -3
  186. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -3
  187. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +3 -9
  188. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +3 -9
  189. package/packages/dd-trace/src/profiling/profilers/events.js +80 -62
  190. package/packages/dd-trace/src/profiling/profilers/poisson.js +105 -0
  191. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  192. package/packages/dd-trace/src/remote_config/manager.js +1 -1
@@ -7,36 +7,20 @@ const { storage } = require('../../datadog-core')
7
7
  const services = require('./services')
8
8
  const Sampler = require('../../dd-trace/src/sampler')
9
9
  const { MEASURED } = require('../../../ext/tags')
10
- const { estimateTokens } = require('./token-estimator')
11
10
 
12
- const makeUtilities = require('../../dd-trace/src/plugins/util/llm')
13
11
  const {
14
12
  convertBuffersToObjects,
15
13
  constructCompletionResponseFromStreamedChunks,
16
14
  constructChatCompletionResponseFromStreamedChunks
17
15
  } = require('./stream-helpers')
18
16
 
19
- let normalize
20
-
21
17
  const { DD_MAJOR } = require('../../../version')
22
18
 
23
- function safeRequire (path) {
24
- try {
25
- return require(path)
26
- } catch {
27
- return null
28
- }
29
- }
30
-
31
- const encodingForModel = safeRequire('tiktoken')?.encoding_for_model
32
-
33
19
  class OpenAiTracingPlugin extends TracingPlugin {
34
- static get id () { return 'openai' }
35
- static get operation () { return 'request' }
36
- static get system () { return 'openai' }
37
- static get prefix () {
38
- return 'tracing:apm:openai:request'
39
- }
20
+ static id = 'openai'
21
+ static operation = 'request'
22
+ static system = 'openai'
23
+ static prefix = 'tracing:apm:openai:request'
40
24
 
41
25
  constructor (...args) {
42
26
  super(...args)
@@ -47,13 +31,6 @@ class OpenAiTracingPlugin extends TracingPlugin {
47
31
 
48
32
  this.sampler = new Sampler(0.1) // default 10% log sampling
49
33
 
50
- // hoist the normalize function to avoid making all of these functions a class method
51
- if (this._tracerConfig) {
52
- const utilities = makeUtilities('openai', this._tracerConfig)
53
-
54
- normalize = utilities.normalize
55
- }
56
-
57
34
  this.addSub('apm:openai:request:chunk', ({ ctx, chunk, done }) => {
58
35
  if (!ctx.chunks) ctx.chunks = []
59
36
 
@@ -97,7 +74,7 @@ class OpenAiTracingPlugin extends TracingPlugin {
97
74
  }
98
75
 
99
76
  bindStart (ctx) {
100
- const { methodName, args, basePath, apiKey } = ctx
77
+ const { methodName, args } = ctx
101
78
  const payload = normalizeRequestPayload(methodName, args)
102
79
  const normalizedMethodName = normalizeMethodName(methodName)
103
80
 
@@ -116,27 +93,8 @@ class OpenAiTracingPlugin extends TracingPlugin {
116
93
  kind: 'client',
117
94
  meta: {
118
95
  [MEASURED]: 1,
119
- // Data that is always available with a request
120
- 'openai.user.api_key': truncateApiKey(apiKey),
121
- 'openai.api_base': basePath,
122
- // The openai.api_type (openai|azure) is present in Python but not in Node.js
123
- // Add support once https://github.com/openai/openai-node/issues/53 is closed
124
-
125
- // Data that is common across many requests
126
- 'openai.request.best_of': payload.best_of,
127
- 'openai.request.echo': payload.echo,
128
- 'openai.request.logprobs': payload.logprobs,
129
- 'openai.request.max_tokens': payload.max_tokens,
130
- 'openai.request.model': payload.model, // vague model
131
- 'openai.request.n': payload.n,
132
- 'openai.request.presence_penalty': payload.presence_penalty,
133
- 'openai.request.frequency_penalty': payload.frequency_penalty,
134
- 'openai.request.stop': payload.stop,
135
- 'openai.request.suffix': payload.suffix,
136
- 'openai.request.temperature': payload.temperature,
137
- 'openai.request.top_p': payload.top_p,
138
- 'openai.request.user': payload.user,
139
- 'openai.request.file_id': payload.file_id // deleteFile, retrieveFile, downloadFile
96
+ // Only model is added to all requests
97
+ 'openai.request.model': payload.model
140
98
  }
141
99
  }, false)
142
100
 
@@ -144,44 +102,11 @@ class OpenAiTracingPlugin extends TracingPlugin {
144
102
 
145
103
  const tags = {} // The remaining tags are added one at a time
146
104
 
147
- // createChatCompletion, createCompletion, createImage, createImageEdit, createTranscription, createTranslation
148
- if (payload.prompt) {
149
- const prompt = payload.prompt
150
- openaiStore.prompt = prompt
151
- if (typeof prompt === 'string' || (Array.isArray(prompt) && typeof prompt[0] === 'number')) {
152
- // This is a single prompt, either String or [Number]
153
- tags['openai.request.prompt'] = normalizeStringOrTokenArray(prompt, true)
154
- } else if (Array.isArray(prompt)) {
155
- // This is multiple prompts, either [String] or [[Number]]
156
- for (let i = 0; i < prompt.length; i++) {
157
- tags[`openai.request.prompt.${i}`] = normalizeStringOrTokenArray(prompt[i], true)
158
- }
159
- }
160
- }
161
-
162
- // createEdit, createEmbedding, createModeration
163
- if (payload.input) {
164
- const normalized = normalizeStringOrTokenArray(payload.input, false)
165
- tags['openai.request.input'] = normalize(normalized)
166
- openaiStore.input = normalized
167
- }
168
-
169
- // createChatCompletion, createCompletion
170
- if (payload.logit_bias !== null && typeof payload.logit_bias === 'object') {
171
- for (const [tokenId, bias] of Object.entries(payload.logit_bias)) {
172
- tags[`openai.request.logit_bias.${tokenId}`] = bias
173
- }
174
- }
175
-
176
105
  if (payload.stream) {
177
106
  tags['openai.request.stream'] = payload.stream
178
107
  }
179
108
 
180
109
  switch (normalizedMethodName) {
181
- case 'createFineTune':
182
- createFineTuneRequestExtraction(tags, payload)
183
- break
184
-
185
110
  case 'createImage':
186
111
  case 'createImageEdit':
187
112
  case 'createImageVariation':
@@ -206,13 +131,6 @@ class OpenAiTracingPlugin extends TracingPlugin {
206
131
  retrieveModelRequestExtraction(tags, payload)
207
132
  break
208
133
 
209
- case 'listFineTuneEvents':
210
- case 'retrieveFineTune':
211
- case 'deleteModel':
212
- case 'cancelFineTune':
213
- commonLookupFineTuneRequestExtraction(tags, payload)
214
- break
215
-
216
134
  case 'createEdit':
217
135
  createEditRequestExtraction(tags, payload, openaiStore)
218
136
  break
@@ -268,9 +186,6 @@ class OpenAiTracingPlugin extends TracingPlugin {
268
186
  'openai.request.endpoint': endpoint,
269
187
  'openai.request.method': method.toUpperCase(),
270
188
 
271
- 'openai.organization.id': body.organization_id, // only available in fine-tunes endpoints
272
- 'openai.organization.name': headers['openai-organization'],
273
-
274
189
  'openai.response.model': headers['openai-model'] || body.model, // specific model, often undefined
275
190
  'openai.response.id': body.id, // common creation value, numeric epoch
276
191
  'openai.response.deleted': body.deleted, // common boolean field in delete responses
@@ -456,86 +371,8 @@ function normalizeMethodName (methodName) {
456
371
  }
457
372
  }
458
373
 
459
- function countPromptTokens (methodName, payload, model) {
460
- let promptTokens = 0
461
- let promptEstimated = false
462
- if (methodName === 'createChatCompletion') {
463
- const messages = payload.messages
464
- for (const message of messages) {
465
- const content = message.content
466
- if (typeof content === 'string') {
467
- const { tokens, estimated } = countTokens(content, model)
468
- promptTokens += tokens
469
- promptEstimated = estimated
470
- } else if (Array.isArray(content)) {
471
- for (const c of content) {
472
- if (c.type === 'text') {
473
- const { tokens, estimated } = countTokens(c.text, model)
474
- promptTokens += tokens
475
- promptEstimated = estimated
476
- }
477
- // unsupported token computation for image_url
478
- // as even though URL is a string, its true token count
479
- // is based on the image itself, something onerous to do client-side
480
- }
481
- }
482
- }
483
- } else if (methodName === 'createCompletion') {
484
- let prompt = payload.prompt
485
- if (!Array.isArray(prompt)) prompt = [prompt]
486
-
487
- for (const p of prompt) {
488
- const { tokens, estimated } = countTokens(p, model)
489
- promptTokens += tokens
490
- promptEstimated = estimated
491
- }
492
- }
493
-
494
- return { promptTokens, promptEstimated }
495
- }
496
-
497
- function countCompletionTokens (body, model) {
498
- let completionTokens = 0
499
- let completionEstimated = false
500
- if (body?.choices) {
501
- for (const choice of body.choices) {
502
- const message = choice.message || choice.delta // delta for streamed responses
503
- const text = choice.text
504
- const content = text || message?.content
505
-
506
- const { tokens, estimated } = countTokens(content, model)
507
- completionTokens += tokens
508
- completionEstimated = estimated
509
- }
510
- }
511
-
512
- return { completionTokens, completionEstimated }
513
- }
514
-
515
- function countTokens (content, model) {
516
- if (encodingForModel) {
517
- try {
518
- // try using tiktoken if it was available
519
- const encoder = encodingForModel(model)
520
- const tokens = encoder.encode(content).length
521
- encoder.free()
522
- return { tokens, estimated: false }
523
- } catch {
524
- // possible errors from tiktoken:
525
- // * model not available for token counts
526
- // * issue encoding content
527
- }
528
- }
529
-
530
- return {
531
- tokens: estimateTokens(content),
532
- estimated: true
533
- }
534
- }
535
-
536
374
  function createEditRequestExtraction (tags, payload, openaiStore) {
537
375
  const instruction = payload.instruction
538
- tags['openai.request.instruction'] = instruction
539
376
  openaiStore.instruction = instruction
540
377
  }
541
378
 
@@ -548,13 +385,6 @@ function createChatCompletionRequestExtraction (tags, payload, openaiStore) {
548
385
  if (!defensiveArrayLength(messages)) return
549
386
 
550
387
  openaiStore.messages = payload.messages
551
- for (let i = 0; i < payload.messages.length; i++) {
552
- const message = payload.messages[i]
553
- tagChatCompletionRequestContent(message.content, i, tags)
554
- tags[`openai.request.messages.${i}.role`] = message.role
555
- tags[`openai.request.messages.${i}.name`] = message.name
556
- tags[`openai.request.messages.${i}.finish_reason`] = message.finish_reason
557
- }
558
388
  }
559
389
 
560
390
  function commonCreateImageRequestExtraction (tags, payload, openaiStore) {
@@ -562,28 +392,18 @@ function commonCreateImageRequestExtraction (tags, payload, openaiStore) {
562
392
  const img = payload.file || payload.image
563
393
  if (img !== null && typeof img === 'object' && img.path) {
564
394
  const file = path.basename(img.path)
565
- tags['openai.request.image'] = file
566
395
  openaiStore.file = file
567
396
  }
568
397
 
569
398
  // createImageEdit
570
399
  if (payload.mask !== null && typeof payload.mask === 'object' && payload.mask.path) {
571
400
  const mask = path.basename(payload.mask.path)
572
- tags['openai.request.mask'] = mask
573
401
  openaiStore.mask = mask
574
402
  }
575
-
576
- tags['openai.request.size'] = payload.size
577
- tags['openai.request.response_format'] = payload.response_format
578
- tags['openai.request.language'] = payload.language
579
403
  }
580
404
 
581
405
  function responseDataExtractionByMethod (methodName, tags, body, openaiStore) {
582
406
  switch (methodName) {
583
- case 'createModeration':
584
- createModerationResponseExtraction(tags, body)
585
- break
586
-
587
407
  case 'createCompletion':
588
408
  case 'createChatCompletion':
589
409
  case 'createEdit':
@@ -596,10 +416,6 @@ function responseDataExtractionByMethod (methodName, tags, body, openaiStore) {
596
416
  commonListCountResponseExtraction(tags, body)
597
417
  break
598
418
 
599
- case 'createEmbedding':
600
- createEmbeddingResponseExtraction(tags, body, openaiStore)
601
- break
602
-
603
419
  case 'createFile':
604
420
  case 'retrieveFile':
605
421
  createRetrieveFileResponseExtraction(tags, body)
@@ -613,23 +429,6 @@ function responseDataExtractionByMethod (methodName, tags, body, openaiStore) {
613
429
  downloadFileResponseExtraction(tags, body)
614
430
  break
615
431
 
616
- case 'createFineTune':
617
- case 'retrieveFineTune':
618
- case 'cancelFineTune':
619
- commonFineTuneResponseExtraction(tags, body)
620
- break
621
-
622
- case 'createTranscription':
623
- case 'createTranslation':
624
- createAudioResponseExtraction(tags, body)
625
- break
626
-
627
- case 'createImage':
628
- case 'createImageEdit':
629
- case 'createImageVariation':
630
- commonImageResponseExtraction(tags, body)
631
- break
632
-
633
432
  case 'listModels':
634
433
  listModelsResponseExtraction(tags, body)
635
434
  break
@@ -660,70 +459,12 @@ function retrieveModelResponseExtraction (tags, body) {
660
459
  tags['openai.response.permission.is_blocking'] = body.permission[0].is_blocking
661
460
  }
662
461
 
663
- function commonLookupFineTuneRequestExtraction (tags, body) {
664
- tags['openai.request.fine_tune_id'] = body.fine_tune_id
665
- tags['openai.request.stream'] = !!body.stream // listFineTuneEvents
666
- }
667
-
668
462
  function listModelsResponseExtraction (tags, body) {
669
463
  if (!body.data) return
670
464
 
671
465
  tags['openai.response.count'] = body.data.length
672
466
  }
673
467
 
674
- function commonImageResponseExtraction (tags, body) {
675
- if (!body.data) return
676
-
677
- tags['openai.response.images_count'] = body.data.length
678
-
679
- for (let i = 0; i < body.data.length; i++) {
680
- const image = body.data[i]
681
- // exactly one of these two options is provided
682
- tags[`openai.response.images.${i}.url`] = normalize(image.url)
683
- tags[`openai.response.images.${i}.b64_json`] = image.b64_json && 'returned'
684
- }
685
- }
686
-
687
- function createAudioResponseExtraction (tags, body) {
688
- tags['openai.response.text'] = body.text
689
- tags['openai.response.language'] = body.language
690
- tags['openai.response.duration'] = body.duration
691
- tags['openai.response.segments_count'] = defensiveArrayLength(body.segments)
692
- }
693
-
694
- function createFineTuneRequestExtraction (tags, body) {
695
- tags['openai.request.training_file'] = body.training_file
696
- tags['openai.request.validation_file'] = body.validation_file
697
- tags['openai.request.n_epochs'] = body.n_epochs
698
- tags['openai.request.batch_size'] = body.batch_size
699
- tags['openai.request.learning_rate_multiplier'] = body.learning_rate_multiplier
700
- tags['openai.request.prompt_loss_weight'] = body.prompt_loss_weight
701
- tags['openai.request.compute_classification_metrics'] = body.compute_classification_metrics
702
- tags['openai.request.classification_n_classes'] = body.classification_n_classes
703
- tags['openai.request.classification_positive_class'] = body.classification_positive_class
704
- tags['openai.request.classification_betas_count'] = defensiveArrayLength(body.classification_betas)
705
- }
706
-
707
- function commonFineTuneResponseExtraction (tags, body) {
708
- tags['openai.response.events_count'] = defensiveArrayLength(body.events)
709
- tags['openai.response.fine_tuned_model'] = body.fine_tuned_model
710
-
711
- const hyperparams = body.hyperparams || body.hyperparameters
712
- const hyperparamsKey = body.hyperparams ? 'hyperparams' : 'hyperparameters'
713
-
714
- if (hyperparams) {
715
- tags[`openai.response.${hyperparamsKey}.n_epochs`] = hyperparams.n_epochs
716
- tags[`openai.response.${hyperparamsKey}.batch_size`] = hyperparams.batch_size
717
- tags[`openai.response.${hyperparamsKey}.prompt_loss_weight`] = hyperparams.prompt_loss_weight
718
- tags[`openai.response.${hyperparamsKey}.learning_rate_multiplier`] = hyperparams.learning_rate_multiplier
719
- }
720
- tags['openai.response.training_files_count'] = defensiveArrayLength(body.training_files || body.training_file)
721
- tags['openai.response.result_files_count'] = defensiveArrayLength(body.result_files)
722
- tags['openai.response.validation_files_count'] = defensiveArrayLength(body.validation_files || body.validation_file)
723
- tags['openai.response.updated_at'] = body.updated_at
724
- tags['openai.response.status'] = body.status
725
- }
726
-
727
468
  // the OpenAI package appears to stream the content download then provide it all as a singular string
728
469
  function downloadFileResponseExtraction (tags, body) {
729
470
  if (typeof body.file !== 'string') return
@@ -735,12 +476,8 @@ function deleteFileResponseExtraction (tags, body) {
735
476
  }
736
477
 
737
478
  function commonCreateAudioRequestExtraction (tags, body, openaiStore) {
738
- tags['openai.request.response_format'] = body.response_format
739
- tags['openai.request.language'] = body.language
740
-
741
479
  if (body.file !== null && typeof body.file === 'object' && body.file.path) {
742
480
  const filename = path.basename(body.file.path)
743
- tags['openai.request.filename'] = filename
744
481
  openaiStore.file = filename
745
482
  }
746
483
  }
@@ -764,140 +501,16 @@ function createRetrieveFileResponseExtraction (tags, body) {
764
501
  tags['openai.response.status_details'] = body.status_details
765
502
  }
766
503
 
767
- function createEmbeddingResponseExtraction (tags, body, openaiStore) {
768
- usageExtraction(tags, body, openaiStore)
769
-
770
- if (!body.data) return
771
-
772
- tags['openai.response.embeddings_count'] = body.data.length
773
- for (let i = 0; i < body.data.length; i++) {
774
- tags[`openai.response.embedding.${i}.embedding_length`] = body.data[i].embedding.length
775
- }
776
- }
777
-
778
504
  function commonListCountResponseExtraction (tags, body) {
779
505
  if (!body.data) return
780
506
  tags['openai.response.count'] = body.data.length
781
507
  }
782
508
 
783
- // TODO: Is there ever more than one entry in body.results?
784
- function createModerationResponseExtraction (tags, body) {
785
- tags['openai.response.id'] = body.id
786
- // tags[`openai.response.model`] = body.model // redundant, already extracted globally
787
-
788
- if (!body.results) return
789
-
790
- tags['openai.response.flagged'] = body.results[0].flagged
791
-
792
- for (const [category, match] of Object.entries(body.results[0].categories)) {
793
- tags[`openai.response.categories.${category}`] = match
794
- }
795
-
796
- for (const [category, score] of Object.entries(body.results[0].category_scores)) {
797
- tags[`openai.response.category_scores.${category}`] = score
798
- }
799
- }
800
-
801
509
  // createCompletion, createChatCompletion, createEdit
802
510
  function commonCreateResponseExtraction (tags, body, openaiStore, methodName) {
803
- usageExtraction(tags, body, methodName, openaiStore)
804
-
805
511
  if (!body.choices) return
806
512
 
807
- tags['openai.response.choices_count'] = body.choices.length
808
-
809
513
  openaiStore.choices = body.choices
810
-
811
- for (let choiceIdx = 0; choiceIdx < body.choices.length; choiceIdx++) {
812
- const choice = body.choices[choiceIdx]
813
-
814
- // logprobs can be null and we still want to tag it as 'returned' even when set to 'null'
815
- const specifiesLogProb = Object.keys(choice).includes('logprobs')
816
-
817
- tags[`openai.response.choices.${choiceIdx}.finish_reason`] = choice.finish_reason
818
- tags[`openai.response.choices.${choiceIdx}.logprobs`] = specifiesLogProb ? 'returned' : undefined
819
- tags[`openai.response.choices.${choiceIdx}.text`] = normalize(choice.text)
820
-
821
- // createChatCompletion only
822
- const message = choice.message || choice.delta // delta for streamed responses
823
- if (message) {
824
- tags[`openai.response.choices.${choiceIdx}.message.role`] = message.role
825
- tags[`openai.response.choices.${choiceIdx}.message.content`] = normalize(message.content)
826
- tags[`openai.response.choices.${choiceIdx}.message.name`] = normalize(message.name)
827
- if (message.tool_calls) {
828
- const toolCalls = message.tool_calls
829
- for (let toolIdx = 0; toolIdx < toolCalls.length; toolIdx++) {
830
- tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.function.name`] =
831
- toolCalls[toolIdx].function.name
832
- tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.function.arguments`] =
833
- toolCalls[toolIdx].function.arguments
834
- tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.id`] =
835
- toolCalls[toolIdx].id
836
- }
837
- }
838
- }
839
- }
840
- }
841
-
842
- // createCompletion, createChatCompletion, createEdit, createEmbedding
843
- function usageExtraction (tags, body, methodName, openaiStore) {
844
- let promptTokens = 0
845
- let completionTokens = 0
846
- let totalTokens = 0
847
- if (body && body.usage) {
848
- promptTokens = body.usage.prompt_tokens
849
- completionTokens = body.usage.completion_tokens
850
- totalTokens = body.usage.total_tokens
851
- } else if (body.model && ['createChatCompletion', 'createCompletion'].includes(methodName)) {
852
- // estimate tokens based on method name for completions and chat completions
853
- const { model } = body
854
-
855
- // prompt tokens
856
- const payload = openaiStore
857
- const promptTokensCount = countPromptTokens(methodName, payload, model)
858
- promptTokens = promptTokensCount.promptTokens
859
- const promptEstimated = promptTokensCount.promptEstimated
860
-
861
- // completion tokens
862
- const completionTokensCount = countCompletionTokens(body, model)
863
- completionTokens = completionTokensCount.completionTokens
864
- const completionEstimated = completionTokensCount.completionEstimated
865
-
866
- // total tokens
867
- totalTokens = promptTokens + completionTokens
868
- if (promptEstimated) tags['openai.response.usage.prompt_tokens_estimated'] = true
869
- if (completionEstimated) tags['openai.response.usage.completion_tokens_estimated'] = true
870
- }
871
-
872
- if (promptTokens != null) tags['openai.response.usage.prompt_tokens'] = promptTokens
873
- if (completionTokens != null) tags['openai.response.usage.completion_tokens'] = completionTokens
874
- if (totalTokens != null) tags['openai.response.usage.total_tokens'] = totalTokens
875
- }
876
-
877
- function truncateApiKey (apiKey) {
878
- return apiKey && `sk-...${apiKey.slice(-4)}`
879
- }
880
-
881
- function tagChatCompletionRequestContent (contents, messageIdx, tags) {
882
- if (typeof contents === 'string') {
883
- tags[`openai.request.messages.${messageIdx}.content`] = normalize(contents)
884
- } else if (Array.isArray(contents)) {
885
- // content can also be an array of objects
886
- // which represent text input or image url
887
- for (const contentIdx in contents) {
888
- const content = contents[contentIdx]
889
- const type = content.type
890
- tags[`openai.request.messages.${messageIdx}.content.${contentIdx}.type`] = content.type
891
- if (type === 'text') {
892
- tags[`openai.request.messages.${messageIdx}.content.${contentIdx}.text`] = normalize(content.text)
893
- } else if (type === 'image_url') {
894
- tags[`openai.request.messages.${messageIdx}.content.${contentIdx}.image_url.url`] =
895
- normalize(content.image_url.url)
896
- }
897
- // unsupported type otherwise, won't be tagged
898
- }
899
- }
900
- // unsupported type otherwise, won't be tagged
901
514
  }
902
515
 
903
516
  // The server almost always responds with JSON
@@ -1055,23 +668,6 @@ function normalizeRequestPayload (methodName, args) {
1055
668
  return args[0]
1056
669
  }
1057
670
 
1058
- /**
1059
- * Converts an array of tokens to a string
1060
- * If input is already a string it's returned
1061
- * In either case the value is truncated
1062
-
1063
- * It's intentional that the array be truncated arbitrarily, e.g. "[999, 888, 77..."
1064
-
1065
- * "foo" -> "foo"
1066
- * [1,2,3] -> "[1, 2, 3]"
1067
- */
1068
- function normalizeStringOrTokenArray (input, truncate) {
1069
- const normalized = Array.isArray(input)
1070
- ? `[${input.join(', ')}]` // "[1, 2, 999]"
1071
- : input // "foo"
1072
- return truncate ? normalize(normalized) : normalized
1073
- }
1074
-
1075
671
  function defensiveArrayLength (maybeArray) {
1076
672
  if (maybeArray) {
1077
673
  // Detect singular item (ie body.training_file vs body.training_files)
@@ -3,9 +3,7 @@
3
3
  const ElasticsearchPlugin = require('../../datadog-plugin-elasticsearch/src')
4
4
 
5
5
  class OpenSearchPlugin extends ElasticsearchPlugin {
6
- static get id () {
7
- return 'opensearch'
8
- }
6
+ static id = 'opensearch'
9
7
  }
10
8
 
11
9
  module.exports = OpenSearchPlugin
@@ -6,11 +6,13 @@ const DatabasePlugin = require('../../dd-trace/src/plugins/database')
6
6
  let parser
7
7
 
8
8
  class OracledbPlugin extends DatabasePlugin {
9
- static get id () { return 'oracledb' }
10
- static get system () { return 'oracle' }
11
- static get peerServicePrecursors () { return ['db.instance', 'db.hostname'] }
9
+ static id = 'oracledb'
10
+ static system = 'oracle'
11
+ static peerServicePrecursors = ['db.instance', 'db.hostname']
12
+
13
+ bindStart (ctx) {
14
+ let { query, connAttrs, port, hostname, dbInstance } = ctx
12
15
 
13
- start ({ query, connAttrs, port, hostname, dbInstance }) {
14
16
  const service = this.serviceName({ pluginConfig: this.config, params: connAttrs })
15
17
 
16
18
  if (hostname === undefined) {
@@ -33,7 +35,9 @@ class OracledbPlugin extends DatabasePlugin {
33
35
  'db.hostname': hostname,
34
36
  [CLIENT_PORT_KEY]: port,
35
37
  }
36
- })
38
+ }, ctx)
39
+
40
+ return ctx.currentStore
37
41
  }
38
42
  }
39
43
 
@@ -4,9 +4,9 @@ const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
4
  const DatabasePlugin = require('../../dd-trace/src/plugins/database')
5
5
 
6
6
  class PGPlugin extends DatabasePlugin {
7
- static get id () { return 'pg' }
8
- static get operation () { return 'query' }
9
- static get system () { return 'postgres' }
7
+ static id = 'pg'
8
+ static operation = 'query'
9
+ static system = 'postgres'
10
10
 
11
11
  start ({ params = {}, query, processId, stream }) {
12
12
  const service = this.serviceName({ pluginConfig: this.config, params })
@@ -1,11 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const StructuredLogPlugin = require('../../dd-trace/src/plugins/structured_log_plugin')
3
+ const LogPlugin = require('../../dd-trace/src/plugins/log_plugin')
4
4
 
5
- class PinoPlugin extends StructuredLogPlugin {
6
- static get id () {
7
- return 'pino'
8
- }
5
+ class PinoPlugin extends LogPlugin {
6
+ static id = 'pino'
9
7
  }
10
8
 
11
9
  module.exports = PinoPlugin
@@ -48,9 +48,7 @@ const {
48
48
  const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
49
49
 
50
50
  class PlaywrightPlugin extends CiPlugin {
51
- static get id () {
52
- return 'playwright'
53
- }
51
+ static id = 'playwright'
54
52
 
55
53
  constructor (...args) {
56
54
  super(...args)
@@ -1,12 +1,10 @@
1
1
  'use strict'
2
2
  const DatabasePlugin = require('../../dd-trace/src/plugins/database')
3
3
  class PrismaClientPlugin extends DatabasePlugin {
4
- static get id () { return 'prisma' }
5
- static get operation () { return 'client' }
6
- static get system () { return 'prisma' }
7
- static get prefix () {
8
- return 'tracing:apm:prisma:client'
9
- }
4
+ static id = 'prisma'
5
+ static operation = 'client'
6
+ static system = 'prisma'
7
+ static prefix = 'tracing:apm:prisma:client'
10
8
 
11
9
  bindStart (ctx) {
12
10
  const service = this.serviceName({ pluginConfig: this.config })
@@ -23,9 +23,9 @@ const databaseDriverMapper = {
23
23
  }
24
24
 
25
25
  class PrismaEngine extends DatabasePlugin {
26
- static get id () { return 'prisma' }
27
- static get operation () { return 'engine' }
28
- static get system () { return 'prisma' }
26
+ static id = 'prisma'
27
+ static operation = 'engine'
28
+ static system = 'prisma'
29
29
 
30
30
  start (ctx) {
31
31
  const { engineSpan, allEngineSpans, childOf, dbConfig } = ctx