dd-trace 5.106.0 → 5.107.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/index.d.ts +20 -1
- package/package.json +5 -7
- package/packages/datadog-core/src/storage.js +47 -48
- package/packages/datadog-esbuild/index.js +6 -1
- package/packages/datadog-instrumentations/src/ai.js +12 -3
- package/packages/datadog-instrumentations/src/body-parser.js +5 -2
- package/packages/datadog-instrumentations/src/connect.js +3 -2
- package/packages/datadog-instrumentations/src/cookie-parser.js +3 -2
- package/packages/datadog-instrumentations/src/cucumber.js +7 -0
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +7 -5
- package/packages/datadog-instrumentations/src/express-session.js +12 -11
- package/packages/datadog-instrumentations/src/express.js +24 -20
- package/packages/datadog-instrumentations/src/fastify.js +18 -6
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +27 -12
- package/packages/datadog-instrumentations/src/http/client.js +9 -12
- package/packages/datadog-instrumentations/src/http/server.js +30 -16
- package/packages/datadog-instrumentations/src/http2/client.js +15 -12
- package/packages/datadog-instrumentations/src/http2/server.js +15 -8
- package/packages/datadog-instrumentations/src/jest/bail-reporter.js +42 -0
- package/packages/datadog-instrumentations/src/jest.js +143 -73
- package/packages/datadog-instrumentations/src/mocha/main.js +43 -8
- package/packages/datadog-instrumentations/src/mocha/utils.js +128 -17
- package/packages/datadog-instrumentations/src/multer.js +3 -2
- package/packages/datadog-instrumentations/src/mysql2.js +34 -0
- package/packages/datadog-instrumentations/src/net.js +8 -6
- package/packages/datadog-instrumentations/src/openai.js +19 -7
- package/packages/datadog-instrumentations/src/pg.js +19 -0
- package/packages/datadog-instrumentations/src/router.js +12 -10
- package/packages/datadog-instrumentations/src/vitest.js +29 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +0 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +62 -11
- package/packages/datadog-plugin-cucumber/src/index.js +2 -0
- package/packages/datadog-plugin-cypress/src/support.js +31 -1
- package/packages/datadog-plugin-http/src/client.js +0 -3
- package/packages/datadog-plugin-http/src/server.js +11 -1
- package/packages/datadog-plugin-mocha/src/index.js +2 -0
- package/packages/datadog-plugin-pg/src/index.js +10 -0
- package/packages/dd-trace/src/aiguard/index.js +34 -15
- package/packages/dd-trace/src/aiguard/sdk.js +34 -3
- package/packages/dd-trace/src/aiguard/tags.js +6 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/config/defaults.js +14 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +1 -1
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +5 -9
- package/packages/dd-trace/src/config/parsers.js +8 -0
- package/packages/dd-trace/src/config/supported-configurations.json +13 -6
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -2
- package/packages/dd-trace/src/datastreams/writer.js +1 -2
- package/packages/dd-trace/src/debugger/config.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -2
- package/packages/dd-trace/src/debugger/index.js +1 -2
- package/packages/dd-trace/src/dogstatsd.js +2 -3
- package/packages/dd-trace/src/encode/0.4.js +49 -41
- package/packages/dd-trace/src/encode/agentless-json.js +5 -1
- package/packages/dd-trace/src/encode/tags-processors.js +14 -0
- package/packages/dd-trace/src/exporters/agent/index.js +1 -2
- package/packages/dd-trace/src/exporters/agentless/index.js +6 -10
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +1 -2
- package/packages/dd-trace/src/exporters/common/request.js +26 -0
- package/packages/dd-trace/src/exporters/span-stats/index.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +4 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +45 -0
- package/packages/dd-trace/src/llmobs/sdk.js +4 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +17 -1
- package/packages/dd-trace/src/llmobs/tagger.js +5 -3
- package/packages/dd-trace/src/llmobs/util.js +54 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -2
- package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
- package/packages/dd-trace/src/openfeature/writers/base.js +1 -10
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -2
- package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +26 -13
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +7 -10
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +92 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +3 -2
- package/packages/dd-trace/src/opentracing/span.js +23 -18
- package/packages/dd-trace/src/opentracing/tracer.js +16 -12
- package/packages/dd-trace/src/plugins/ci_plugin.js +131 -46
- package/packages/dd-trace/src/priority_sampler.js +6 -5
- package/packages/dd-trace/src/profiling/config.js +1 -2
- package/packages/dd-trace/src/proxy.js +13 -10
- package/packages/dd-trace/src/remote_config/index.js +1 -2
- package/packages/dd-trace/src/runtime_metrics/client.js +30 -0
- package/packages/dd-trace/src/runtime_metrics/index.js +12 -2
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +284 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -11
- package/packages/dd-trace/src/service-naming/source-resolver.js +5 -1
- package/packages/dd-trace/src/span_format.js +33 -25
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/startup-log.js +1 -2
- package/packages/dd-trace/src/telemetry/send-data.js +1 -1
- package/packages/dd-trace/src/tracer.js +1 -1
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +2 -2
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/dd-trace/src/agent/url.js +0 -28
- package/scripts/preinstall.js +0 -34
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const { URL } = require('url')
|
|
4
4
|
const log = require('../../log')
|
|
5
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
6
5
|
const Writer = require('./writer')
|
|
7
6
|
|
|
8
7
|
class AgentExporter {
|
|
@@ -11,7 +10,7 @@ class AgentExporter {
|
|
|
11
10
|
constructor (config, prioritySampler) {
|
|
12
11
|
this._config = config
|
|
13
12
|
const { lookup, protocolVersion, stats = {}, apmTracingEnabled } = config
|
|
14
|
-
this._url =
|
|
13
|
+
this._url = config.url
|
|
15
14
|
|
|
16
15
|
const headers = {}
|
|
17
16
|
if (stats.enabled || apmTracingEnabled === false) {
|
|
@@ -18,25 +18,21 @@ class AgentlessExporter {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {object} config - Configuration object
|
|
21
|
-
* @param {string} [config.site] - The Datadog site. Defaults to 'datadoghq.com'.
|
|
22
|
-
* @param {string} [config.url] - Override intake URL
|
|
21
|
+
* @param {string} [config.site] - The Datadog site. Defaults to 'datadoghq.com'.
|
|
23
22
|
* @param {number} [config.flushInterval] - Batch flush interval in ms
|
|
24
23
|
* @param {string} [config.env] - Environment name
|
|
25
24
|
* @param {object} [config.tags] - Tags including runtime-id
|
|
26
25
|
*/
|
|
27
26
|
constructor (config) {
|
|
28
27
|
this._config = config
|
|
29
|
-
const
|
|
28
|
+
const site = config.site ?? 'datadoghq.com'
|
|
30
29
|
|
|
31
30
|
try {
|
|
32
|
-
|
|
31
|
+
// Agentless traffic carries the Datadog API key, so the intake is always the public https
|
|
32
|
+
// endpoint; never derive it from config.url (the agent's cleartext http) or the key leaks.
|
|
33
|
+
this._url = new URL(`https://public-trace-http-intake.logs.${site}`)
|
|
33
34
|
} catch (err) {
|
|
34
|
-
log.error(
|
|
35
|
-
'Invalid URL configuration for agentless exporter. url=%s, site=%s. Error: %s',
|
|
36
|
-
url || 'not set',
|
|
37
|
-
site,
|
|
38
|
-
err.message
|
|
39
|
-
)
|
|
35
|
+
log.error('Invalid site for agentless exporter. site=%s. Error: %s', site, err.message)
|
|
40
36
|
this._url = null
|
|
41
37
|
}
|
|
42
38
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { incrementCountMetric, TELEMETRY_EVENTS_ENQUEUED_FOR_SERIALIZATION } = require('../../ci-visibility/telemetry')
|
|
4
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Base exporter that buffers traces until a writer is initialized.
|
|
@@ -14,7 +13,7 @@ class BufferingExporter {
|
|
|
14
13
|
|
|
15
14
|
constructor (tracerConfig) {
|
|
16
15
|
this._config = tracerConfig
|
|
17
|
-
this._url =
|
|
16
|
+
this._url = tracerConfig.url
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
export (trace) {
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const { Readable } = require('stream')
|
|
7
7
|
const http = require('http')
|
|
8
8
|
const https = require('https')
|
|
9
|
+
const net = require('net')
|
|
9
10
|
const zlib = require('zlib')
|
|
10
11
|
|
|
11
12
|
const { storage } = require('../../../../datadog-core')
|
|
@@ -45,6 +46,17 @@ function parseUrl (urlObjOrString) {
|
|
|
45
46
|
return url
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} hostname Host as resolved by {@link parseUrl}; IPv6 is unbracketed (`::1`).
|
|
51
|
+
*/
|
|
52
|
+
function isLoopbackHost (hostname) {
|
|
53
|
+
// The 127.0.0.0/8 block is loopback, but only when the host is an actual IPv4 literal: a
|
|
54
|
+
// hostname like `127.evil.com` shares the prefix yet resolves anywhere, so net.isIPv4 gates it.
|
|
55
|
+
return hostname === 'localhost' ||
|
|
56
|
+
hostname === '::1' ||
|
|
57
|
+
(hostname.startsWith('127.') && net.isIPv4(hostname))
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
/**
|
|
49
61
|
* @param {Buffer|string|Readable|Array<Buffer|string>} data
|
|
50
62
|
* @param {object} options
|
|
@@ -67,6 +79,20 @@ function request (data, options, callback) {
|
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
// Never put the Datadog API key on a cleartext connection to a non-loopback host; that would
|
|
83
|
+
// expose it on the wire. Loopback (local agent, dev proxy, tests) is exempt. Strip the key
|
|
84
|
+
// rather than drop the request: the agent proxies telemetry with its own key, while an https
|
|
85
|
+
// intake URL is required to authenticate agentless traffic.
|
|
86
|
+
const hasApiKey = options.headers['dd-api-key'] !== undefined || options.headers['DD-API-KEY'] !== undefined
|
|
87
|
+
if (hasApiKey && options.protocol === 'http:' && !isLoopbackHost(options.hostname)) {
|
|
88
|
+
log.error(
|
|
89
|
+
'Not sending the Datadog API key over a non-TLS connection to %s. Configure an https intake URL.',
|
|
90
|
+
options.hostname
|
|
91
|
+
)
|
|
92
|
+
delete options.headers['dd-api-key']
|
|
93
|
+
delete options.headers['DD-API-KEY']
|
|
94
|
+
}
|
|
95
|
+
|
|
70
96
|
if (data instanceof Readable) {
|
|
71
97
|
const chunks = []
|
|
72
98
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
4
3
|
const { Writer } = require('./writer')
|
|
5
4
|
|
|
6
5
|
class SpanStatsExporter {
|
|
7
6
|
constructor (config) {
|
|
8
|
-
this._url =
|
|
7
|
+
this._url = config.url
|
|
9
8
|
this._writer = new Writer({ url: this._url })
|
|
10
9
|
}
|
|
11
10
|
|
|
@@ -5,6 +5,7 @@ const {
|
|
|
5
5
|
getOperation,
|
|
6
6
|
extractMetrics,
|
|
7
7
|
extractMetadata,
|
|
8
|
+
extractToolDefinitions,
|
|
8
9
|
aggregateStreamingChunks,
|
|
9
10
|
formatInputMessages,
|
|
10
11
|
formatEmbeddingInput,
|
|
@@ -79,6 +80,9 @@ class GenAiLLMObsPlugin extends LLMObsPlugin {
|
|
|
79
80
|
const metadata = extractMetadata(config)
|
|
80
81
|
this._tagger.tagMetadata(span, metadata)
|
|
81
82
|
|
|
83
|
+
const toolDefinitions = extractToolDefinitions(config)
|
|
84
|
+
if (toolDefinitions.length > 0) this._tagger.tagToolDefinitions(span, toolDefinitions)
|
|
85
|
+
|
|
82
86
|
if (error) {
|
|
83
87
|
this._tagger.tagLLMIO(span, inputMessages, [{ content: '' }])
|
|
84
88
|
return
|
|
@@ -155,6 +155,50 @@ function extractMetadata (config) {
|
|
|
155
155
|
return metadata
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Extract tool definitions from config
|
|
160
|
+
* @param {object} config
|
|
161
|
+
* @returns {Array}
|
|
162
|
+
*/
|
|
163
|
+
function extractToolDefinitions (config) {
|
|
164
|
+
const toolDefinitions = []
|
|
165
|
+
|
|
166
|
+
if (!Array.isArray(config?.tools)) {
|
|
167
|
+
return toolDefinitions
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const tool of config.tools) {
|
|
171
|
+
// Only extract tools with valid function declarations
|
|
172
|
+
if (!Array.isArray(tool?.functionDeclarations)) {
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
for (const currDeclaration of tool.functionDeclarations) {
|
|
177
|
+
// A valid declaration must have a name
|
|
178
|
+
if (!currDeclaration?.name) {
|
|
179
|
+
continue
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const toolDef = { name: currDeclaration.name }
|
|
183
|
+
|
|
184
|
+
if (currDeclaration.description !== undefined) {
|
|
185
|
+
toolDef.description = currDeclaration.description
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Parameters can be in two different fields depending on user input
|
|
189
|
+
if (currDeclaration.parameters !== undefined) {
|
|
190
|
+
toolDef.schema = currDeclaration.parameters
|
|
191
|
+
} else if (currDeclaration.parametersJsonSchema !== undefined) {
|
|
192
|
+
toolDef.schema = currDeclaration.parametersJsonSchema
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
toolDefinitions.push(toolDef)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return toolDefinitions
|
|
200
|
+
}
|
|
201
|
+
|
|
158
202
|
/**
|
|
159
203
|
* Format function call message
|
|
160
204
|
* @param {Array} parts
|
|
@@ -498,6 +542,7 @@ module.exports = {
|
|
|
498
542
|
getOperation,
|
|
499
543
|
extractMetrics,
|
|
500
544
|
extractMetadata,
|
|
545
|
+
extractToolDefinitions,
|
|
501
546
|
aggregateStreamingChunks,
|
|
502
547
|
formatInputMessages,
|
|
503
548
|
formatEmbeddingInput,
|
|
@@ -259,7 +259,7 @@ class LLMObs extends NoopLLMObs {
|
|
|
259
259
|
throw new Error('LLMObs span must have a span kind specified')
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
const { inputData, outputData, metadata, metrics, tags, prompt, costTags } = options
|
|
262
|
+
const { inputData, outputData, metadata, metrics, tags, prompt, costTags, toolDefinitions } = options
|
|
263
263
|
|
|
264
264
|
if (inputData || outputData) {
|
|
265
265
|
if (spanKind === 'llm') {
|
|
@@ -289,6 +289,9 @@ class LLMObs extends NoopLLMObs {
|
|
|
289
289
|
if (prompt) {
|
|
290
290
|
this._tagger.tagPrompt(span, prompt)
|
|
291
291
|
}
|
|
292
|
+
if (toolDefinitions != null) {
|
|
293
|
+
this._tagger.tagToolDefinitions(span, toolDefinitions)
|
|
294
|
+
}
|
|
292
295
|
} catch (e) {
|
|
293
296
|
if (e.ddErrorTag) {
|
|
294
297
|
err = e.ddErrorTag
|
|
@@ -332,8 +332,24 @@ class LLMObsSpanProcessor {
|
|
|
332
332
|
return tags
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
/**
|
|
336
|
+
* @param {Record<string, unknown>} tags
|
|
337
|
+
*/
|
|
335
338
|
#objectTagsToStringArrayTags (tags) {
|
|
336
|
-
|
|
339
|
+
const out = []
|
|
340
|
+
for (const [key, value] of Object.entries(tags)) {
|
|
341
|
+
// Comma is the intake-side tag delimiter, so a single `"key:v1,v2"`
|
|
342
|
+
// entry fans into two orphan tags. One-per-element keeps each value
|
|
343
|
+
// addressable; empty arrays fall through to the scalar branch and
|
|
344
|
+
// still emit `key:` so `_dd.cost_tags` references keep finding a
|
|
345
|
+
// wire entry.
|
|
346
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
347
|
+
for (const item of value) out.push(`${key}:${item ?? ''}`)
|
|
348
|
+
} else {
|
|
349
|
+
out.push(`${key}:${value ?? ''}`)
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return out
|
|
337
353
|
}
|
|
338
354
|
|
|
339
355
|
/**
|
|
@@ -43,7 +43,7 @@ const {
|
|
|
43
43
|
INSTRUMENTATION_METHOD_ANNOTATED,
|
|
44
44
|
} = require('./constants/tags')
|
|
45
45
|
const { storage } = require('./storage')
|
|
46
|
-
const { findGenAIAncestorSpanId, validateCostTags, writeBridgeTags } = require('./util')
|
|
46
|
+
const { findGenAIAncestorSpanId, validateCostTags, writeBridgeTags, validateToolDefinitions } = require('./util')
|
|
47
47
|
|
|
48
48
|
// global registry of LLMObs spans
|
|
49
49
|
// maps LLMObs spans to their annotations
|
|
@@ -176,8 +176,10 @@ class LLMObsTagger {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
tagToolDefinitions (span, toolDefinitions) {
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
const validatedToolDefinitions = validateToolDefinitions(toolDefinitions)
|
|
180
|
+
|
|
181
|
+
if (validatedToolDefinitions.length > 0) {
|
|
182
|
+
this._setTag(span, TOOL_DEFINITIONS, validatedToolDefinitions)
|
|
181
183
|
} else {
|
|
182
184
|
this.#handleFailure('Tool definitions must be a non-empty array.', 'invalid_tool_definitions')
|
|
183
185
|
}
|
|
@@ -89,6 +89,59 @@ function validateCostTags (span, costTags, source, spanTags) {
|
|
|
89
89
|
return [...validatedCostTags]
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// Validates tool definition entires
|
|
93
|
+
function validateToolDefinitions (toolDefinitions) {
|
|
94
|
+
if (!Array.isArray(toolDefinitions)) {
|
|
95
|
+
log.warn('toolDefinitions must be an array.')
|
|
96
|
+
return []
|
|
97
|
+
}
|
|
98
|
+
const validated = []
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < toolDefinitions.length; i++) {
|
|
101
|
+
const currToolDef = toolDefinitions[i]
|
|
102
|
+
if (!currToolDef || typeof currToolDef !== 'object') {
|
|
103
|
+
log.warn('Tool definition at index %d must be an object. Skipping.', i)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Name is not optional
|
|
108
|
+
if (!currToolDef.name || typeof currToolDef.name !== 'string' || currToolDef.name.length <= 0) {
|
|
109
|
+
log.warn('Tool definition at index %d must have a non empty string "name". Skipping.', i)
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
const validatedToolDef = { name: currToolDef.name }
|
|
113
|
+
|
|
114
|
+
// Description, Schema, and Version are optional types
|
|
115
|
+
if (currToolDef.description !== undefined) {
|
|
116
|
+
if (typeof currToolDef.description === 'string') {
|
|
117
|
+
validatedToolDef.description = currToolDef.description
|
|
118
|
+
} else {
|
|
119
|
+
log.warn('Tool definition "description" at index %d must be a string. Skipping field.', i)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (currToolDef.schema !== undefined) {
|
|
124
|
+
if (currToolDef.schema !== null && typeof currToolDef.schema === 'object' && !Array.isArray(currToolDef.schema)) {
|
|
125
|
+
validatedToolDef.schema = currToolDef.schema
|
|
126
|
+
} else {
|
|
127
|
+
log.warn('Tool definition "schema" at index %d must be a plain object. Skipping field.', i)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (currToolDef.version !== undefined) {
|
|
132
|
+
if (typeof currToolDef.version === 'string') {
|
|
133
|
+
validatedToolDef.version = currToolDef.version
|
|
134
|
+
} else {
|
|
135
|
+
log.warn('Tool definition "version" at index %d must be a string. Skipping field.', i)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
validated.push(validatedToolDef)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return validated
|
|
143
|
+
}
|
|
144
|
+
|
|
92
145
|
// extracts the argument names from a function string
|
|
93
146
|
function parseArgumentNames (str) {
|
|
94
147
|
const result = []
|
|
@@ -318,4 +371,5 @@ module.exports = {
|
|
|
318
371
|
safeJsonParse,
|
|
319
372
|
spanHasError,
|
|
320
373
|
writeBridgeTags,
|
|
374
|
+
validateToolDefinitions,
|
|
321
375
|
}
|
|
@@ -14,7 +14,6 @@ const {
|
|
|
14
14
|
EVP_SUBDOMAIN_HEADER_NAME,
|
|
15
15
|
EVP_PROXY_AGENT_BASE_PATH,
|
|
16
16
|
} = require('../constants/writers')
|
|
17
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
18
17
|
const { parseResponseAndLog } = require('./util')
|
|
19
18
|
|
|
20
19
|
class LLMObsBuffer {
|
|
@@ -210,7 +209,7 @@ class BaseLLMObsWriter {
|
|
|
210
209
|
|
|
211
210
|
const overrideOriginEnv = getEnvironmentVariable('_DD_LLMOBS_OVERRIDE_ORIGIN')
|
|
212
211
|
const overrideOriginUrl = overrideOriginEnv && new URL(overrideOriginEnv)
|
|
213
|
-
const base = overrideOriginUrl ??
|
|
212
|
+
const base = overrideOriginUrl ?? this._config.url
|
|
214
213
|
|
|
215
214
|
return {
|
|
216
215
|
url: base,
|
|
@@ -4,7 +4,6 @@ const logger = require('../../log')
|
|
|
4
4
|
const { EVP_PROXY_AGENT_BASE_PATH } = require('../constants/writers')
|
|
5
5
|
const telemetry = require('../telemetry')
|
|
6
6
|
const { fetchAgentInfo } = require('../../agent/info')
|
|
7
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* @param {import('../../config/config-base')} config
|
|
@@ -17,7 +16,7 @@ function setAgentStrategy (config, setWritersAgentlessValue) {
|
|
|
17
16
|
return
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
fetchAgentInfo(
|
|
19
|
+
fetchAgentInfo(config.url, (err, agentInfo) => {
|
|
21
20
|
if (err) {
|
|
22
21
|
setWritersAgentlessValue(true)
|
|
23
22
|
return
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const request = require('../../exporters/common/request')
|
|
4
4
|
const { safeJSONStringify } = require('../../exporters/common/util')
|
|
5
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
6
5
|
|
|
7
6
|
const log = require('../../log')
|
|
8
7
|
|
|
@@ -37,7 +36,7 @@ class BaseFFEWriter {
|
|
|
37
36
|
|
|
38
37
|
this._config = config
|
|
39
38
|
this._endpoint = endpoint
|
|
40
|
-
this._baseUrl = agentUrl ??
|
|
39
|
+
this._baseUrl = agentUrl ?? config.url
|
|
41
40
|
this._payloadSizeLimit = payloadSizeLimit
|
|
42
41
|
this._eventSizeLimit = eventSizeLimit
|
|
43
42
|
this._headers = headers || {}
|
|
@@ -154,14 +153,6 @@ class BaseFFEWriter {
|
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
/**
|
|
158
|
-
* @private
|
|
159
|
-
* @returns {URL} Constructs agent URL from config
|
|
160
|
-
*/
|
|
161
|
-
_getAgentUrl () {
|
|
162
|
-
return getAgentUrl(this._config)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
156
|
/**
|
|
166
157
|
* @private
|
|
167
158
|
* @param {Array<object>} payload - Payload to encode
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const logger = require('../../log')
|
|
4
4
|
const { EVP_PROXY_AGENT_BASE_PATH } = require('../constants/constants')
|
|
5
5
|
const { fetchAgentInfo } = require('../../agent/info')
|
|
6
|
-
const { getAgentUrl } = require('../../agent/url')
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Determines if the agent supports EVP proxy and sets the writer enabled state accordingly
|
|
@@ -11,7 +10,7 @@ const { getAgentUrl } = require('../../agent/url')
|
|
|
11
10
|
* @param {Function} setWriterEnabledValue - Callback to set the writer enabled state
|
|
12
11
|
*/
|
|
13
12
|
function setAgentStrategy (config, setWriterEnabledValue) {
|
|
14
|
-
fetchAgentInfo(
|
|
13
|
+
fetchAgentInfo(config.url, (err, agentInfo) => {
|
|
15
14
|
if (err) {
|
|
16
15
|
logger.debug('FFE Writer disabled - error getting agent info:', err.message)
|
|
17
16
|
setWriterEnabledValue(false)
|
|
@@ -50,7 +50,7 @@ class Instrument {
|
|
|
50
50
|
* Creates a measurement object for recording metric values.
|
|
51
51
|
* @param {string} type - Metric type from METRIC_TYPES
|
|
52
52
|
* @param {number} value - Numeric value to record
|
|
53
|
-
* @param {Attributes} attributes - Key-value pairs for metric dimensions
|
|
53
|
+
* @param {Attributes} [attributes] - Key-value pairs for metric dimensions
|
|
54
54
|
* @returns {Measurement} Measurement object with metadata and timestamp
|
|
55
55
|
*/
|
|
56
56
|
createMeasurement (type, value, attributes) {
|
|
@@ -73,9 +73,9 @@ class Instrument {
|
|
|
73
73
|
* @class Counter
|
|
74
74
|
*/
|
|
75
75
|
class Counter extends Instrument {
|
|
76
|
-
add (value, attributes
|
|
76
|
+
add (value, attributes) {
|
|
77
77
|
if (value < 0) return
|
|
78
|
-
this.reader
|
|
78
|
+
this.reader.record(this.createMeasurement(METRIC_TYPES.COUNTER, value, attributes))
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -85,8 +85,8 @@ class Counter extends Instrument {
|
|
|
85
85
|
* @class UpDownCounter
|
|
86
86
|
*/
|
|
87
87
|
class UpDownCounter extends Instrument {
|
|
88
|
-
add (value, attributes
|
|
89
|
-
this.reader
|
|
88
|
+
add (value, attributes) {
|
|
89
|
+
this.reader.record(this.createMeasurement(METRIC_TYPES.UPDOWNCOUNTER, value, attributes))
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -96,9 +96,9 @@ class UpDownCounter extends Instrument {
|
|
|
96
96
|
* @class Histogram
|
|
97
97
|
*/
|
|
98
98
|
class Histogram extends Instrument {
|
|
99
|
-
record (value, attributes
|
|
99
|
+
record (value, attributes) {
|
|
100
100
|
if (value < 0) return
|
|
101
|
-
this.reader
|
|
101
|
+
this.reader.record(this.createMeasurement(METRIC_TYPES.HISTOGRAM, value, attributes))
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -108,8 +108,8 @@ class Histogram extends Instrument {
|
|
|
108
108
|
* @class Gauge
|
|
109
109
|
*/
|
|
110
110
|
class Gauge extends Instrument {
|
|
111
|
-
record (value, attributes
|
|
112
|
-
this.reader
|
|
111
|
+
record (value, attributes) {
|
|
112
|
+
this.reader.record(this.createMeasurement(METRIC_TYPES.GAUGE, value, attributes))
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -136,7 +136,7 @@ class ObservableInstrument extends Instrument {
|
|
|
136
136
|
addCallback (callback) {
|
|
137
137
|
if (typeof callback !== 'function') return
|
|
138
138
|
this.#callbacks.push(callback)
|
|
139
|
-
this.reader
|
|
139
|
+
this.reader.observableInstruments.add(this)
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
/**
|
|
@@ -150,7 +150,7 @@ class ObservableInstrument extends Instrument {
|
|
|
150
150
|
this.#callbacks.splice(index, 1)
|
|
151
151
|
if (this.#callbacks.length === 0) {
|
|
152
152
|
// Remove instrument from collection when no callbacks remain
|
|
153
|
-
this.reader
|
|
153
|
+
this.reader.observableInstruments.delete(this)
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
}
|
|
@@ -163,8 +163,8 @@ class ObservableInstrument extends Instrument {
|
|
|
163
163
|
collect () {
|
|
164
164
|
const observations = []
|
|
165
165
|
const observableResult = {
|
|
166
|
-
observe: (value, attributes
|
|
167
|
-
observations.push(this.
|
|
166
|
+
observe: (value, attributes) => {
|
|
167
|
+
observations.push(this.createObservation(value, attributes))
|
|
168
168
|
},
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -179,6 +179,18 @@ class ObservableInstrument extends Instrument {
|
|
|
179
179
|
|
|
180
180
|
return observations
|
|
181
181
|
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Builds a measurement for this instrument's metric type. Keeps the type
|
|
185
|
+
* encapsulated so callers (e.g. batch observable callbacks) don't read it.
|
|
186
|
+
*
|
|
187
|
+
* @param {number} value
|
|
188
|
+
* @param {Attributes} attributes
|
|
189
|
+
* @returns {Measurement}
|
|
190
|
+
*/
|
|
191
|
+
createObservation (value, attributes) {
|
|
192
|
+
return this.createMeasurement(this.#type, value, attributes)
|
|
193
|
+
}
|
|
182
194
|
}
|
|
183
195
|
|
|
184
196
|
/**
|
|
@@ -219,6 +231,7 @@ module.exports = {
|
|
|
219
231
|
UpDownCounter,
|
|
220
232
|
Histogram,
|
|
221
233
|
Gauge,
|
|
234
|
+
ObservableInstrument,
|
|
222
235
|
ObservableGauge,
|
|
223
236
|
ObservableCounter,
|
|
224
237
|
ObservableUpDownCounter,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { VERSION: packageVersion } = require('../../../../../version')
|
|
4
|
-
const log = require('../../log')
|
|
5
4
|
const {
|
|
6
5
|
Counter, UpDownCounter, Histogram, Gauge, ObservableGauge, ObservableCounter, ObservableUpDownCounter,
|
|
7
6
|
} = require('./instruments')
|
|
@@ -148,23 +147,21 @@ class Meter {
|
|
|
148
147
|
}
|
|
149
148
|
|
|
150
149
|
/**
|
|
151
|
-
*
|
|
150
|
+
* Registers a batch observable callback for the given observables.
|
|
152
151
|
*
|
|
153
|
-
* @param {Function} callback
|
|
154
|
-
* @param {Array} observables
|
|
152
|
+
* @param {Function} callback
|
|
153
|
+
* @param {Array} observables
|
|
155
154
|
*/
|
|
156
155
|
addBatchObservableCallback (callback, observables) {
|
|
157
|
-
|
|
156
|
+
this.meterProvider.reader.addBatchObservableCallback(callback, observables)
|
|
158
157
|
}
|
|
159
158
|
|
|
160
159
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* @param {Function} callback - Batch observable callback
|
|
164
|
-
* @param {Array} observables - Array of observable instruments
|
|
160
|
+
* @param {Function} callback
|
|
161
|
+
* @param {Array} observables
|
|
165
162
|
*/
|
|
166
163
|
removeBatchObservableCallback (callback, observables) {
|
|
167
|
-
|
|
164
|
+
this.meterProvider.reader.removeBatchObservableCallback(callback, observables)
|
|
168
165
|
}
|
|
169
166
|
}
|
|
170
167
|
|