dd-trace 6.9.0 → 6.11.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/README.md +0 -17
- package/ci/vitest-no-worker-init-setup.mjs +112 -10
- package/index.d.ts +150 -3
- package/initialize.mjs +28 -17
- package/openfeature.js +2 -2
- package/package.json +14 -10
- package/packages/datadog-esbuild/index.js +0 -34
- package/packages/datadog-instrumentations/src/anthropic.js +210 -15
- package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
- package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
- package/packages/datadog-instrumentations/src/bunyan.js +3 -16
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/cucumber.js +26 -11
- package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
- package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
- package/packages/datadog-instrumentations/src/cypress.js +2 -0
- package/packages/datadog-instrumentations/src/fastify.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +634 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/jest.js +26 -18
- package/packages/datadog-instrumentations/src/mariadb.js +278 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +540 -56
- package/packages/datadog-instrumentations/src/mocha/utils.js +132 -25
- package/packages/datadog-instrumentations/src/mysql.js +45 -15
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +116 -92
- package/packages/datadog-instrumentations/src/playwright-reporter.js +99 -0
- package/packages/datadog-instrumentations/src/playwright.js +149 -2
- package/packages/datadog-instrumentations/src/router.js +2 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
- package/packages/datadog-instrumentations/src/vitest-main.js +180 -20
- package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
- package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
- package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -13
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
- package/packages/datadog-plugin-bunyan/src/index.js +5 -8
- package/packages/datadog-plugin-cucumber/src/index.js +11 -0
- package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
- package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +82 -30
- package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
- package/packages/datadog-plugin-cypress/src/index.js +12 -6
- package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
- package/packages/datadog-plugin-electron/src/index.js +2 -0
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-jest/src/index.js +11 -4
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +606 -40
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-nats/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +1 -19
- package/packages/datadog-plugin-openai/src/tracing.js +41 -30
- package/packages/datadog-plugin-openai-agents/src/integration.js +279 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +1 -0
- package/packages/datadog-plugin-playwright/src/index.js +42 -13
- package/packages/datadog-plugin-vitest/src/index.js +14 -20
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/datadog-webpack/index.js +0 -11
- package/packages/dd-trace/index.js +0 -1
- package/packages/dd-trace/src/agent/info.js +6 -5
- package/packages/dd-trace/src/aiguard/client.js +100 -1
- package/packages/dd-trace/src/aiguard/errors.js +41 -0
- package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
- package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
- package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
- package/packages/dd-trace/src/aiguard/sdk.js +22 -278
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +27 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +6 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +7 -0
- package/packages/dd-trace/src/config/index.js +13 -2
- package/packages/dd-trace/src/config/major-overrides.js +7 -0
- package/packages/dd-trace/src/config/supported-configurations.json +24 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/index.js +2 -0
- package/packages/dd-trace/src/datastreams/manager.js +14 -3
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +16 -13
- package/packages/dd-trace/src/datastreams/size.js +5 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
- package/packages/dd-trace/src/exporters/common/writer.js +11 -6
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +163 -5
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +241 -87
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +280 -20
- package/packages/dd-trace/src/llmobs/experiments/index.js +58 -59
- package/packages/dd-trace/src/llmobs/experiments/noop.js +71 -3
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +41 -5
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/noop/proxy.js +3 -4
- package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
- package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/opentracing/tracer.js +5 -2
- package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
- package/packages/dd-trace/src/plugin_manager.js +5 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +5 -65
- package/packages/dd-trace/src/plugins/util/test.js +93 -14
- package/packages/dd-trace/src/plugins/util/web.js +56 -2
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
- package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
- package/packages/dd-trace/src/proxy.js +38 -29
- package/packages/dd-trace/src/ritm.js +9 -2
- package/packages/dd-trace/src/serverless.js +37 -0
- package/packages/dd-trace/src/span_format.js +1 -0
- package/packages/dd-trace/src/span_stats.js +30 -3
- package/packages/dd-trace/src/storage-channels.js +86 -0
- package/packages/dd-trace/src/tracer.js +9 -2
- package/packages/dd-trace/src/tracer_metadata.js +14 -1
- package/packages/dd-trace/src/web-tags-cache.js +132 -0
- package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
- package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
- package/packages/dd-trace/src/feature-registry.js +0 -29
- package/packages/dd-trace/src/openfeature/register.js +0 -35
- package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
|
@@ -1,90 +1,18 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
|
|
4
|
-
const { HTTP_CLIENT_IP, NETWORK_CLIENT_IP, HTTP_USERAGENT } = require('../../../../ext/tags')
|
|
5
|
-
const { USER_ID, USER_SESSION_ID } = require('../appsec/addresses')
|
|
6
|
-
const { getActiveRequest } = require('../appsec/store')
|
|
7
3
|
const log = require('../log')
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const { keepTrace } = require('../priority_sampler')
|
|
12
|
-
const { AI_GUARD } = require('../standalone/product')
|
|
4
|
+
const AIGuardClient = require('./client')
|
|
5
|
+
const { createEvaluationOutcome, EvaluationReporter } = require('./evaluation')
|
|
6
|
+
const { AIGuardAbortError } = require('./errors')
|
|
13
7
|
const NoopAIGuard = require('./noop')
|
|
14
|
-
const executeRequest = require('./client')
|
|
15
8
|
const TAGS = require('./tags')
|
|
16
9
|
|
|
17
|
-
const aiguardMetrics = telemetryMetrics.manager.namespace('ai_guard')
|
|
18
|
-
|
|
19
|
-
const ALLOW = 'ALLOW'
|
|
20
|
-
|
|
21
|
-
// Tags from the service entry span that must be mirrored onto every AI Guard span
|
|
22
|
-
// so anomaly detection pipelines can process each span independently.
|
|
23
|
-
const SERVICE_ENTRY_TAG_MAPPINGS = [
|
|
24
|
-
[HTTP_USERAGENT, TAGS.HTTP_USERAGENT_TAG_KEY],
|
|
25
|
-
[HTTP_CLIENT_IP, TAGS.HTTP_CLIENT_IP_TAG_KEY],
|
|
26
|
-
[NETWORK_CLIENT_IP, TAGS.NETWORK_CLIENT_IP_TAG_KEY],
|
|
27
|
-
[USER_ID, TAGS.USR_ID_TAG_KEY],
|
|
28
|
-
[USER_SESSION_ID, TAGS.USR_SESSION_ID_TAG_KEY],
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Reports a telemetry error
|
|
33
|
-
*
|
|
34
|
-
* @param {string} errorType - The error type constant (client_error, bad_status, bad_response)
|
|
35
|
-
* @param {{ source: string, integration: string }} telemetryTags - Source and integration tags
|
|
36
|
-
*/
|
|
37
|
-
function reportTelemetryError (errorType, telemetryTags) {
|
|
38
|
-
aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, { error: true, ...telemetryTags }).inc(1)
|
|
39
|
-
aiguardMetrics.count(TAGS.TELEMETRY_ERROR, { type: errorType, ...telemetryTags }).inc(1)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
class AIGuardAbortError extends Error {
|
|
43
|
-
constructor (reason, tags, tagProbs, sds) {
|
|
44
|
-
super(reason)
|
|
45
|
-
this.name = 'AIGuardAbortError'
|
|
46
|
-
this.reason = reason
|
|
47
|
-
this.tags = tags
|
|
48
|
-
this.tagProbabilities = tagProbs
|
|
49
|
-
this.sds = sds || []
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
class AIGuardClientError extends Error {
|
|
54
|
-
constructor (message, opts = {}) {
|
|
55
|
-
super(message)
|
|
56
|
-
this.name = 'AIGuardClientError'
|
|
57
|
-
if (opts.errors) {
|
|
58
|
-
this.errors = opts.errors
|
|
59
|
-
}
|
|
60
|
-
if (opts.cause) {
|
|
61
|
-
this.cause = opts.cause
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Resolves the AI Guard host for a given Datadog site. Sites with a single subdomain level
|
|
68
|
-
* (e.g. `datadoghq.com`, `ddog-gov.com`) are served from the `app.` subdomain, while regional
|
|
69
|
-
* sites (e.g. `us3.datadoghq.com`, `ap1.datadoghq.com`) are used as-is.
|
|
70
|
-
*
|
|
71
|
-
* @param {string} site - Datadog site (e.g. `datadoghq.com`, `us3.datadoghq.com`)
|
|
72
|
-
* @returns {string} The host to use for the AI Guard endpoint
|
|
73
|
-
*/
|
|
74
|
-
function aiGuardHost (site) {
|
|
75
|
-
return site.split('.').length === 2 ? `app.${site}` : site
|
|
76
|
-
}
|
|
77
|
-
|
|
78
10
|
class AIGuard extends NoopAIGuard {
|
|
79
11
|
#initialized
|
|
80
12
|
#tracer
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#timeout
|
|
84
|
-
#maxMessagesLength
|
|
85
|
-
#maxContentSize
|
|
13
|
+
#client
|
|
14
|
+
#reporter
|
|
86
15
|
#meta
|
|
87
|
-
#config
|
|
88
16
|
|
|
89
17
|
/**
|
|
90
18
|
* @param {import('../tracer')} tracer - Tracer instance
|
|
@@ -99,223 +27,39 @@ class AIGuard extends NoopAIGuard {
|
|
|
99
27
|
return
|
|
100
28
|
}
|
|
101
29
|
this.#tracer = tracer
|
|
102
|
-
this.#
|
|
103
|
-
|
|
104
|
-
'DD-APPLICATION-KEY': config.DD_APP_KEY,
|
|
105
|
-
'DD-AI-GUARD-VERSION': tracerVersion,
|
|
106
|
-
'DD-AI-GUARD-SOURCE': 'SDK',
|
|
107
|
-
'DD-AI-GUARD-LANGUAGE': 'nodejs',
|
|
108
|
-
}
|
|
109
|
-
const endpoint = config.experimental.aiguard.endpoint || `https://${aiGuardHost(config.site)}/api/v2/ai-guard`
|
|
110
|
-
this.#evaluateUrl = `${endpoint}/evaluate`
|
|
111
|
-
this.#timeout = config.experimental.aiguard.timeout
|
|
112
|
-
this.#maxMessagesLength = config.experimental.aiguard.maxMessagesLength
|
|
113
|
-
this.#maxContentSize = config.experimental.aiguard.maxContentSize
|
|
30
|
+
this.#client = new AIGuardClient(config)
|
|
31
|
+
this.#reporter = new EvaluationReporter(config)
|
|
114
32
|
this.#meta = { service: config.service, env: config.env }
|
|
115
|
-
this.#config = config
|
|
116
33
|
this.#initialized = true
|
|
117
34
|
}
|
|
118
35
|
|
|
119
|
-
/**
|
|
120
|
-
* Returns a safe copy of the messages to be serialized into the meta struct.
|
|
121
|
-
*
|
|
122
|
-
* - Clones each message so callers cannot mutate the data set in the meta struct.
|
|
123
|
-
* - Truncates the list of messages and `content` fields emitting metrics accordingly.
|
|
124
|
-
*
|
|
125
|
-
* @param {import('../../../../index').aiguard.Message[]} messages
|
|
126
|
-
* @param {{ source: string, integration: string }} telemetryTags
|
|
127
|
-
*/
|
|
128
|
-
#buildMessagesForMetaStruct (messages, telemetryTags) {
|
|
129
|
-
const size = Math.min(messages.length, this.#maxMessagesLength)
|
|
130
|
-
if (messages.length > size) {
|
|
131
|
-
aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'messages', ...telemetryTags }).inc(1)
|
|
132
|
-
}
|
|
133
|
-
const result = []
|
|
134
|
-
let contentTruncated = false
|
|
135
|
-
for (let i = messages.length - size; i < messages.length; i++) {
|
|
136
|
-
const message = rfdc(messages[i])
|
|
137
|
-
if (message.content?.length > this.#maxContentSize) {
|
|
138
|
-
contentTruncated = true
|
|
139
|
-
message.content = message.content.slice(0, this.#maxContentSize)
|
|
140
|
-
}
|
|
141
|
-
result.push(message)
|
|
142
|
-
}
|
|
143
|
-
if (contentTruncated) {
|
|
144
|
-
aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'content', ...telemetryTags }).inc(1)
|
|
145
|
-
}
|
|
146
|
-
return result
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
#isToolCall (message) {
|
|
150
|
-
return message.tool_calls || message.tool_call_id
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
#getToolName (message, history) {
|
|
154
|
-
// 1. assistant message with tool calls
|
|
155
|
-
if (message.tool_calls) {
|
|
156
|
-
const names = message.tool_calls.map((tool) => tool.function.name)
|
|
157
|
-
return names.length === 0 ? null : names.join(',')
|
|
158
|
-
}
|
|
159
|
-
// 2. assistant message with tool output (search the linked tool call in reverse order)
|
|
160
|
-
const id = message.tool_call_id
|
|
161
|
-
for (let i = history.length - 2; i >= 0; i--) {
|
|
162
|
-
const item = history[i]
|
|
163
|
-
if (item.tool_calls) {
|
|
164
|
-
for (const toolCall of item.tool_calls) {
|
|
165
|
-
if (toolCall.id === id) {
|
|
166
|
-
return toolCall.function.name
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return null
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
#setRootSpanClientIpTags (rootSpan) {
|
|
175
|
-
if (!rootSpan) return
|
|
176
|
-
|
|
177
|
-
const currentTags = rootSpan.context().getTags()
|
|
178
|
-
const needsHttpClientIp = !Object.hasOwn(currentTags, HTTP_CLIENT_IP)
|
|
179
|
-
const needsNetworkClientIp = !Object.hasOwn(currentTags, NETWORK_CLIENT_IP)
|
|
180
|
-
|
|
181
|
-
if (!needsHttpClientIp && !needsNetworkClientIp) return
|
|
182
|
-
|
|
183
|
-
const req = getActiveRequest()
|
|
184
|
-
|
|
185
|
-
if (!req) return
|
|
186
|
-
|
|
187
|
-
const newTags = {}
|
|
188
|
-
|
|
189
|
-
if (needsHttpClientIp) {
|
|
190
|
-
const clientIp = extractIp(this.#config, req)
|
|
191
|
-
|
|
192
|
-
if (clientIp) {
|
|
193
|
-
newTags[HTTP_CLIENT_IP] = clientIp
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (needsNetworkClientIp) {
|
|
198
|
-
const networkClientIp = req.socket?.remoteAddress
|
|
199
|
-
|
|
200
|
-
if (networkClientIp) {
|
|
201
|
-
newTags[NETWORK_CLIENT_IP] = networkClientIp
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (Object.keys(newTags).length > 0) {
|
|
206
|
-
rootSpan.addTags(newTags)
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Copies service entry span tags needed by anomaly detection to the AI Guard span.
|
|
212
|
-
*
|
|
213
|
-
* @param {import('../opentracing/span')} guardSpan
|
|
214
|
-
* @param {import('../opentracing/span')} rootSpan
|
|
215
|
-
*/
|
|
216
|
-
#copyServiceEntryTagsToGuardSpan (guardSpan, rootSpan) {
|
|
217
|
-
const rootTags = rootSpan.context().getTags()
|
|
218
|
-
for (const [sourceTag, destTag] of SERVICE_ENTRY_TAG_MAPPINGS) {
|
|
219
|
-
const value = rootTags[sourceTag]
|
|
220
|
-
if (value !== undefined && value !== null) {
|
|
221
|
-
guardSpan.setTag(destTag, value)
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
36
|
evaluate (messages, opts) {
|
|
227
37
|
if (!this.#initialized) {
|
|
228
38
|
return super.evaluate(messages, opts)
|
|
229
39
|
}
|
|
230
40
|
const { block = true, source = TAGS.SOURCE_SDK, integration = TAGS.INTEGRATION_NONE, childOf } = opts ?? {}
|
|
231
|
-
const telemetryTags = { source, integration }
|
|
232
41
|
// Only pass `childOf` when truthy so `tracer.trace`'s default (`scope().active()`)
|
|
233
42
|
// still applies for SDK callers that don't supply an explicit parent.
|
|
234
43
|
const traceOpts = childOf ? { childOf } : {}
|
|
235
44
|
return this.#tracer.trace(TAGS.RESOURCE, traceOpts, async (span) => {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
span.setTag(TAGS.TARGET_TAG_KEY, target)
|
|
239
|
-
if (target === 'tool') {
|
|
240
|
-
const name = this.#getToolName(last, messages)
|
|
241
|
-
if (name) {
|
|
242
|
-
span.setTag(TAGS.TOOL_NAME_TAG_KEY, name)
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const metaStruct = {
|
|
246
|
-
messages: this.#buildMessagesForMetaStruct(messages, telemetryTags),
|
|
247
|
-
}
|
|
248
|
-
span.meta_struct = {
|
|
249
|
-
[TAGS.META_STRUCT_KEY]: metaStruct,
|
|
250
|
-
}
|
|
251
|
-
const rootSpan = span.context()?._trace?.started?.[0]
|
|
252
|
-
if (rootSpan) {
|
|
253
|
-
this.#setRootSpanClientIpTags(rootSpan)
|
|
254
|
-
this.#copyServiceEntryTagsToGuardSpan(span, rootSpan)
|
|
255
|
-
// keepTrace must be called before executeRequest so the sampling decision
|
|
256
|
-
// is propagated correctly to outgoing HTTP client calls.
|
|
257
|
-
keepTrace(rootSpan, AI_GUARD)
|
|
258
|
-
rootSpan.setTag(TAGS.EVENT_TAG_KEY, 'true')
|
|
259
|
-
}
|
|
260
|
-
let response
|
|
45
|
+
const report = this.#reporter.start(span, messages, { source, integration })
|
|
46
|
+
let evaluation
|
|
261
47
|
try {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
meta: this.#meta,
|
|
267
|
-
},
|
|
268
|
-
},
|
|
269
|
-
}
|
|
270
|
-
response = await executeRequest(
|
|
271
|
-
payload,
|
|
272
|
-
{ url: this.#evaluateUrl, headers: this.#headers, timeout: this.#timeout })
|
|
273
|
-
} catch (e) {
|
|
274
|
-
reportTelemetryError(TAGS.ERROR_TYPE_CLIENT, telemetryTags)
|
|
275
|
-
throw new AIGuardClientError(`Unexpected error calling AI Guard service: ${e.message}`, { cause: e })
|
|
276
|
-
}
|
|
277
|
-
if (response.status !== 200) {
|
|
278
|
-
reportTelemetryError(TAGS.ERROR_TYPE_STATUS, telemetryTags)
|
|
279
|
-
throw new AIGuardClientError(
|
|
280
|
-
`AI Guard service call failed, status ${response.status}`,
|
|
281
|
-
{ errors: response.body?.errors })
|
|
48
|
+
evaluation = await this.#client.evaluate(messages, this.#meta)
|
|
49
|
+
} catch (error) {
|
|
50
|
+
this.#reporter.fail(report, error.telemetryType ?? TAGS.ERROR_TYPE_CLIENT)
|
|
51
|
+
throw error
|
|
282
52
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const tags = attr.tags ?? []
|
|
291
|
-
if (tags.length > 0) {
|
|
292
|
-
metaStruct.attack_categories = tags
|
|
293
|
-
}
|
|
294
|
-
const sdsFindings = attr.sds_findings ?? []
|
|
295
|
-
if (sdsFindings.length > 0) {
|
|
296
|
-
metaStruct.sds = sdsFindings
|
|
297
|
-
}
|
|
298
|
-
const tagProbabilities = attr.tag_probs ?? {}
|
|
299
|
-
if (attr.tag_probs) {
|
|
300
|
-
metaStruct.tag_probs = tagProbabilities
|
|
301
|
-
}
|
|
302
|
-
const blockingEnabled = attr.is_blocking_enabled ?? false
|
|
303
|
-
const shouldBlock = block && blockingEnabled && action !== ALLOW
|
|
304
|
-
aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, {
|
|
305
|
-
action,
|
|
306
|
-
error: false,
|
|
307
|
-
block: shouldBlock,
|
|
308
|
-
...telemetryTags,
|
|
309
|
-
}).inc(1)
|
|
310
|
-
span.setTag(TAGS.ACTION_TAG_KEY, action)
|
|
311
|
-
if (reason) {
|
|
312
|
-
span.setTag(TAGS.REASON_TAG_KEY, reason)
|
|
313
|
-
}
|
|
314
|
-
if (shouldBlock) {
|
|
315
|
-
span.setTag(TAGS.BLOCKED_TAG_KEY, 'true')
|
|
316
|
-
throw new AIGuardAbortError(reason, tags, tagProbabilities, sdsFindings)
|
|
53
|
+
|
|
54
|
+
const outcome = createEvaluationOutcome(evaluation, block)
|
|
55
|
+
this.#reporter.finish(report, outcome)
|
|
56
|
+
|
|
57
|
+
if (outcome.shouldBlock) {
|
|
58
|
+
const { reason, tags, tagProbabilities, sds } = outcome.result
|
|
59
|
+
throw new AIGuardAbortError(reason, tags, tagProbabilities, sds)
|
|
317
60
|
}
|
|
318
|
-
|
|
61
|
+
|
|
62
|
+
return outcome.result
|
|
319
63
|
})
|
|
320
64
|
}
|
|
321
65
|
}
|