dd-trace 5.97.0 → 5.99.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.
- package/LICENSE-3rdparty.csv +0 -1
- package/ext/tags.js +1 -0
- package/index.d.ts +35 -3
- package/package.json +48 -46
- package/packages/datadog-instrumentations/src/crypto.js +45 -0
- package/packages/datadog-instrumentations/src/cucumber.js +65 -3
- package/packages/datadog-instrumentations/src/cypress-config.js +153 -53
- package/packages/datadog-instrumentations/src/dns.js +24 -56
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +74 -0
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +4 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +10 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +59 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +11 -2
- package/packages/datadog-instrumentations/src/jest.js +104 -12
- package/packages/datadog-instrumentations/src/mocha/utils.js +8 -0
- package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +4 -28
- package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +27 -0
- package/packages/datadog-instrumentations/src/playwright.js +5 -17
- package/packages/datadog-instrumentations/src/redis.js +12 -6
- package/packages/datadog-instrumentations/src/stripe.js +38 -24
- package/packages/datadog-instrumentations/src/vitest.js +32 -4
- package/packages/datadog-instrumentations/src/zlib.js +29 -0
- package/packages/datadog-plugin-aws-sdk/src/base.js +2 -3
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +8 -15
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -9
- package/packages/datadog-plugin-cucumber/src/index.js +8 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +114 -6
- package/packages/datadog-plugin-cypress/src/index.js +59 -2
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +48 -1
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +21 -13
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +10 -2
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +1 -2
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/index.js +24 -0
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +55 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +4 -9
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +8 -2
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-playwright/src/index.js +2 -3
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +14 -6
- package/packages/datadog-plugin-ws/src/close.js +3 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -0
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/dd-trace/src/aiguard/channels.js +8 -0
- package/packages/dd-trace/src/aiguard/index.js +7 -3
- package/packages/dd-trace/src/aiguard/sdk.js +66 -22
- package/packages/dd-trace/src/aiguard/tags.js +1 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
- package/packages/dd-trace/src/appsec/blocking.js +62 -34
- package/packages/dd-trace/src/appsec/graphql.js +6 -6
- package/packages/dd-trace/src/appsec/index.js +9 -11
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +4 -5
- package/packages/dd-trace/src/appsec/rasp/lfi.js +8 -4
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +5 -10
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +5 -6
- package/packages/dd-trace/src/appsec/recommended.json +2438 -13
- package/packages/dd-trace/src/appsec/reporter.js +6 -5
- package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +6 -10
- package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
- package/packages/dd-trace/src/appsec/store.js +50 -0
- package/packages/dd-trace/src/appsec/waf/index.js +3 -5
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
- 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 +3 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -5
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +3 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +6 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +2 -2
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
- package/packages/dd-trace/src/config/config-types.d.ts +0 -4
- package/packages/dd-trace/src/config/defaults.js +10 -11
- package/packages/dd-trace/src/config/generated-config-types.d.ts +14 -8
- package/packages/dd-trace/src/config/index.js +49 -32
- package/packages/dd-trace/src/config/parsers.js +26 -9
- package/packages/dd-trace/src/config/supported-configurations.json +86 -33
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/debugger/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +25 -5
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
- package/packages/dd-trace/src/encode/0.4.js +11 -11
- package/packages/dd-trace/src/encode/span-stats.js +4 -1
- package/packages/dd-trace/src/exporters/agent/index.js +0 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -2
- package/packages/dd-trace/src/exporters/agentless/writer.js +3 -3
- package/packages/dd-trace/src/exporters/common/util.js +2 -2
- package/packages/dd-trace/src/id.js +2 -0
- package/packages/dd-trace/src/index.js +2 -5
- package/packages/dd-trace/src/lambda/handler.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/{anthropic.js → anthropic/index.js} +5 -63
- package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +106 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +3 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +0 -49
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/messages.js +76 -0
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -26
- package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/index.js +68 -0
- package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +57 -0
- package/packages/dd-trace/src/llmobs/sdk.js +2 -2
- package/packages/dd-trace/src/log/index.js +0 -10
- package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +103 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +19 -51
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
- package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
- package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +70 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +74 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +342 -0
- package/packages/dd-trace/src/opentelemetry/tracer.js +9 -11
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -10
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/tracer.js +17 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +6 -11
- package/packages/dd-trace/src/plugins/storage.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +22 -5
- package/packages/dd-trace/src/plugins/util/test.js +128 -5
- package/packages/dd-trace/src/plugins/util/url.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +6 -88
- package/packages/dd-trace/src/profiling/profiler.js +34 -77
- package/packages/dd-trace/src/profiling/profilers/event_plugins/crypto.js +32 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/zlib.js +19 -0
- package/packages/dd-trace/src/profiling/profilers/events.js +35 -0
- package/packages/dd-trace/src/proxy.js +3 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -13
- package/packages/dd-trace/src/service-naming/index.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +21 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
- package/packages/dd-trace/src/span_processor.js +1 -2
- package/packages/dd-trace/src/span_stats.js +5 -1
- package/packages/dd-trace/src/tagger.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +5 -7
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
- package/vendor/dist/protobufjs/index.js +1 -1
- package/packages/dd-trace/src/log/utils.js +0 -16
- package/vendor/dist/ignore/LICENSE +0 -21
- package/vendor/dist/ignore/index.js +0 -1
|
@@ -31,7 +31,7 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
_encodeStat (bytes, stat) {
|
|
34
|
-
this._encodeMapPrefix(bytes,
|
|
34
|
+
this._encodeMapPrefix(bytes, 15)
|
|
35
35
|
|
|
36
36
|
this._encodeString(bytes, 'Service')
|
|
37
37
|
const service = stat.Service || DEFAULT_SERVICE_NAME
|
|
@@ -76,6 +76,9 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
76
76
|
|
|
77
77
|
this._encodeString(bytes, 'HTTPEndpoint')
|
|
78
78
|
this._encodeString(bytes, stat.HTTPEndpoint)
|
|
79
|
+
|
|
80
|
+
this._encodeString(bytes, 'srv_src')
|
|
81
|
+
this._encodeString(bytes, stat.srv_src || '')
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
_encodeBucket (bytes, bucket) {
|
|
@@ -20,14 +20,13 @@ class AgentWriter extends BaseWriter {
|
|
|
20
20
|
...args[0],
|
|
21
21
|
beforeFirstFlush: () => firstFlushChannel.publish(),
|
|
22
22
|
})
|
|
23
|
-
const { prioritySampler, lookup, protocolVersion, headers
|
|
23
|
+
const { prioritySampler, lookup, protocolVersion, headers } = args[0]
|
|
24
24
|
const AgentEncoder = getEncoder(protocolVersion)
|
|
25
25
|
|
|
26
26
|
this._prioritySampler = prioritySampler
|
|
27
27
|
this._lookup = lookup
|
|
28
28
|
this._protocolVersion = protocolVersion
|
|
29
29
|
this._headers = headers
|
|
30
|
-
this._config = config
|
|
31
30
|
this._encoder = new AgentEncoder(this)
|
|
32
31
|
}
|
|
33
32
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const getConfig = require('../../config')
|
|
4
4
|
const log = require('../../log')
|
|
5
5
|
const request = require('../common/request')
|
|
6
6
|
const tracerVersion = require('../../../../../package.json').version
|
|
@@ -39,7 +39,7 @@ class AgentlessWriter extends BaseWriter {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
if (!
|
|
42
|
+
if (!getConfig().apiKey) {
|
|
43
43
|
this.#apiKeyMissing = true
|
|
44
44
|
log.error('DD_API_KEY is required for agentless trace intake. Set DD_API_KEY. Traces will not be sent.')
|
|
45
45
|
}
|
|
@@ -108,7 +108,7 @@ class AgentlessWriter extends BaseWriter {
|
|
|
108
108
|
return
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const apiKey =
|
|
111
|
+
const apiKey = getConfig().apiKey
|
|
112
112
|
if (!apiKey) {
|
|
113
113
|
if (!this.#apiKeyMissing) {
|
|
114
114
|
this.#apiKeyMissing = true
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const getConfig = require('../../config')
|
|
4
4
|
|
|
5
5
|
function safeJSONStringify (value) {
|
|
6
6
|
return JSON.stringify(
|
|
7
7
|
value,
|
|
8
8
|
(key, value) => key === 'dd-api-key' ? undefined : value,
|
|
9
|
-
|
|
9
|
+
getConfig().DD_TRACE_BEAUTIFUL_LOGS ? 2 : undefined
|
|
10
10
|
)
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { getValueFromEnvSources } = require('./config/helper')
|
|
4
|
-
const { isFalse
|
|
4
|
+
const { isFalse } = require('./util')
|
|
5
5
|
|
|
6
6
|
// Global `jest` is only present in Jest workers.
|
|
7
7
|
const inJestWorker = typeof jest !== 'undefined'
|
|
@@ -9,10 +9,7 @@ const inJestWorker = typeof jest !== 'undefined'
|
|
|
9
9
|
const ddTraceDisabled = getValueFromEnvSources('DD_TRACE_ENABLED')
|
|
10
10
|
? isFalse(getValueFromEnvSources('DD_TRACE_ENABLED'))
|
|
11
11
|
: String(getValueFromEnvSources('OTEL_TRACES_EXPORTER')).toLowerCase() === 'none'
|
|
12
|
-
const shouldUseProxyWhenTracingDisabled =
|
|
13
|
-
isTrue(getValueFromEnvSources('DD_DYNAMIC_INSTRUMENTATION_ENABLED')) ||
|
|
14
|
-
isTrue(getValueFromEnvSources('DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED'))
|
|
15
12
|
|
|
16
|
-
module.exports =
|
|
13
|
+
module.exports = ddTraceDisabled || inJestWorker
|
|
17
14
|
? require('./noop/proxy')
|
|
18
15
|
: require('./proxy')
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const log = require('../log')
|
|
4
4
|
const { channel } = require('../../../datadog-instrumentations/src/helpers/instrument')
|
|
5
5
|
const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
|
|
6
|
-
const { getValueFromEnvSources } = require('../config/helper')
|
|
7
6
|
const { ImpendingTimeout } = require('./runtime/errors')
|
|
8
7
|
const { extractContext } = require('./context')
|
|
9
8
|
|
|
@@ -27,8 +26,7 @@ let __lambdaTimeout
|
|
|
27
26
|
function checkTimeout (context) {
|
|
28
27
|
const remainingTimeInMillis = context.getRemainingTimeInMillis()
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
apmFlushDeadline = apmFlushDeadline < 0 ? 100 : apmFlushDeadline
|
|
29
|
+
const apmFlushDeadline = tracer._config.DD_APM_FLUSH_DEADLINE_MILLISECONDS
|
|
32
30
|
|
|
33
31
|
__lambdaTimeout = setTimeout(() => {
|
|
34
32
|
timeoutChannel.publish()
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { UNKNOWN_MODEL_PROVIDER } = require('
|
|
4
|
-
const LLMObsPlugin = require('
|
|
3
|
+
const { UNKNOWN_MODEL_PROVIDER } = require('../../constants/tags')
|
|
4
|
+
const LLMObsPlugin = require('../base')
|
|
5
|
+
const { appendMessage } = require('./util')
|
|
5
6
|
|
|
6
7
|
const ALLOWED_METADATA_KEYS = new Set([
|
|
7
8
|
'max_tokens',
|
|
@@ -144,51 +145,11 @@ class AnthropicLLMObsPlugin extends LLMObsPlugin {
|
|
|
144
145
|
const inputMessages = []
|
|
145
146
|
|
|
146
147
|
if (system) {
|
|
147
|
-
|
|
148
|
+
appendMessage(inputMessages, { role: 'system', content: system })
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
for (const message of messages) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (typeof content === 'string') {
|
|
154
|
-
inputMessages.push({ content, role })
|
|
155
|
-
continue
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
for (const block of content) {
|
|
159
|
-
if (block.type === 'text') {
|
|
160
|
-
inputMessages.push({ content: block.text, role })
|
|
161
|
-
} else if (block.type === 'image') {
|
|
162
|
-
inputMessages.push({ content: '([IMAGE DETECTED])', role })
|
|
163
|
-
} else if (block.type === 'tool_use') {
|
|
164
|
-
const { text, name, id, type } = block
|
|
165
|
-
let input = block.input
|
|
166
|
-
if (typeof input === 'string') {
|
|
167
|
-
input = JSON.parse(input)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const toolCall = {
|
|
171
|
-
name,
|
|
172
|
-
arguments: input,
|
|
173
|
-
toolId: id,
|
|
174
|
-
type,
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
inputMessages.push({ content: text ?? '', role, toolCalls: [toolCall] })
|
|
178
|
-
} else if (block.type === 'tool_result') {
|
|
179
|
-
const { content } = block
|
|
180
|
-
const formattedContent = this.#formatAnthropicToolResultContent(content)
|
|
181
|
-
const toolResult = {
|
|
182
|
-
result: formattedContent,
|
|
183
|
-
toolId: block.tool_use_id,
|
|
184
|
-
type: 'tool_result',
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
inputMessages.push({ content: '', role, toolResults: [toolResult] })
|
|
188
|
-
} else {
|
|
189
|
-
inputMessages.push({ content: JSON.stringify(block), role })
|
|
190
|
-
}
|
|
191
|
-
}
|
|
152
|
+
appendMessage(inputMessages, message)
|
|
192
153
|
}
|
|
193
154
|
|
|
194
155
|
this._tagger.tagLLMIO(span, inputMessages)
|
|
@@ -273,25 +234,6 @@ class AnthropicLLMObsPlugin extends LLMObsPlugin {
|
|
|
273
234
|
|
|
274
235
|
this._tagger.tagMetrics(span, metrics)
|
|
275
236
|
}
|
|
276
|
-
|
|
277
|
-
// maybe can make into a util file
|
|
278
|
-
#formatAnthropicToolResultContent (content) {
|
|
279
|
-
if (typeof content === 'string') {
|
|
280
|
-
return content
|
|
281
|
-
} else if (Array.isArray(content)) {
|
|
282
|
-
const formattedContent = []
|
|
283
|
-
for (const toolResultBlock of content) {
|
|
284
|
-
if (toolResultBlock.text) {
|
|
285
|
-
formattedContent.push(toolResultBlock.text)
|
|
286
|
-
} else if (toolResultBlock.type === 'image') {
|
|
287
|
-
formattedContent.push('([IMAGE DETECTED])')
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return formattedContent.join(',')
|
|
292
|
-
}
|
|
293
|
-
return JSON.stringify(content)
|
|
294
|
-
}
|
|
295
237
|
}
|
|
296
238
|
|
|
297
239
|
module.exports = AnthropicLLMObsPlugin
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {{type: 'text', text: string}} TextBlock
|
|
5
|
+
* @typedef {{type: 'image'}} ImageBlock
|
|
6
|
+
* @typedef {{
|
|
7
|
+
* type: 'tool_use', text: string, name: string, id: string, input: string | Record<string, unknown>
|
|
8
|
+
* }} ToolUseBlock
|
|
9
|
+
* @typedef {{
|
|
10
|
+
* type: 'tool_result',
|
|
11
|
+
* tool_use_id: string,
|
|
12
|
+
* content: string | Array<{type: string, text?: string}>
|
|
13
|
+
* }} ToolResultBlock
|
|
14
|
+
*
|
|
15
|
+
* @typedef {{
|
|
16
|
+
* content: string,
|
|
17
|
+
* role: string,
|
|
18
|
+
* toolCalls?: Array<{
|
|
19
|
+
* name: string,
|
|
20
|
+
* arguments: string | Record<string, unknown>,
|
|
21
|
+
* toolId: string,
|
|
22
|
+
* type: string
|
|
23
|
+
* }>,
|
|
24
|
+
* toolResults?: Array<{
|
|
25
|
+
* result: string,
|
|
26
|
+
* toolId: string,
|
|
27
|
+
* type: 'tool_result'
|
|
28
|
+
* }>
|
|
29
|
+
* }} AnthropicLlmObsMessage
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Formats tool result into LLM Observability compatible contents
|
|
34
|
+
* @param {ToolResultBlock['content']} content
|
|
35
|
+
*/
|
|
36
|
+
function formatAnthropicToolResultContent (content) {
|
|
37
|
+
if (typeof content === 'string') {
|
|
38
|
+
return content
|
|
39
|
+
} else if (Array.isArray(content)) {
|
|
40
|
+
const formattedContent = []
|
|
41
|
+
for (const toolResultBlock of content) {
|
|
42
|
+
if (toolResultBlock.text) {
|
|
43
|
+
formattedContent.push(toolResultBlock.text)
|
|
44
|
+
} else if (toolResultBlock.type === 'image') {
|
|
45
|
+
formattedContent.push('([IMAGE DETECTED])')
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return formattedContent.join(',')
|
|
50
|
+
}
|
|
51
|
+
return JSON.stringify(content)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Normalizes and formats a message into LLM Observability compatible contents.
|
|
56
|
+
* Can be spread into a list of other messages.
|
|
57
|
+
*
|
|
58
|
+
* @param {AnthropicLlmObsMessage[]} messages
|
|
59
|
+
* @param {{ role: string, content: string | Array<TextBlock | ImageBlock | ToolUseBlock | ToolResultBlock> }} message
|
|
60
|
+
* @returns {void}
|
|
61
|
+
*/
|
|
62
|
+
function appendMessage (messages, { role, content }) {
|
|
63
|
+
if (typeof content === 'string') {
|
|
64
|
+
messages.push({ content, role })
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const block of content) {
|
|
69
|
+
if (block.type === 'text') {
|
|
70
|
+
messages.push({ content: block.text, role })
|
|
71
|
+
} else if (block.type === 'image') {
|
|
72
|
+
messages.push({ content: '([IMAGE DETECTED])', role })
|
|
73
|
+
} else if (block.type === 'tool_use') {
|
|
74
|
+
const { text, name, id, type } = block
|
|
75
|
+
let input = block.input
|
|
76
|
+
if (typeof input === 'string') {
|
|
77
|
+
input = JSON.parse(input)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const toolCall = {
|
|
81
|
+
name,
|
|
82
|
+
arguments: input,
|
|
83
|
+
toolId: id,
|
|
84
|
+
type,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
messages.push({ content: text ?? '', role, toolCalls: [toolCall] })
|
|
88
|
+
} else if (block.type === 'tool_result') {
|
|
89
|
+
const { content } = block
|
|
90
|
+
const formattedContent = formatAnthropicToolResultContent(content)
|
|
91
|
+
const toolResult = {
|
|
92
|
+
result: formattedContent,
|
|
93
|
+
toolId: block.tool_use_id,
|
|
94
|
+
type: 'tool_result',
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
messages.push({ content: '', role, toolResults: [toolResult] })
|
|
98
|
+
} else {
|
|
99
|
+
messages.push({ content: JSON.stringify(block), role })
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
appendMessage,
|
|
106
|
+
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { spanHasError } = require('../../../util')
|
|
4
|
+
const { formatIO } = require('../messages')
|
|
4
5
|
const LangChainLLMObsHandler = require('.')
|
|
5
6
|
|
|
6
7
|
class LangChainLLMObsChainHandler extends LangChainLLMObsHandler {
|
|
7
8
|
setMetaTags ({ span, inputs, results }) {
|
|
8
9
|
let input
|
|
9
10
|
if (inputs) {
|
|
10
|
-
input =
|
|
11
|
+
input = formatIO(inputs)
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const output = !results || spanHasError(span) ? '' :
|
|
14
|
+
const output = !results || spanHasError(span) ? '' : formatIO(results)
|
|
14
15
|
|
|
15
16
|
// chain spans will always be workflows
|
|
16
17
|
this._tagger.tagTextIO(span, input, output)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const LLMObsTagger = require('../../../tagger')
|
|
4
4
|
const { spanHasError } = require('../../../util')
|
|
5
|
+
const { getRole } = require('../messages')
|
|
5
6
|
const LangChainLLMObsHandler = require('.')
|
|
6
7
|
|
|
7
8
|
const LLM = 'llm'
|
|
@@ -22,7 +23,7 @@ class LangChainLLMObsChatModelHandler extends LangChainLLMObsHandler {
|
|
|
22
23
|
for (const messageSet of inputs) {
|
|
23
24
|
for (const message of messageSet) {
|
|
24
25
|
const content = message.content || ''
|
|
25
|
-
const role =
|
|
26
|
+
const role = getRole(message)
|
|
26
27
|
inputMessages.push({ content, role })
|
|
27
28
|
}
|
|
28
29
|
}
|
|
@@ -54,7 +55,7 @@ class LangChainLLMObsChatModelHandler extends LangChainLLMObsHandler {
|
|
|
54
55
|
for (const messageSet of results.generations) {
|
|
55
56
|
for (const chatCompletion of messageSet) {
|
|
56
57
|
const chatCompletionMessage = chatCompletion.message
|
|
57
|
-
const role =
|
|
58
|
+
const role = getRole(chatCompletionMessage)
|
|
58
59
|
const content = chatCompletionMessage.text || ''
|
|
59
60
|
const toolCalls = this.extractToolCalls(chatCompletionMessage)
|
|
60
61
|
outputMessages.push({ content, role, toolCalls })
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const LLMObsTagger = require('../../../tagger')
|
|
4
4
|
const { spanHasError } = require('../../../util')
|
|
5
|
+
const { formatIO } = require('../messages')
|
|
5
6
|
const LangChainLLMObsHandler = require('.')
|
|
6
7
|
|
|
7
8
|
class LangChainLLMObsEmbeddingHandler extends LangChainLLMObsHandler {
|
|
@@ -10,7 +11,7 @@ class LangChainLLMObsEmbeddingHandler extends LangChainLLMObsHandler {
|
|
|
10
11
|
let embeddingInput, embeddingOutput
|
|
11
12
|
|
|
12
13
|
if (isWorkflow) {
|
|
13
|
-
embeddingInput =
|
|
14
|
+
embeddingInput = formatIO(inputs)
|
|
14
15
|
} else {
|
|
15
16
|
const input = Array.isArray(inputs) ? inputs : [inputs]
|
|
16
17
|
embeddingInput = input.map(doc => ({ text: doc }))
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const ROLE_MAPPINGS = {
|
|
4
|
-
human: 'user',
|
|
5
|
-
ai: 'assistant',
|
|
6
|
-
system: 'system',
|
|
7
|
-
}
|
|
8
|
-
|
|
9
3
|
class LangChainLLMObsHandler {
|
|
10
4
|
constructor (tagger) {
|
|
11
5
|
/** @type {import('../../../tagger')} */
|
|
@@ -18,38 +12,6 @@ class LangChainLLMObsHandler {
|
|
|
18
12
|
|
|
19
13
|
setMetaTags () {}
|
|
20
14
|
|
|
21
|
-
formatIO (messages) {
|
|
22
|
-
if (messages.constructor.name === 'Object') { // plain JSON
|
|
23
|
-
const formatted = {}
|
|
24
|
-
for (const [key, value] of Object.entries(messages)) {
|
|
25
|
-
formatted[key] = this.formatIO(value)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return formatted
|
|
29
|
-
} else if (Array.isArray(messages)) {
|
|
30
|
-
return messages.map(message => this.formatIO(message))
|
|
31
|
-
} // either a BaseMesage type or a string
|
|
32
|
-
return this.getContentFromMessage(messages)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getContentFromMessage (message) {
|
|
36
|
-
if (typeof message === 'string') {
|
|
37
|
-
return message
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const messageContent = {
|
|
41
|
-
content: message.content || '',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const role = this.getRole(message)
|
|
45
|
-
if (role) messageContent.role = role
|
|
46
|
-
|
|
47
|
-
return messageContent
|
|
48
|
-
} catch {
|
|
49
|
-
return JSON.stringify(message)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
15
|
checkTokenUsageChatOrLLMResult (results) {
|
|
54
16
|
const llmOutput = results.llmOutput
|
|
55
17
|
const tokens = {
|
|
@@ -90,17 +52,6 @@ class LangChainLLMObsHandler {
|
|
|
90
52
|
runId: runIdBase,
|
|
91
53
|
}
|
|
92
54
|
}
|
|
93
|
-
|
|
94
|
-
getRole (message) {
|
|
95
|
-
if (message.role) return ROLE_MAPPINGS[message.role] || message.role
|
|
96
|
-
|
|
97
|
-
const type = (
|
|
98
|
-
(typeof message.getType === 'function' && message.getType()) ||
|
|
99
|
-
(typeof message._getType === 'function' && message._getType())
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
return ROLE_MAPPINGS[type] || type
|
|
103
|
-
}
|
|
104
55
|
}
|
|
105
56
|
|
|
106
57
|
module.exports = LangChainLLMObsHandler
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { spanHasError } = require('../../../util')
|
|
4
|
+
const { formatIO } = require('../messages')
|
|
4
5
|
const LangChainLLMObsHandler = require('.')
|
|
5
6
|
|
|
6
7
|
class LangChainLLMObsVectorStoreHandler extends LangChainLLMObsHandler {
|
|
7
8
|
setMetaTags ({ span, inputs, results }) {
|
|
8
|
-
const input =
|
|
9
|
+
const input = formatIO(inputs)
|
|
9
10
|
if (spanHasError(span)) {
|
|
10
11
|
this._tagger.tagRetrievalIO(span, input)
|
|
11
12
|
return
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const ROLE_MAPPINGS = {
|
|
4
|
+
human: 'user',
|
|
5
|
+
ai: 'assistant',
|
|
6
|
+
system: 'system',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function getRole (message) {
|
|
10
|
+
if (message.role) return ROLE_MAPPINGS[message.role] || message.role
|
|
11
|
+
|
|
12
|
+
const type = (
|
|
13
|
+
(typeof message.getType === 'function' && message.getType()) ||
|
|
14
|
+
(typeof message._getType === 'function' && message._getType())
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
return ROLE_MAPPINGS[type] || type
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getContentFromMessage (message) {
|
|
21
|
+
if (typeof message === 'string') {
|
|
22
|
+
return message
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const messageContent = {
|
|
26
|
+
content: message.content || '',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const role = getRole(message)
|
|
30
|
+
if (role) messageContent.role = role
|
|
31
|
+
|
|
32
|
+
return messageContent
|
|
33
|
+
} catch {
|
|
34
|
+
return JSON.stringify(message)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isBaseMessage (data) {
|
|
39
|
+
return typeof data._getType === 'function' || typeof data.getType === 'function'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function formatIO (data) {
|
|
43
|
+
if (data == null) return ''
|
|
44
|
+
|
|
45
|
+
if (typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean') {
|
|
46
|
+
return data
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (data.constructor?.name === 'Object') {
|
|
50
|
+
const formatted = {}
|
|
51
|
+
for (const [key, value] of Object.entries(data)) {
|
|
52
|
+
formatted[key] = formatIO(value)
|
|
53
|
+
}
|
|
54
|
+
return formatted
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (Array.isArray(data)) {
|
|
58
|
+
return data.map(item => formatIO(item))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Only duck-typed BaseMessage instances collapse to { content, role }.
|
|
62
|
+
// Other class instances (e.g. LangChain Document) preserve their shape via JSON.stringify,
|
|
63
|
+
// otherwise they'd reduce to { content: '' } and lose data.
|
|
64
|
+
if (isBaseMessage(data)) return getContentFromMessage(data)
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
return JSON.stringify(data)
|
|
68
|
+
} catch {
|
|
69
|
+
return String(data)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
getRole,
|
|
75
|
+
formatIO,
|
|
76
|
+
}
|
|
@@ -1,36 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const LLMObsPlugin = require('../base')
|
|
4
|
+
const { formatIO } = require('../langchain/messages')
|
|
4
5
|
const { spanHasError } = require('../../util')
|
|
5
6
|
|
|
6
7
|
const streamDataMap = new WeakMap()
|
|
7
8
|
|
|
8
|
-
function formatIO (data) {
|
|
9
|
-
if (data == null) return ''
|
|
10
|
-
|
|
11
|
-
if (typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean') {
|
|
12
|
-
return data
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (data.constructor?.name === 'Object') {
|
|
16
|
-
const formatted = {}
|
|
17
|
-
for (const [key, value] of Object.entries(data)) {
|
|
18
|
-
formatted[key] = formatIO(value)
|
|
19
|
-
}
|
|
20
|
-
return formatted
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (Array.isArray(data)) {
|
|
24
|
-
return data.map(item => formatIO(item))
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
return JSON.stringify(data)
|
|
29
|
-
} catch {
|
|
30
|
-
return String(data)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
9
|
class PregelStreamLLMObsPlugin extends LLMObsPlugin {
|
|
35
10
|
static id = 'llmobs_langgraph_pregel_stream'
|
|
36
11
|
static integration = 'langgraph'
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const LLMObsPlugin = require('../base')
|
|
4
|
+
const { formatInput, formatOutput } = require('./utils')
|
|
5
|
+
|
|
6
|
+
class McpToolCallLLMObsPlugin extends LLMObsPlugin {
|
|
7
|
+
static id = 'llmobs_mcp_tool_call'
|
|
8
|
+
static integration = 'modelcontextprotocol-sdk'
|
|
9
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_callTool'
|
|
10
|
+
|
|
11
|
+
getLLMObsSpanRegisterOptions (ctx) {
|
|
12
|
+
const params = ctx.arguments?.[0]
|
|
13
|
+
const toolName = params?.name || 'unknown_tool'
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
kind: 'tool',
|
|
17
|
+
name: `MCP Client Tool Call: ${toolName}`,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
setLLMObsTags (ctx) {
|
|
22
|
+
const span = ctx.currentStore?.span
|
|
23
|
+
if (!span) return
|
|
24
|
+
|
|
25
|
+
const params = ctx.arguments?.[0]
|
|
26
|
+
const toolName = params?.name
|
|
27
|
+
const toolArguments = params?.arguments
|
|
28
|
+
|
|
29
|
+
const spanTags = { mcp_tool_kind: 'client' }
|
|
30
|
+
|
|
31
|
+
const serverVersion = ctx.self?.getServerVersion?.()
|
|
32
|
+
if (serverVersion) {
|
|
33
|
+
if (serverVersion.name) spanTags.mcp_server_name = serverVersion.name
|
|
34
|
+
if (serverVersion.version) spanTags.mcp_server_version = serverVersion.version
|
|
35
|
+
if (serverVersion.title) spanTags.mcp_server_title = serverVersion.title
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this._tagger.tagSpanTags(span, spanTags)
|
|
39
|
+
|
|
40
|
+
const hasError = ctx.error || ctx.result?.isError
|
|
41
|
+
const input = formatInput(toolName, toolArguments)
|
|
42
|
+
const output = hasError ? undefined : formatOutput(ctx.result)
|
|
43
|
+
|
|
44
|
+
this._tagger.tagTextIO(span, input, output)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class McpListToolsLLMObsPlugin extends LLMObsPlugin {
|
|
49
|
+
static id = 'llmobs_mcp_list_tools'
|
|
50
|
+
static integration = 'modelcontextprotocol-sdk'
|
|
51
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_listTools'
|
|
52
|
+
|
|
53
|
+
getLLMObsSpanRegisterOptions () {
|
|
54
|
+
return {
|
|
55
|
+
kind: 'task',
|
|
56
|
+
name: 'MCP Client List Tools',
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setLLMObsTags (ctx) {
|
|
61
|
+
const span = ctx.currentStore?.span
|
|
62
|
+
if (!span || ctx.error) return
|
|
63
|
+
|
|
64
|
+
this._tagger.tagTextIO(span, null, JSON.stringify(ctx.result))
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = [McpToolCallLLMObsPlugin, McpListToolsLLMObsPlugin]
|