dd-trace 5.56.0 → 5.57.1
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.
- package/index.d.ts +44 -2
- package/init.js +4 -1
- package/package.json +20 -20
- package/packages/datadog-esbuild/index.js +22 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +4 -6
- package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
- package/packages/datadog-instrumentations/src/fastify.js +91 -9
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
- package/packages/datadog-instrumentations/src/ioredis.js +8 -13
- package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
- package/packages/datadog-instrumentations/src/jest.js +28 -6
- package/packages/datadog-instrumentations/src/memcached.js +17 -24
- package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
- package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
- package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
- package/packages/datadog-instrumentations/src/openai.js +30 -2
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +116 -0
- package/packages/datadog-instrumentations/src/redis.js +32 -43
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/sharedb.js +10 -16
- package/packages/datadog-instrumentations/src/vitest.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-bunyan/src/index.js +2 -2
- package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +4 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
- package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
- package/packages/datadog-plugin-http/src/client.js +1 -0
- package/packages/datadog-plugin-http/src/server.js +2 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -0
- package/packages/datadog-plugin-http2/src/server.js +1 -0
- package/packages/datadog-plugin-jest/src/index.js +4 -3
- package/packages/datadog-plugin-memcached/src/index.js +6 -2
- package/packages/datadog-plugin-mocha/src/index.js +3 -2
- package/packages/datadog-plugin-moleculer/src/client.js +15 -9
- package/packages/datadog-plugin-moleculer/src/server.js +9 -5
- package/packages/datadog-plugin-next/src/index.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +127 -80
- package/packages/datadog-plugin-pino/src/index.js +2 -2
- package/packages/datadog-plugin-prisma/src/client.js +62 -0
- package/packages/datadog-plugin-prisma/src/engine.js +81 -0
- package/packages/datadog-plugin-prisma/src/index.js +22 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +9 -3
- package/packages/datadog-plugin-router/src/index.js +1 -0
- package/packages/datadog-plugin-sharedb/src/index.js +13 -5
- package/packages/datadog-plugin-winston/src/index.js +2 -2
- package/packages/dd-trace/src/appsec/channels.js +26 -21
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +16 -1
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
- package/packages/dd-trace/src/config.js +286 -270
- package/packages/dd-trace/src/constants.js +2 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
- package/packages/dd-trace/src/datastreams/context.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
- package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
- package/packages/dd-trace/src/dogstatsd.js +3 -3
- package/packages/dd-trace/src/exporters/agent/index.js +10 -5
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/log/index.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
- package/packages/dd-trace/src/guardrails/index.js +3 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/index.js +11 -5
- package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +13 -13
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
- package/packages/dd-trace/src/opentracing/span.js +1 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/cache.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
- package/packages/dd-trace/src/plugins/database.js +3 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
- package/packages/dd-trace/src/plugins/outbound.js +8 -6
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +83 -30
- package/packages/dd-trace/src/plugins/util/git.js +1 -0
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/test.js +80 -10
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiler.js +0 -2
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
- package/packages/dd-trace/src/proxy.js +12 -27
- package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/supported-configurations.json +12 -3
- package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
- package/packages/dd-trace/src/tracer.js +11 -0
- package/packages/dd-trace/src/tracer_metadata.js +25 -0
- package/packages/dd-trace/src/util.js +11 -4
- package/version.js +3 -1
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
|
@@ -27,13 +27,14 @@ class HttpServerPlugin extends ServerPlugin {
|
|
|
27
27
|
this.tracer,
|
|
28
28
|
{
|
|
29
29
|
...this.config,
|
|
30
|
-
service: this.config.service || this.serviceName()
|
|
30
|
+
service: this.config.service || this.serviceName(),
|
|
31
31
|
},
|
|
32
32
|
req,
|
|
33
33
|
res,
|
|
34
34
|
this.operationName()
|
|
35
35
|
)
|
|
36
36
|
span.setTag(COMPONENT, this.constructor.id)
|
|
37
|
+
span._integrationName = this.constructor.id
|
|
37
38
|
|
|
38
39
|
this._parentStore = store
|
|
39
40
|
this.enter(span, { ...store, req, res })
|
|
@@ -40,6 +40,7 @@ class Http2ClientPlugin extends ClientPlugin {
|
|
|
40
40
|
const childOf = store && allowed ? store.span : null
|
|
41
41
|
const span = this.startSpan(this.operationName(), {
|
|
42
42
|
childOf,
|
|
43
|
+
integrationName: this.constructor.id,
|
|
43
44
|
meta: {
|
|
44
45
|
[COMPONENT]: this.constructor.id,
|
|
45
46
|
[SPAN_KIND]: CLIENT,
|
|
@@ -252,7 +252,8 @@ class JestPlugin extends CiPlugin {
|
|
|
252
252
|
[COMPONENT]: this.constructor.id,
|
|
253
253
|
...this.testEnvironmentMetadata,
|
|
254
254
|
...testSuiteMetadata
|
|
255
|
-
}
|
|
255
|
+
},
|
|
256
|
+
integrationName: this.constructor.id
|
|
256
257
|
})
|
|
257
258
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
258
259
|
if (_ddTestCodeCoverageEnabled) {
|
|
@@ -318,11 +319,11 @@ class JestPlugin extends CiPlugin {
|
|
|
318
319
|
* because this subscription happens in a different process from the one
|
|
319
320
|
* fetching the ITR config.
|
|
320
321
|
*/
|
|
321
|
-
this.addSub('ci:jest:test-suite:code-coverage', ({ coverageFiles, testSuite }) => {
|
|
322
|
+
this.addSub('ci:jest:test-suite:code-coverage', ({ coverageFiles, testSuite, mockedFiles }) => {
|
|
322
323
|
if (!coverageFiles.length) {
|
|
323
324
|
this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
324
325
|
}
|
|
325
|
-
const files = [...coverageFiles, testSuite]
|
|
326
|
+
const files = [...coverageFiles, ...mockedFiles, testSuite]
|
|
326
327
|
|
|
327
328
|
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
328
329
|
const formattedCoverage = {
|
|
@@ -6,7 +6,9 @@ const CachePlugin = require('../../dd-trace/src/plugins/cache')
|
|
|
6
6
|
class MemcachedPlugin extends CachePlugin {
|
|
7
7
|
static get id () { return 'memcached' }
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
bindStart (ctx) {
|
|
10
|
+
const { client, server, query } = ctx
|
|
11
|
+
|
|
10
12
|
const address = getAddress(client, server, query)
|
|
11
13
|
|
|
12
14
|
const meta = {
|
|
@@ -23,7 +25,9 @@ class MemcachedPlugin extends CachePlugin {
|
|
|
23
25
|
resource: query.type,
|
|
24
26
|
type: 'memcached',
|
|
25
27
|
meta
|
|
26
|
-
})
|
|
28
|
+
}, ctx)
|
|
29
|
+
|
|
30
|
+
return ctx.currentStore
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -152,7 +152,8 @@ class MochaPlugin extends CiPlugin {
|
|
|
152
152
|
[COMPONENT]: this.constructor.id,
|
|
153
153
|
...this.testEnvironmentMetadata,
|
|
154
154
|
...testSuiteMetadata
|
|
155
|
-
}
|
|
155
|
+
},
|
|
156
|
+
integrationName: this.constructor.id
|
|
156
157
|
})
|
|
157
158
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
158
159
|
if (this.libraryConfig?.isCodeCoverageEnabled) {
|
|
@@ -450,7 +451,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
450
451
|
const testSuite = span.meta[TEST_SUITE]
|
|
451
452
|
const testSuiteSpan = this._testSuites.get(testSuite)
|
|
452
453
|
if (!testSuiteSpan) {
|
|
453
|
-
log.warn(
|
|
454
|
+
log.warn('Test suite span not found for test span with test suite', testSuite)
|
|
454
455
|
return formattedSpan
|
|
455
456
|
}
|
|
456
457
|
const suiteTags = getTestSuiteLevelVisibilityTags(testSuiteSpan)
|
|
@@ -7,29 +7,35 @@ class MoleculerClientPlugin extends ClientPlugin {
|
|
|
7
7
|
static get id () { return 'moleculer' }
|
|
8
8
|
static get operation () { return 'call' }
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
bindStart (ctx) {
|
|
11
|
+
const { actionName, opts } = ctx
|
|
12
|
+
|
|
11
13
|
const span = this.startSpan(this.operationName(), {
|
|
12
14
|
service: this.config.service || this.serviceName(),
|
|
13
15
|
resource: actionName,
|
|
14
16
|
kind: 'client'
|
|
15
|
-
})
|
|
17
|
+
}, ctx)
|
|
16
18
|
|
|
17
19
|
this.tracer.inject(span, 'text_map', opts.meta)
|
|
20
|
+
|
|
21
|
+
return ctx.currentStore
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
finish (
|
|
21
|
-
const
|
|
24
|
+
finish (ctx) {
|
|
25
|
+
const { promiseCtx, broker } = ctx
|
|
26
|
+
|
|
27
|
+
const span = ctx.currentStore.span || this.activeSpan
|
|
22
28
|
|
|
23
|
-
if (
|
|
24
|
-
const endpoint =
|
|
29
|
+
if (promiseCtx) {
|
|
30
|
+
const endpoint = promiseCtx.endpoint || {}
|
|
25
31
|
const node = endpoint.node || {}
|
|
26
32
|
|
|
27
|
-
this.addHost(node.hostname, node.port)
|
|
33
|
+
this.addHost({ hostname: node.hostname, port: node.port })
|
|
28
34
|
|
|
29
|
-
span.addTags(moleculerTags(broker,
|
|
35
|
+
span.addTags(moleculerTags(broker, promiseCtx, this.config))
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
super.finish()
|
|
38
|
+
super.finish(ctx)
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
|
|
@@ -7,19 +7,23 @@ class MoleculerServerPlugin extends ServerPlugin {
|
|
|
7
7
|
static get id () { return 'moleculer' }
|
|
8
8
|
static get operation () { return 'action' }
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const
|
|
10
|
+
bindStart (ctx) {
|
|
11
|
+
const { action, middlewareCtx, broker } = ctx
|
|
12
|
+
|
|
13
|
+
const followsFrom = this.tracer.extract('text_map', middlewareCtx.meta)
|
|
12
14
|
this.startSpan(this.operationName(), {
|
|
13
|
-
childOf: followsFrom || this.activeSpan,
|
|
15
|
+
childOf: followsFrom || ctx?.currentStore?.span || this.activeSpan,
|
|
14
16
|
service: this.config.service || this.serviceName(),
|
|
15
17
|
resource: action.name,
|
|
16
18
|
kind: 'server',
|
|
17
19
|
type: 'web',
|
|
18
20
|
meta: {
|
|
19
21
|
'resource.name': action.name,
|
|
20
|
-
...moleculerTags(broker,
|
|
22
|
+
...moleculerTags(broker, middlewareCtx, this.config)
|
|
21
23
|
}
|
|
22
|
-
})
|
|
24
|
+
}, ctx)
|
|
25
|
+
|
|
26
|
+
return ctx.currentStore
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
|
|
@@ -13,6 +13,8 @@ const makeUtilities = require('../../dd-trace/src/plugins/util/llm')
|
|
|
13
13
|
|
|
14
14
|
let normalize
|
|
15
15
|
|
|
16
|
+
const { DD_MAJOR } = require('../../../version')
|
|
17
|
+
|
|
16
18
|
function safeRequire (path) {
|
|
17
19
|
try {
|
|
18
20
|
return require(path)
|
|
@@ -59,11 +61,19 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
59
61
|
bindStart (ctx) {
|
|
60
62
|
const { methodName, args, basePath, apiKey } = ctx
|
|
61
63
|
const payload = normalizeRequestPayload(methodName, args)
|
|
64
|
+
const normalizedMethodName = normalizeMethodName(methodName)
|
|
65
|
+
|
|
62
66
|
const store = storage('legacy').getStore() || {}
|
|
63
67
|
|
|
68
|
+
// hold onto these to make response extraction matching efficient
|
|
69
|
+
// the original method name corresponds to the SDK method name (e.g. createChatCompletion, chat.completions.create)
|
|
70
|
+
// the normalized method name corresponds to the resource name (e.g. createChatCompletion, createCompletion)
|
|
71
|
+
store.originalMethodName = methodName
|
|
72
|
+
store.normalizedMethodName = normalizedMethodName
|
|
73
|
+
|
|
64
74
|
const span = this.startSpan('openai.request', {
|
|
65
75
|
service: this.config.service,
|
|
66
|
-
resource: methodName,
|
|
76
|
+
resource: DD_MAJOR >= 6 ? normalizedMethodName : methodName,
|
|
67
77
|
type: 'openai',
|
|
68
78
|
kind: 'client',
|
|
69
79
|
meta: {
|
|
@@ -129,62 +139,43 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
129
139
|
tags['openai.request.stream'] = payload.stream
|
|
130
140
|
}
|
|
131
141
|
|
|
132
|
-
switch (
|
|
142
|
+
switch (normalizedMethodName) {
|
|
133
143
|
case 'createFineTune':
|
|
134
|
-
case 'fine_tuning.jobs.create':
|
|
135
|
-
case 'fine-tune.create':
|
|
136
144
|
createFineTuneRequestExtraction(tags, payload)
|
|
137
145
|
break
|
|
138
146
|
|
|
139
147
|
case 'createImage':
|
|
140
|
-
case 'images.generate':
|
|
141
148
|
case 'createImageEdit':
|
|
142
|
-
case 'images.edit':
|
|
143
149
|
case 'createImageVariation':
|
|
144
|
-
case 'images.createVariation':
|
|
145
150
|
commonCreateImageRequestExtraction(tags, payload, openaiStore)
|
|
146
151
|
break
|
|
147
152
|
|
|
148
153
|
case 'createChatCompletion':
|
|
149
|
-
case 'chat.completions.create':
|
|
150
154
|
createChatCompletionRequestExtraction(tags, payload, openaiStore)
|
|
151
155
|
break
|
|
152
156
|
|
|
153
157
|
case 'createFile':
|
|
154
|
-
case 'files.create':
|
|
155
158
|
case 'retrieveFile':
|
|
156
|
-
case 'files.retrieve':
|
|
157
159
|
commonFileRequestExtraction(tags, payload)
|
|
158
160
|
break
|
|
159
161
|
|
|
160
162
|
case 'createTranscription':
|
|
161
|
-
case 'audio.transcriptions.create':
|
|
162
163
|
case 'createTranslation':
|
|
163
|
-
case 'audio.translations.create':
|
|
164
164
|
commonCreateAudioRequestExtraction(tags, payload, openaiStore)
|
|
165
165
|
break
|
|
166
166
|
|
|
167
167
|
case 'retrieveModel':
|
|
168
|
-
case 'models.retrieve':
|
|
169
168
|
retrieveModelRequestExtraction(tags, payload)
|
|
170
169
|
break
|
|
171
170
|
|
|
172
171
|
case 'listFineTuneEvents':
|
|
173
|
-
case 'fine_tuning.jobs.listEvents':
|
|
174
|
-
case 'fine-tune.listEvents':
|
|
175
172
|
case 'retrieveFineTune':
|
|
176
|
-
case 'fine_tuning.jobs.retrieve':
|
|
177
|
-
case 'fine-tune.retrieve':
|
|
178
173
|
case 'deleteModel':
|
|
179
|
-
case 'models.del':
|
|
180
174
|
case 'cancelFineTune':
|
|
181
|
-
case 'fine_tuning.jobs.cancel':
|
|
182
|
-
case 'fine-tune.cancel':
|
|
183
175
|
commonLookupFineTuneRequestExtraction(tags, payload)
|
|
184
176
|
break
|
|
185
177
|
|
|
186
178
|
case 'createEdit':
|
|
187
|
-
case 'edits.create':
|
|
188
179
|
createEditRequestExtraction(tags, payload, openaiStore)
|
|
189
180
|
break
|
|
190
181
|
}
|
|
@@ -216,9 +207,11 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
216
207
|
if (!error && headers?.constructor.name === 'Headers') {
|
|
217
208
|
headers = Object.fromEntries(headers)
|
|
218
209
|
}
|
|
219
|
-
const methodName = span._spanContext._tags['resource.name']
|
|
220
210
|
|
|
221
|
-
|
|
211
|
+
const resource = span._spanContext._tags['resource.name']
|
|
212
|
+
const normalizedMethodName = store.normalizedMethodName
|
|
213
|
+
|
|
214
|
+
body = coerceResponseBody(body, normalizedMethodName)
|
|
222
215
|
|
|
223
216
|
const openaiStore = store.openai
|
|
224
217
|
|
|
@@ -227,7 +220,9 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
227
220
|
// not using a full regex as it will likely be "https://api.openai.com/..."
|
|
228
221
|
path = new URL(path).pathname
|
|
229
222
|
}
|
|
230
|
-
|
|
223
|
+
|
|
224
|
+
const originalMethodName = store.originalMethodName
|
|
225
|
+
const endpoint = lookupOperationEndpoint(normalizedMethodName, originalMethodName, path)
|
|
231
226
|
|
|
232
227
|
const tags = error
|
|
233
228
|
? {}
|
|
@@ -248,11 +243,11 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
248
243
|
'openai.response.created_at': body.created_at
|
|
249
244
|
}
|
|
250
245
|
|
|
251
|
-
responseDataExtractionByMethod(
|
|
246
|
+
responseDataExtractionByMethod(normalizedMethodName, tags, body, openaiStore)
|
|
252
247
|
span.addTags(tags)
|
|
253
248
|
|
|
254
249
|
span.finish()
|
|
255
|
-
this.sendLog(
|
|
250
|
+
this.sendLog(resource, span, tags, openaiStore, error)
|
|
256
251
|
this.sendMetrics(headers, body, endpoint, span._duration, error, tags)
|
|
257
252
|
}
|
|
258
253
|
|
|
@@ -343,10 +338,90 @@ class OpenAiTracingPlugin extends TracingPlugin {
|
|
|
343
338
|
}
|
|
344
339
|
}
|
|
345
340
|
|
|
341
|
+
function normalizeMethodName (methodName) {
|
|
342
|
+
switch (methodName) {
|
|
343
|
+
// moderations
|
|
344
|
+
case 'moderations.create':
|
|
345
|
+
return 'createModeration'
|
|
346
|
+
|
|
347
|
+
// completions
|
|
348
|
+
case 'completions.create':
|
|
349
|
+
return 'createCompletion'
|
|
350
|
+
|
|
351
|
+
// chat completions
|
|
352
|
+
case 'chat.completions.create':
|
|
353
|
+
return 'createChatCompletion'
|
|
354
|
+
|
|
355
|
+
// edits
|
|
356
|
+
case 'edits.create':
|
|
357
|
+
return 'createEdit'
|
|
358
|
+
|
|
359
|
+
// embeddings
|
|
360
|
+
case 'embeddings.create':
|
|
361
|
+
return 'createEmbedding'
|
|
362
|
+
|
|
363
|
+
// files
|
|
364
|
+
case 'files.create':
|
|
365
|
+
return 'createFile'
|
|
366
|
+
case 'files.retrieve':
|
|
367
|
+
return 'retrieveFile'
|
|
368
|
+
case 'files.del':
|
|
369
|
+
case 'files.delete':
|
|
370
|
+
return 'deleteFile'
|
|
371
|
+
case 'files.retrieveContent':
|
|
372
|
+
case 'files.content':
|
|
373
|
+
return 'downloadFile'
|
|
374
|
+
case 'files.list':
|
|
375
|
+
return 'listFiles'
|
|
376
|
+
|
|
377
|
+
// fine-tuning
|
|
378
|
+
case 'fine_tuning.jobs.list':
|
|
379
|
+
case 'fine-tune.list':
|
|
380
|
+
return 'listFineTunes'
|
|
381
|
+
case 'fine_tuning.jobs.listEvents':
|
|
382
|
+
case 'fine-tune.listEvents':
|
|
383
|
+
return 'listFineTuneEvents'
|
|
384
|
+
case 'fine_tuning.jobs.create':
|
|
385
|
+
case 'fine-tune.create':
|
|
386
|
+
return 'createFineTune'
|
|
387
|
+
case 'fine_tuning.jobs.retrieve':
|
|
388
|
+
case 'fine-tune.retrieve':
|
|
389
|
+
return 'retrieveFineTune'
|
|
390
|
+
case 'fine_tuning.jobs.cancel':
|
|
391
|
+
case 'fine-tune.cancel':
|
|
392
|
+
return 'cancelFineTune'
|
|
393
|
+
|
|
394
|
+
// audio
|
|
395
|
+
case 'audio.transcriptions.create':
|
|
396
|
+
return 'createTranscription'
|
|
397
|
+
case 'audio.translations.create':
|
|
398
|
+
return 'createTranslation'
|
|
399
|
+
|
|
400
|
+
// images
|
|
401
|
+
case 'images.generate':
|
|
402
|
+
return 'createImage'
|
|
403
|
+
case 'images.edit':
|
|
404
|
+
return 'createImageEdit'
|
|
405
|
+
case 'images.createVariation':
|
|
406
|
+
return 'createImageVariation'
|
|
407
|
+
|
|
408
|
+
// models
|
|
409
|
+
case 'models.list':
|
|
410
|
+
return 'listModels'
|
|
411
|
+
case 'models.retrieve':
|
|
412
|
+
return 'retrieveModel'
|
|
413
|
+
case 'models.del':
|
|
414
|
+
case 'models.delete':
|
|
415
|
+
return 'deleteModel'
|
|
416
|
+
default:
|
|
417
|
+
return methodName
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
346
421
|
function countPromptTokens (methodName, payload, model) {
|
|
347
422
|
let promptTokens = 0
|
|
348
423
|
let promptEstimated = false
|
|
349
|
-
if (methodName === '
|
|
424
|
+
if (methodName === 'createChatCompletion') {
|
|
350
425
|
const messages = payload.messages
|
|
351
426
|
for (const message of messages) {
|
|
352
427
|
const content = message.content
|
|
@@ -367,7 +442,7 @@ function countPromptTokens (methodName, payload, model) {
|
|
|
367
442
|
}
|
|
368
443
|
}
|
|
369
444
|
}
|
|
370
|
-
} else if (methodName === '
|
|
445
|
+
} else if (methodName === 'createCompletion') {
|
|
371
446
|
let prompt = payload.prompt
|
|
372
447
|
if (!Array.isArray(prompt)) prompt = [prompt]
|
|
373
448
|
|
|
@@ -468,88 +543,60 @@ function commonCreateImageRequestExtraction (tags, payload, openaiStore) {
|
|
|
468
543
|
function responseDataExtractionByMethod (methodName, tags, body, openaiStore) {
|
|
469
544
|
switch (methodName) {
|
|
470
545
|
case 'createModeration':
|
|
471
|
-
case 'moderations.create':
|
|
472
546
|
createModerationResponseExtraction(tags, body)
|
|
473
547
|
break
|
|
474
548
|
|
|
475
549
|
case 'createCompletion':
|
|
476
|
-
case 'completions.create':
|
|
477
550
|
case 'createChatCompletion':
|
|
478
|
-
case 'chat.completions.create':
|
|
479
551
|
case 'createEdit':
|
|
480
|
-
case 'edits.create':
|
|
481
552
|
commonCreateResponseExtraction(tags, body, openaiStore, methodName)
|
|
482
553
|
break
|
|
483
554
|
|
|
484
555
|
case 'listFiles':
|
|
485
|
-
case 'files.list':
|
|
486
556
|
case 'listFineTunes':
|
|
487
|
-
case 'fine_tuning.jobs.list':
|
|
488
|
-
case 'fine-tune.list':
|
|
489
557
|
case 'listFineTuneEvents':
|
|
490
|
-
case 'fine_tuning.jobs.listEvents':
|
|
491
|
-
case 'fine-tune.listEvents':
|
|
492
558
|
commonListCountResponseExtraction(tags, body)
|
|
493
559
|
break
|
|
494
560
|
|
|
495
561
|
case 'createEmbedding':
|
|
496
|
-
case 'embeddings.create':
|
|
497
562
|
createEmbeddingResponseExtraction(tags, body, openaiStore)
|
|
498
563
|
break
|
|
499
564
|
|
|
500
565
|
case 'createFile':
|
|
501
|
-
case 'files.create':
|
|
502
566
|
case 'retrieveFile':
|
|
503
|
-
case 'files.retrieve':
|
|
504
567
|
createRetrieveFileResponseExtraction(tags, body)
|
|
505
568
|
break
|
|
506
569
|
|
|
507
570
|
case 'deleteFile':
|
|
508
|
-
case 'files.del':
|
|
509
571
|
deleteFileResponseExtraction(tags, body)
|
|
510
572
|
break
|
|
511
573
|
|
|
512
574
|
case 'downloadFile':
|
|
513
|
-
case 'files.retrieveContent':
|
|
514
|
-
case 'files.content':
|
|
515
575
|
downloadFileResponseExtraction(tags, body)
|
|
516
576
|
break
|
|
517
577
|
|
|
518
578
|
case 'createFineTune':
|
|
519
|
-
case 'fine_tuning.jobs.create':
|
|
520
|
-
case 'fine-tune.create':
|
|
521
579
|
case 'retrieveFineTune':
|
|
522
|
-
case 'fine_tuning.jobs.retrieve':
|
|
523
|
-
case 'fine-tune.retrieve':
|
|
524
580
|
case 'cancelFineTune':
|
|
525
|
-
case 'fine_tuning.jobs.cancel':
|
|
526
|
-
case 'fine-tune.cancel':
|
|
527
581
|
commonFineTuneResponseExtraction(tags, body)
|
|
528
582
|
break
|
|
529
583
|
|
|
530
584
|
case 'createTranscription':
|
|
531
|
-
case 'audio.transcriptions.create':
|
|
532
585
|
case 'createTranslation':
|
|
533
|
-
case 'audio.translations.create':
|
|
534
586
|
createAudioResponseExtraction(tags, body)
|
|
535
587
|
break
|
|
536
588
|
|
|
537
589
|
case 'createImage':
|
|
538
|
-
case 'images.generate':
|
|
539
590
|
case 'createImageEdit':
|
|
540
|
-
case 'images.edit':
|
|
541
591
|
case 'createImageVariation':
|
|
542
|
-
case 'images.createVariation':
|
|
543
592
|
commonImageResponseExtraction(tags, body)
|
|
544
593
|
break
|
|
545
594
|
|
|
546
595
|
case 'listModels':
|
|
547
|
-
case 'models.list':
|
|
548
596
|
listModelsResponseExtraction(tags, body)
|
|
549
597
|
break
|
|
550
598
|
|
|
551
599
|
case 'retrieveModel':
|
|
552
|
-
case 'models.retrieve':
|
|
553
600
|
retrieveModelResponseExtraction(tags, body)
|
|
554
601
|
break
|
|
555
602
|
}
|
|
@@ -641,8 +688,8 @@ function commonFineTuneResponseExtraction (tags, body) {
|
|
|
641
688
|
|
|
642
689
|
// the OpenAI package appears to stream the content download then provide it all as a singular string
|
|
643
690
|
function downloadFileResponseExtraction (tags, body) {
|
|
644
|
-
if (
|
|
645
|
-
tags['openai.response.total_bytes'] = body.file
|
|
691
|
+
if (typeof body.file !== 'string') return
|
|
692
|
+
tags['openai.response.total_bytes'] = Buffer.byteLength(body.file)
|
|
646
693
|
}
|
|
647
694
|
|
|
648
695
|
function deleteFileResponseExtraction (tags, body) {
|
|
@@ -763,7 +810,7 @@ function usageExtraction (tags, body, methodName, openaiStore) {
|
|
|
763
810
|
promptTokens = body.usage.prompt_tokens
|
|
764
811
|
completionTokens = body.usage.completion_tokens
|
|
765
812
|
totalTokens = body.usage.total_tokens
|
|
766
|
-
} else if (body.model && ['
|
|
813
|
+
} else if (body.model && ['createChatCompletion', 'createCompletion'].includes(methodName)) {
|
|
767
814
|
// estimate tokens based on method name for completions and chat completions
|
|
768
815
|
const { model } = body
|
|
769
816
|
|
|
@@ -819,8 +866,6 @@ function tagChatCompletionRequestContent (contents, messageIdx, tags) {
|
|
|
819
866
|
function coerceResponseBody (body, methodName) {
|
|
820
867
|
switch (methodName) {
|
|
821
868
|
case 'downloadFile':
|
|
822
|
-
case 'files.retrieveContent':
|
|
823
|
-
case 'files.content':
|
|
824
869
|
return { file: body }
|
|
825
870
|
}
|
|
826
871
|
|
|
@@ -839,42 +884,42 @@ function coerceResponseBody (body, methodName) {
|
|
|
839
884
|
}
|
|
840
885
|
|
|
841
886
|
// This method is used to replace a dynamic URL segment with an asterisk
|
|
842
|
-
function lookupOperationEndpoint (operationId, url) {
|
|
887
|
+
function lookupOperationEndpoint (operationId, methodName, url) {
|
|
843
888
|
switch (operationId) {
|
|
844
889
|
case 'deleteModel':
|
|
845
|
-
case 'models.del':
|
|
846
890
|
case 'retrieveModel':
|
|
847
|
-
case 'models.retrieve':
|
|
848
891
|
return '/v1/models/*'
|
|
849
892
|
|
|
850
893
|
case 'deleteFile':
|
|
851
|
-
case 'files.del':
|
|
852
894
|
case 'retrieveFile':
|
|
853
|
-
case 'files.retrieve':
|
|
854
895
|
return '/v1/files/*'
|
|
855
896
|
|
|
856
897
|
case 'downloadFile':
|
|
857
|
-
case 'files.retrieveContent':
|
|
858
|
-
case 'files.content':
|
|
859
898
|
return '/v1/files/*/content'
|
|
860
899
|
|
|
861
900
|
case 'retrieveFineTune':
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
901
|
+
switch (methodName) {
|
|
902
|
+
case 'fine_tuning.jobs.retrieve':
|
|
903
|
+
return '/v1/fine_tuning/jobs/*'
|
|
904
|
+
default:
|
|
905
|
+
return '/v1/fine-tunes/*'
|
|
906
|
+
}
|
|
866
907
|
|
|
867
908
|
case 'listFineTuneEvents':
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
909
|
+
switch (methodName) {
|
|
910
|
+
case 'fine_tuning.jobs.listEvents':
|
|
911
|
+
return '/v1/fine_tuning/jobs/*/events'
|
|
912
|
+
default:
|
|
913
|
+
return '/v1/fine-tunes/*/events'
|
|
914
|
+
}
|
|
872
915
|
|
|
873
916
|
case 'cancelFineTune':
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
917
|
+
switch (methodName) {
|
|
918
|
+
case 'fine_tuning.jobs.cancel':
|
|
919
|
+
return '/v1/fine_tuning/jobs/*/cancel'
|
|
920
|
+
default:
|
|
921
|
+
return '/v1/fine-tunes/*/cancel'
|
|
922
|
+
}
|
|
878
923
|
}
|
|
879
924
|
|
|
880
925
|
return url
|
|
@@ -909,6 +954,7 @@ function normalizeRequestPayload (methodName, args) {
|
|
|
909
954
|
|
|
910
955
|
case 'deleteFile':
|
|
911
956
|
case 'files.del':
|
|
957
|
+
case 'files.delete':
|
|
912
958
|
case 'retrieveFile':
|
|
913
959
|
case 'files.retrieve':
|
|
914
960
|
case 'downloadFile':
|
|
@@ -929,6 +975,7 @@ function normalizeRequestPayload (methodName, args) {
|
|
|
929
975
|
case 'fine-tune.retrieve':
|
|
930
976
|
case 'deleteModel':
|
|
931
977
|
case 'models.del':
|
|
978
|
+
case 'models.delete':
|
|
932
979
|
case 'cancelFineTune':
|
|
933
980
|
case 'fine_tuning.jobs.cancel':
|
|
934
981
|
case 'fine-tune.cancel':
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const StructuredLogPlugin = require('../../dd-trace/src/plugins/structured_log_plugin')
|
|
4
4
|
|
|
5
|
-
class PinoPlugin extends
|
|
5
|
+
class PinoPlugin extends StructuredLogPlugin {
|
|
6
6
|
static get id () {
|
|
7
7
|
return 'pino'
|
|
8
8
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const DatabasePlugin = require('../../dd-trace/src/plugins/database')
|
|
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
|
+
}
|
|
10
|
+
|
|
11
|
+
bindStart (ctx) {
|
|
12
|
+
const service = this.serviceName({ pluginConfig: this.config })
|
|
13
|
+
const resource = formatResourceName(ctx.resourceName, ctx.attributes)
|
|
14
|
+
|
|
15
|
+
const options = { service, resource }
|
|
16
|
+
|
|
17
|
+
if (ctx.resourceName === 'operation') {
|
|
18
|
+
options.meta = {
|
|
19
|
+
prisma: {
|
|
20
|
+
method: ctx.attributes.method,
|
|
21
|
+
model: ctx.attributes.model,
|
|
22
|
+
type: 'client'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const operationName = this.operationName({ operation: this.operation })
|
|
27
|
+
this.startSpan(operationName, options, ctx)
|
|
28
|
+
|
|
29
|
+
return ctx.currentStore
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
end (ctx) {
|
|
33
|
+
// Only synchronous operations would have `result` on `end`.
|
|
34
|
+
if (Object.hasOwn(ctx, 'result')) {
|
|
35
|
+
this.finish(ctx)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
bindAsyncStart (ctx) {
|
|
40
|
+
return this.bindFinish(ctx)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
asyncStart (ctx) {
|
|
44
|
+
this.finish(ctx)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
error (error) {
|
|
48
|
+
this.addError(error)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function formatResourceName (resource, attributes) {
|
|
53
|
+
if (attributes?.name) {
|
|
54
|
+
return `${attributes.name}`.trim()
|
|
55
|
+
}
|
|
56
|
+
if (attributes?.model && attributes.method) {
|
|
57
|
+
return `${attributes.model}.${attributes.method}`.trim()
|
|
58
|
+
}
|
|
59
|
+
return resource
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = PrismaClientPlugin
|