@latitude-data/telemetry 2.0.4 → 3.0.0-alpha.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/LICENSE +157 -0
- package/README.md +455 -31
- package/dist/index.cjs +489 -2089
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +169 -0
- package/dist/index.d.ts +144 -314
- package/dist/index.js +458 -2062
- package/dist/index.js.map +1 -1
- package/package.json +39 -47
- package/LICENSE.md +0 -21
package/dist/index.js
CHANGED
|
@@ -1,2089 +1,485 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { Translator, Provider } from 'rosetta-ai';
|
|
7
|
-
import { v4 } from 'uuid';
|
|
8
|
-
import { BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS } from '@opentelemetry/baggage-span-processor';
|
|
9
|
-
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
|
|
10
|
-
import { CompositePropagator, W3CTraceContextPropagator, W3CBaggagePropagator } from '@opentelemetry/core';
|
|
11
|
-
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
12
|
-
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
13
|
-
import { Resource } from '@opentelemetry/resources';
|
|
14
|
-
import { NodeTracerProvider, SimpleSpanProcessor, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
|
|
15
|
-
import { AnthropicInstrumentation } from '@traceloop/instrumentation-anthropic';
|
|
16
|
-
import { BedrockInstrumentation } from '@traceloop/instrumentation-bedrock';
|
|
17
|
-
import { CohereInstrumentation } from '@traceloop/instrumentation-cohere';
|
|
18
|
-
import { LangChainInstrumentation } from '@traceloop/instrumentation-langchain';
|
|
19
|
-
import { LlamaIndexInstrumentation } from '@traceloop/instrumentation-llamaindex';
|
|
20
|
-
import { OpenAIInstrumentation } from '@traceloop/instrumentation-openai';
|
|
21
|
-
import { TogetherInstrumentation } from '@traceloop/instrumentation-together';
|
|
22
|
-
import { AIPlatformInstrumentation, VertexAIInstrumentation } from '@traceloop/instrumentation-vertexai';
|
|
23
|
-
|
|
24
|
-
class RedactSpanProcessor {
|
|
25
|
-
options;
|
|
26
|
-
constructor(options) {
|
|
27
|
-
this.options = options;
|
|
28
|
-
if (!options.mask) {
|
|
29
|
-
this.options.mask = (_attribute, _value) => '******';
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
onStart(_span, _context) {
|
|
33
|
-
// Noop
|
|
34
|
-
}
|
|
35
|
-
onEnd(span) {
|
|
36
|
-
Object.assign(span.attributes, this.redactAttributes(span.attributes));
|
|
37
|
-
for (const event of span.events) {
|
|
38
|
-
if (!event.attributes)
|
|
39
|
-
continue;
|
|
40
|
-
Object.assign(event.attributes, this.redactAttributes(event.attributes));
|
|
41
|
-
}
|
|
42
|
-
for (const link of span.links) {
|
|
43
|
-
if (!link.attributes)
|
|
44
|
-
continue;
|
|
45
|
-
Object.assign(link.attributes, this.redactAttributes(link.attributes));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
forceFlush() {
|
|
49
|
-
return Promise.resolve();
|
|
50
|
-
}
|
|
51
|
-
shutdown() {
|
|
52
|
-
return Promise.resolve();
|
|
53
|
-
}
|
|
54
|
-
shouldRedact(attribute) {
|
|
55
|
-
return this.options.attributes.some((pattern) => {
|
|
56
|
-
if (typeof pattern === 'string') {
|
|
57
|
-
return attribute === pattern;
|
|
58
|
-
}
|
|
59
|
-
else if (pattern instanceof RegExp) {
|
|
60
|
-
return pattern.test(attribute);
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
redactAttributes(attributes) {
|
|
66
|
-
const redacted = {};
|
|
67
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
68
|
-
if (this.shouldRedact(key)) {
|
|
69
|
-
redacted[key] = this.options.mask(key, value);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return redacted;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
|
|
76
|
-
attributes: [
|
|
77
|
-
/^.*auth.*$/i,
|
|
78
|
-
/^.*authorization.*$/i,
|
|
79
|
-
/^(?!gen_ai\.).*usage.*$/i,
|
|
80
|
-
/^(?!gen_ai\.).*token.*$/i,
|
|
81
|
-
/^.*secret.*$/i,
|
|
82
|
-
/^.*key.*$/i,
|
|
83
|
-
/^.*password.*$/i,
|
|
84
|
-
/^.*cookie.*$/i,
|
|
85
|
-
/^.*session.*$/i,
|
|
86
|
-
/^.*credential.*$/i,
|
|
87
|
-
/^.*signature.*$/i,
|
|
88
|
-
/^.*oauth.*$/i,
|
|
89
|
-
/^.*saml.*$/i,
|
|
90
|
-
/^.*openid.*$/i,
|
|
91
|
-
/^.*refresh.*$/i,
|
|
92
|
-
/^.*jwt.*$/i,
|
|
93
|
-
/^.*otp.*$/i,
|
|
94
|
-
/^.*mfa.*$/i,
|
|
95
|
-
/^.*csrf.*$/i,
|
|
96
|
-
/^.*xsrf.*$/i,
|
|
97
|
-
/^.*refresh.*$/i,
|
|
98
|
-
/^.*x[-_]forwarded[-_]for.*$/i,
|
|
99
|
-
/^.*x[-_]real[-_]ip.*$/i,
|
|
100
|
-
],
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
101
6
|
});
|
|
102
7
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (process.env.GATEWAY_BASE_URL) {
|
|
110
|
-
return process.env.GATEWAY_BASE_URL;
|
|
111
|
-
}
|
|
112
|
-
if (!process.env.GATEWAY_HOSTNAME) {
|
|
113
|
-
return DEFAULT_GATEWAY_BASE_URL;
|
|
114
|
-
}
|
|
115
|
-
const protocol = process.env.GATEWAY_SSL ? 'https' : 'http';
|
|
116
|
-
const port = process.env.GATEWAY_PORT ?? (process.env.GATEWAY_SSL ? 443 : 80);
|
|
117
|
-
const hostname = process.env.GATEWAY_HOSTNAME;
|
|
118
|
-
return `${protocol}://${hostname}:${port}`;
|
|
8
|
+
// src/sdk/context.ts
|
|
9
|
+
import { context, createContextKey, trace } from "@opentelemetry/api";
|
|
10
|
+
var LATITUDE_CONTEXT_KEY = createContextKey("latitude-internal-context");
|
|
11
|
+
var CAPTURE_TRACER_NAME = "so.latitude.instrumentation.capture";
|
|
12
|
+
function getLatitudeContext(ctx) {
|
|
13
|
+
return ctx.getValue(LATITUDE_CONTEXT_KEY);
|
|
119
14
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
126
|
-
.replace(/_+/g, '_')
|
|
127
|
-
.replace(/^_+|_+$/g, '')
|
|
128
|
-
.toLowerCase();
|
|
15
|
+
function mergeArrays(a, b) {
|
|
16
|
+
if (!a && !b) return void 0;
|
|
17
|
+
if (!a) return b;
|
|
18
|
+
if (!b) return a;
|
|
19
|
+
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
129
20
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
21
|
+
function capture(name, fn, options = {}) {
|
|
22
|
+
const currentContext = context.active();
|
|
23
|
+
const existingData = getLatitudeContext(currentContext);
|
|
24
|
+
const mergedData = {
|
|
25
|
+
name: options.name ?? name,
|
|
26
|
+
tags: mergeArrays(existingData?.tags, options.tags),
|
|
27
|
+
metadata: { ...existingData?.metadata, ...options.metadata },
|
|
28
|
+
sessionId: options.sessionId ?? existingData?.sessionId,
|
|
29
|
+
userId: options.userId ?? existingData?.userId
|
|
30
|
+
};
|
|
31
|
+
const newContext = currentContext.setValue(LATITUDE_CONTEXT_KEY, mergedData);
|
|
32
|
+
const existingSpan = trace.getSpan(currentContext);
|
|
33
|
+
if (existingSpan) {
|
|
34
|
+
return context.with(newContext, fn);
|
|
35
|
+
}
|
|
36
|
+
const tracer = trace.getTracer(CAPTURE_TRACER_NAME);
|
|
37
|
+
return tracer.startActiveSpan(name, { attributes: { "latitude.capture.root": true } }, newContext, (span) => {
|
|
38
|
+
let result;
|
|
39
|
+
try {
|
|
40
|
+
result = fn();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
span.recordException(error);
|
|
43
|
+
span.end();
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
if (result instanceof Promise) {
|
|
47
|
+
return result.catch((error) => {
|
|
48
|
+
span.recordException(error);
|
|
49
|
+
throw error;
|
|
50
|
+
}).finally(() => {
|
|
51
|
+
span.end();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
span.end();
|
|
55
|
+
return result;
|
|
56
|
+
});
|
|
137
57
|
}
|
|
138
58
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
name: z.string(),
|
|
147
|
-
result: z.unknown(),
|
|
148
|
-
isError: z.boolean().optional(),
|
|
149
|
-
text: z.string().optional(),
|
|
150
|
-
});
|
|
151
|
-
z.object({
|
|
152
|
-
inputTokens: z.number(),
|
|
153
|
-
outputTokens: z.number(),
|
|
154
|
-
promptTokens: z.number(),
|
|
155
|
-
completionTokens: z.number(),
|
|
156
|
-
totalTokens: z.number(),
|
|
157
|
-
reasoningTokens: z.number(),
|
|
158
|
-
cachedInputTokens: z.number(),
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
var ParameterType;
|
|
162
|
-
(function (ParameterType) {
|
|
163
|
-
ParameterType["Text"] = "text";
|
|
164
|
-
ParameterType["Image"] = "image";
|
|
165
|
-
ParameterType["File"] = "file";
|
|
166
|
-
})(ParameterType || (ParameterType = {}));
|
|
167
|
-
var LatitudeTool;
|
|
168
|
-
(function (LatitudeTool) {
|
|
169
|
-
LatitudeTool["RunCode"] = "code";
|
|
170
|
-
LatitudeTool["WebSearch"] = "search";
|
|
171
|
-
LatitudeTool["WebExtract"] = "extract";
|
|
172
|
-
LatitudeTool["Think"] = "think";
|
|
173
|
-
LatitudeTool["TODO"] = "todo";
|
|
174
|
-
})(LatitudeTool || (LatitudeTool = {}));
|
|
175
|
-
var LatitudeToolInternalName;
|
|
176
|
-
(function (LatitudeToolInternalName) {
|
|
177
|
-
LatitudeToolInternalName["RunCode"] = "lat_tool_run_code";
|
|
178
|
-
LatitudeToolInternalName["WebSearch"] = "lat_tool_web_search";
|
|
179
|
-
LatitudeToolInternalName["WebExtract"] = "lat_tool_web_extract";
|
|
180
|
-
LatitudeToolInternalName["Think"] = "think";
|
|
181
|
-
LatitudeToolInternalName["TODO"] = "todo_write";
|
|
182
|
-
})(LatitudeToolInternalName || (LatitudeToolInternalName = {}));
|
|
183
|
-
[
|
|
184
|
-
LatitudeTool.Think,
|
|
185
|
-
LatitudeTool.TODO,
|
|
186
|
-
];
|
|
187
|
-
|
|
188
|
-
const actualOutputConfiguration = z.object({
|
|
189
|
-
messageSelection: z.enum(['last', 'all']), // Which assistant messages to select
|
|
190
|
-
contentFilter: z
|
|
191
|
-
.enum(['text', 'reasoning', 'image', 'file', 'tool_call'])
|
|
192
|
-
.optional(),
|
|
193
|
-
parsingFormat: z.enum(['string', 'json']),
|
|
194
|
-
fieldAccessor: z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
195
|
-
});
|
|
196
|
-
const expectedOutputConfiguration = z.object({
|
|
197
|
-
parsingFormat: z.enum(['string', 'json']),
|
|
198
|
-
fieldAccessor: z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
199
|
-
});
|
|
200
|
-
const EVALUATION_TRIGGER_TARGETS = ['first', 'every', 'last'];
|
|
201
|
-
const LAST_INTERACTION_DEBOUNCE_MIN_SECONDS = 30;
|
|
202
|
-
const LAST_INTERACTION_DEBOUNCE_MAX_SECONDS = 60 * 60 * 24; // 1 day
|
|
203
|
-
const MIN_EVALUATION_SAMPLE_RATE = 0; // 0%
|
|
204
|
-
const MAX_EVALUATION_SAMPLE_RATE = 100; // 100%
|
|
205
|
-
const triggerConfiguration = z.object({
|
|
206
|
-
target: z.enum(EVALUATION_TRIGGER_TARGETS),
|
|
207
|
-
lastInteractionDebounce: z
|
|
208
|
-
.number()
|
|
209
|
-
.min(LAST_INTERACTION_DEBOUNCE_MIN_SECONDS)
|
|
210
|
-
.max(LAST_INTERACTION_DEBOUNCE_MAX_SECONDS)
|
|
211
|
-
.optional(),
|
|
212
|
-
sampleRate: z
|
|
213
|
-
.number()
|
|
214
|
-
.int()
|
|
215
|
-
.min(MIN_EVALUATION_SAMPLE_RATE)
|
|
216
|
-
.max(MAX_EVALUATION_SAMPLE_RATE)
|
|
217
|
-
.optional(),
|
|
218
|
-
});
|
|
219
|
-
const baseEvaluationConfiguration = z.object({
|
|
220
|
-
reverseScale: z.boolean(), // If true, lower is better, otherwise, higher is better
|
|
221
|
-
actualOutput: actualOutputConfiguration,
|
|
222
|
-
expectedOutput: expectedOutputConfiguration.optional(),
|
|
223
|
-
trigger: triggerConfiguration.optional(),
|
|
224
|
-
});
|
|
225
|
-
const baseEvaluationResultMetadata = z.object({
|
|
226
|
-
// configuration: Configuration snapshot is defined in every metric specification
|
|
227
|
-
actualOutput: z.string(),
|
|
228
|
-
expectedOutput: z.string().optional(),
|
|
229
|
-
datasetLabel: z.string().optional(),
|
|
230
|
-
});
|
|
231
|
-
const baseEvaluationResultError = z.object({
|
|
232
|
-
message: z.string(),
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
236
|
-
evaluationUuids: z.array(z.string()),
|
|
237
|
-
minThreshold: z.number().optional(), // Threshold percentage
|
|
238
|
-
maxThreshold: z.number().optional(), // Threshold percentage
|
|
239
|
-
});
|
|
240
|
-
const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
241
|
-
results: z.record(z.string(), // Evaluation uuid
|
|
242
|
-
z.object({
|
|
243
|
-
uuid: z.string(), // Result uuid (for side effects)
|
|
244
|
-
name: z.string(), // Evaluation name
|
|
245
|
-
score: z.number(), // Normalized score
|
|
246
|
-
reason: z.string(),
|
|
247
|
-
passed: z.boolean(),
|
|
248
|
-
tokens: z.number().optional(), // Optional llm evaluation usage
|
|
249
|
-
})),
|
|
250
|
-
});
|
|
251
|
-
const compositeEvaluationResultError = baseEvaluationResultError.extend({
|
|
252
|
-
errors: z
|
|
253
|
-
.record(z.string(), // Evaluation uuid
|
|
254
|
-
z.object({
|
|
255
|
-
uuid: z.string(), // Result uuid (for side effects)
|
|
256
|
-
name: z.string(), // Evaluation name
|
|
257
|
-
message: z.string(),
|
|
258
|
-
}))
|
|
259
|
-
.optional(),
|
|
260
|
-
});
|
|
261
|
-
// AVERAGE
|
|
262
|
-
const compositeEvaluationAverageConfiguration = compositeEvaluationConfiguration.extend({});
|
|
263
|
-
compositeEvaluationResultMetadata.extend({
|
|
264
|
-
configuration: compositeEvaluationAverageConfiguration,
|
|
265
|
-
});
|
|
266
|
-
compositeEvaluationResultError.extend({});
|
|
267
|
-
const CompositeEvaluationAverageSpecification = {
|
|
268
|
-
};
|
|
269
|
-
// WEIGHTED
|
|
270
|
-
const compositeEvaluationWeightedConfiguration = compositeEvaluationConfiguration.extend({
|
|
271
|
-
weights: z.record(z.string(), // Evaluation uuid
|
|
272
|
-
z.number()),
|
|
273
|
-
});
|
|
274
|
-
compositeEvaluationResultMetadata.extend({
|
|
275
|
-
configuration: compositeEvaluationWeightedConfiguration,
|
|
276
|
-
});
|
|
277
|
-
compositeEvaluationResultError.extend({});
|
|
278
|
-
const CompositeEvaluationWeightedSpecification = {
|
|
279
|
-
};
|
|
280
|
-
// CUSTOM
|
|
281
|
-
const compositeEvaluationCustomConfiguration = compositeEvaluationConfiguration.extend({
|
|
282
|
-
formula: z.string(),
|
|
283
|
-
});
|
|
284
|
-
compositeEvaluationResultMetadata.extend({
|
|
285
|
-
configuration: compositeEvaluationCustomConfiguration,
|
|
286
|
-
});
|
|
287
|
-
compositeEvaluationResultError.extend({});
|
|
288
|
-
const CompositeEvaluationCustomSpecification = {
|
|
289
|
-
};
|
|
290
|
-
/* ------------------------------------------------------------------------- */
|
|
291
|
-
var CompositeEvaluationMetric;
|
|
292
|
-
(function (CompositeEvaluationMetric) {
|
|
293
|
-
CompositeEvaluationMetric["Average"] = "average";
|
|
294
|
-
CompositeEvaluationMetric["Weighted"] = "weighted";
|
|
295
|
-
CompositeEvaluationMetric["Custom"] = "custom";
|
|
296
|
-
})(CompositeEvaluationMetric || (CompositeEvaluationMetric = {}));
|
|
297
|
-
const CompositeEvaluationSpecification = {
|
|
298
|
-
// prettier-ignore
|
|
299
|
-
metrics: {
|
|
300
|
-
[CompositeEvaluationMetric.Average]: CompositeEvaluationAverageSpecification,
|
|
301
|
-
[CompositeEvaluationMetric.Weighted]: CompositeEvaluationWeightedSpecification,
|
|
302
|
-
[CompositeEvaluationMetric.Custom]: CompositeEvaluationCustomSpecification,
|
|
303
|
-
},
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const selectedContextSchema = z.object({
|
|
307
|
-
messageIndex: z.number().int().nonnegative(),
|
|
308
|
-
contentBlockIndex: z.number().int().nonnegative(),
|
|
309
|
-
contentType: z.enum([
|
|
310
|
-
'text',
|
|
311
|
-
'reasoning',
|
|
312
|
-
'image',
|
|
313
|
-
'file',
|
|
314
|
-
'tool-call',
|
|
315
|
-
'tool-result',
|
|
316
|
-
]),
|
|
317
|
-
textRange: z
|
|
318
|
-
.object({
|
|
319
|
-
start: z.number().int().nonnegative(),
|
|
320
|
-
end: z.number().int().nonnegative(),
|
|
321
|
-
})
|
|
322
|
-
.optional(),
|
|
323
|
-
selectedText: z.string().optional(),
|
|
324
|
-
toolCallId: z.string().optional(),
|
|
325
|
-
});
|
|
326
|
-
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
327
|
-
enableControls: z.boolean().optional(), // UI annotation controls
|
|
328
|
-
criteria: z.string().optional(),
|
|
329
|
-
});
|
|
330
|
-
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
331
|
-
reason: z.string().optional(),
|
|
332
|
-
enrichedReason: z.string().optional(),
|
|
333
|
-
selectedContexts: z.array(selectedContextSchema).optional(),
|
|
334
|
-
});
|
|
335
|
-
const humanEvaluationResultError = baseEvaluationResultError.extend({});
|
|
336
|
-
// BINARY
|
|
337
|
-
const humanEvaluationBinaryConfiguration = humanEvaluationConfiguration.extend({
|
|
338
|
-
passDescription: z.string().optional(),
|
|
339
|
-
failDescription: z.string().optional(),
|
|
340
|
-
});
|
|
341
|
-
humanEvaluationResultMetadata.extend({
|
|
342
|
-
configuration: humanEvaluationBinaryConfiguration,
|
|
343
|
-
});
|
|
344
|
-
humanEvaluationResultError.extend({});
|
|
345
|
-
const HumanEvaluationBinarySpecification = {
|
|
346
|
-
};
|
|
347
|
-
// RATING
|
|
348
|
-
const humanEvaluationRatingConfiguration = humanEvaluationConfiguration.extend({
|
|
349
|
-
minRating: z.number(),
|
|
350
|
-
minRatingDescription: z.string().optional(),
|
|
351
|
-
maxRating: z.number(),
|
|
352
|
-
maxRatingDescription: z.string().optional(),
|
|
353
|
-
minThreshold: z.number().optional(), // Threshold in rating range
|
|
354
|
-
maxThreshold: z.number().optional(), // Threshold in rating range
|
|
355
|
-
});
|
|
356
|
-
humanEvaluationResultMetadata.extend({
|
|
357
|
-
configuration: humanEvaluationRatingConfiguration,
|
|
358
|
-
});
|
|
359
|
-
humanEvaluationResultError.extend({});
|
|
360
|
-
const HumanEvaluationRatingSpecification = {
|
|
361
|
-
};
|
|
362
|
-
/* ------------------------------------------------------------------------- */
|
|
363
|
-
var HumanEvaluationMetric;
|
|
364
|
-
(function (HumanEvaluationMetric) {
|
|
365
|
-
HumanEvaluationMetric["Binary"] = "binary";
|
|
366
|
-
HumanEvaluationMetric["Rating"] = "rating";
|
|
367
|
-
})(HumanEvaluationMetric || (HumanEvaluationMetric = {}));
|
|
368
|
-
const HumanEvaluationSpecification = {
|
|
369
|
-
// prettier-ignore
|
|
370
|
-
metrics: {
|
|
371
|
-
[HumanEvaluationMetric.Binary]: HumanEvaluationBinarySpecification,
|
|
372
|
-
[HumanEvaluationMetric.Rating]: HumanEvaluationRatingSpecification,
|
|
373
|
-
},
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
const llmEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
377
|
-
provider: z.string(),
|
|
378
|
-
model: z.string(),
|
|
379
|
-
});
|
|
380
|
-
const llmEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
381
|
-
evaluationLogId: z.number(),
|
|
382
|
-
reason: z.string(),
|
|
383
|
-
tokens: z.number(),
|
|
384
|
-
cost: z.number(),
|
|
385
|
-
duration: z.number(),
|
|
386
|
-
});
|
|
387
|
-
const llmEvaluationResultError = baseEvaluationResultError.extend({
|
|
388
|
-
runErrorId: z.number().optional(),
|
|
389
|
-
});
|
|
390
|
-
// BINARY
|
|
391
|
-
const llmEvaluationBinaryConfiguration = llmEvaluationConfiguration.extend({
|
|
392
|
-
criteria: z.string(),
|
|
393
|
-
passDescription: z.string(),
|
|
394
|
-
failDescription: z.string(),
|
|
395
|
-
});
|
|
396
|
-
llmEvaluationResultMetadata.extend({
|
|
397
|
-
configuration: llmEvaluationBinaryConfiguration,
|
|
398
|
-
});
|
|
399
|
-
llmEvaluationResultError.extend({});
|
|
400
|
-
const LlmEvaluationBinarySpecification = {
|
|
401
|
-
};
|
|
402
|
-
// RATING
|
|
403
|
-
const llmEvaluationRatingConfiguration = llmEvaluationConfiguration.extend({
|
|
404
|
-
criteria: z.string(),
|
|
405
|
-
minRating: z.number(),
|
|
406
|
-
minRatingDescription: z.string(),
|
|
407
|
-
maxRating: z.number(),
|
|
408
|
-
maxRatingDescription: z.string(),
|
|
409
|
-
minThreshold: z.number().optional(), // Threshold in rating range
|
|
410
|
-
maxThreshold: z.number().optional(), // Threshold in rating range
|
|
411
|
-
});
|
|
412
|
-
llmEvaluationResultMetadata.extend({
|
|
413
|
-
configuration: llmEvaluationRatingConfiguration,
|
|
414
|
-
});
|
|
415
|
-
llmEvaluationResultError.extend({});
|
|
416
|
-
const LlmEvaluationRatingSpecification = {
|
|
417
|
-
};
|
|
418
|
-
// COMPARISON
|
|
419
|
-
const llmEvaluationComparisonConfiguration = llmEvaluationConfiguration.extend({
|
|
420
|
-
criteria: z.string(),
|
|
421
|
-
passDescription: z.string(),
|
|
422
|
-
failDescription: z.string(),
|
|
423
|
-
minThreshold: z.number().optional(), // Threshold percentage
|
|
424
|
-
maxThreshold: z.number().optional(), // Threshold percentage
|
|
425
|
-
});
|
|
426
|
-
llmEvaluationResultMetadata.extend({
|
|
427
|
-
configuration: llmEvaluationComparisonConfiguration,
|
|
428
|
-
});
|
|
429
|
-
llmEvaluationResultError.extend({});
|
|
430
|
-
const LlmEvaluationComparisonSpecification = {
|
|
431
|
-
};
|
|
432
|
-
// CUSTOM
|
|
433
|
-
const llmEvaluationCustomConfiguration = llmEvaluationConfiguration.extend({
|
|
434
|
-
prompt: z.string(),
|
|
435
|
-
minScore: z.number(),
|
|
436
|
-
maxScore: z.number(),
|
|
437
|
-
minThreshold: z.number().optional(), // Threshold percentage
|
|
438
|
-
maxThreshold: z.number().optional(), // Threshold percentage
|
|
439
|
-
});
|
|
440
|
-
llmEvaluationResultMetadata.extend({
|
|
441
|
-
configuration: llmEvaluationCustomConfiguration,
|
|
442
|
-
});
|
|
443
|
-
llmEvaluationResultError.extend({});
|
|
444
|
-
const LlmEvaluationCustomSpecification = {
|
|
445
|
-
};
|
|
446
|
-
// CUSTOM LABELED
|
|
447
|
-
const LlmEvaluationCustomLabeledSpecification = {
|
|
448
|
-
};
|
|
449
|
-
/* ------------------------------------------------------------------------- */
|
|
450
|
-
var LlmEvaluationMetric;
|
|
451
|
-
(function (LlmEvaluationMetric) {
|
|
452
|
-
LlmEvaluationMetric["Binary"] = "binary";
|
|
453
|
-
LlmEvaluationMetric["Rating"] = "rating";
|
|
454
|
-
LlmEvaluationMetric["Comparison"] = "comparison";
|
|
455
|
-
LlmEvaluationMetric["Custom"] = "custom";
|
|
456
|
-
LlmEvaluationMetric["CustomLabeled"] = "custom_labeled";
|
|
457
|
-
})(LlmEvaluationMetric || (LlmEvaluationMetric = {}));
|
|
458
|
-
const LlmEvaluationSpecification = {
|
|
459
|
-
// prettier-ignore
|
|
460
|
-
metrics: {
|
|
461
|
-
[LlmEvaluationMetric.Binary]: LlmEvaluationBinarySpecification,
|
|
462
|
-
[LlmEvaluationMetric.Rating]: LlmEvaluationRatingSpecification,
|
|
463
|
-
[LlmEvaluationMetric.Comparison]: LlmEvaluationComparisonSpecification,
|
|
464
|
-
[LlmEvaluationMetric.Custom]: LlmEvaluationCustomSpecification,
|
|
465
|
-
[LlmEvaluationMetric.CustomLabeled]: LlmEvaluationCustomLabeledSpecification,
|
|
466
|
-
},
|
|
467
|
-
};
|
|
59
|
+
// src/sdk/init.ts
|
|
60
|
+
import { context as context2, propagation } from "@opentelemetry/api";
|
|
61
|
+
import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
|
|
62
|
+
import { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
63
|
+
import { Resource } from "@opentelemetry/resources";
|
|
64
|
+
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
65
|
+
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
468
66
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
configuration: ruleEvaluationRegularExpressionConfiguration,
|
|
490
|
-
});
|
|
491
|
-
ruleEvaluationResultError.extend({});
|
|
492
|
-
const RuleEvaluationRegularExpressionSpecification = {
|
|
493
|
-
};
|
|
494
|
-
// SCHEMA VALIDATION
|
|
495
|
-
const ruleEvaluationSchemaValidationConfiguration = ruleEvaluationConfiguration.extend({
|
|
496
|
-
format: z.enum(['json']),
|
|
497
|
-
schema: z.string(),
|
|
498
|
-
});
|
|
499
|
-
ruleEvaluationResultMetadata.extend({
|
|
500
|
-
configuration: ruleEvaluationSchemaValidationConfiguration,
|
|
501
|
-
});
|
|
502
|
-
ruleEvaluationResultError.extend({});
|
|
503
|
-
const RuleEvaluationSchemaValidationSpecification = {
|
|
504
|
-
};
|
|
505
|
-
// LENGTH COUNT
|
|
506
|
-
const ruleEvaluationLengthCountConfiguration = ruleEvaluationConfiguration.extend({
|
|
507
|
-
algorithm: z.enum(['character', 'word', 'sentence']),
|
|
508
|
-
minLength: z.number().optional(),
|
|
509
|
-
maxLength: z.number().optional(),
|
|
510
|
-
});
|
|
511
|
-
ruleEvaluationResultMetadata.extend({
|
|
512
|
-
configuration: ruleEvaluationLengthCountConfiguration,
|
|
513
|
-
});
|
|
514
|
-
ruleEvaluationResultError.extend({});
|
|
515
|
-
const RuleEvaluationLengthCountSpecification = {
|
|
516
|
-
};
|
|
517
|
-
// LEXICAL OVERLAP
|
|
518
|
-
const ruleEvaluationLexicalOverlapConfiguration = ruleEvaluationConfiguration.extend({
|
|
519
|
-
algorithm: z.enum(['substring', 'levenshtein_distance', 'rouge']),
|
|
520
|
-
minOverlap: z.number().optional(), // Percentage of overlap
|
|
521
|
-
maxOverlap: z.number().optional(), // Percentage of overlap
|
|
522
|
-
});
|
|
523
|
-
ruleEvaluationResultMetadata.extend({
|
|
524
|
-
configuration: ruleEvaluationLexicalOverlapConfiguration,
|
|
525
|
-
});
|
|
526
|
-
ruleEvaluationResultError.extend({});
|
|
527
|
-
const RuleEvaluationLexicalOverlapSpecification = {
|
|
528
|
-
};
|
|
529
|
-
// SEMANTIC SIMILARITY
|
|
530
|
-
const ruleEvaluationSemanticSimilarityConfiguration = ruleEvaluationConfiguration.extend({
|
|
531
|
-
algorithm: z.enum(['cosine_distance']),
|
|
532
|
-
minSimilarity: z.number().optional(), // Percentage of similarity
|
|
533
|
-
maxSimilarity: z.number().optional(), // Percentage of similarity
|
|
534
|
-
});
|
|
535
|
-
ruleEvaluationResultMetadata.extend({
|
|
536
|
-
configuration: ruleEvaluationSemanticSimilarityConfiguration,
|
|
537
|
-
});
|
|
538
|
-
ruleEvaluationResultError.extend({});
|
|
539
|
-
const RuleEvaluationSemanticSimilaritySpecification = {
|
|
540
|
-
};
|
|
541
|
-
// NUMERIC SIMILARITY
|
|
542
|
-
const ruleEvaluationNumericSimilarityConfiguration = ruleEvaluationConfiguration.extend({
|
|
543
|
-
algorithm: z.enum(['relative_difference']),
|
|
544
|
-
minSimilarity: z.number().optional(), // Percentage of similarity
|
|
545
|
-
maxSimilarity: z.number().optional(), // Percentage of similarity
|
|
546
|
-
});
|
|
547
|
-
ruleEvaluationResultMetadata.extend({
|
|
548
|
-
configuration: ruleEvaluationNumericSimilarityConfiguration,
|
|
549
|
-
});
|
|
550
|
-
ruleEvaluationResultError.extend({});
|
|
551
|
-
const RuleEvaluationNumericSimilaritySpecification = {
|
|
552
|
-
};
|
|
553
|
-
/* ------------------------------------------------------------------------- */
|
|
554
|
-
var RuleEvaluationMetric;
|
|
555
|
-
(function (RuleEvaluationMetric) {
|
|
556
|
-
RuleEvaluationMetric["ExactMatch"] = "exact_match";
|
|
557
|
-
RuleEvaluationMetric["RegularExpression"] = "regular_expression";
|
|
558
|
-
RuleEvaluationMetric["SchemaValidation"] = "schema_validation";
|
|
559
|
-
RuleEvaluationMetric["LengthCount"] = "length_count";
|
|
560
|
-
RuleEvaluationMetric["LexicalOverlap"] = "lexical_overlap";
|
|
561
|
-
RuleEvaluationMetric["SemanticSimilarity"] = "semantic_similarity";
|
|
562
|
-
RuleEvaluationMetric["NumericSimilarity"] = "numeric_similarity";
|
|
563
|
-
})(RuleEvaluationMetric || (RuleEvaluationMetric = {}));
|
|
564
|
-
const RuleEvaluationSpecification = {
|
|
565
|
-
// prettier-ignore
|
|
566
|
-
metrics: {
|
|
567
|
-
[RuleEvaluationMetric.ExactMatch]: RuleEvaluationExactMatchSpecification,
|
|
568
|
-
[RuleEvaluationMetric.RegularExpression]: RuleEvaluationRegularExpressionSpecification,
|
|
569
|
-
[RuleEvaluationMetric.SchemaValidation]: RuleEvaluationSchemaValidationSpecification,
|
|
570
|
-
[RuleEvaluationMetric.LengthCount]: RuleEvaluationLengthCountSpecification,
|
|
571
|
-
[RuleEvaluationMetric.LexicalOverlap]: RuleEvaluationLexicalOverlapSpecification,
|
|
572
|
-
[RuleEvaluationMetric.SemanticSimilarity]: RuleEvaluationSemanticSimilaritySpecification,
|
|
573
|
-
[RuleEvaluationMetric.NumericSimilarity]: RuleEvaluationNumericSimilaritySpecification,
|
|
574
|
-
},
|
|
67
|
+
// src/sdk/instrumentations.ts
|
|
68
|
+
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
69
|
+
import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic";
|
|
70
|
+
import { BedrockInstrumentation } from "@traceloop/instrumentation-bedrock";
|
|
71
|
+
import { CohereInstrumentation } from "@traceloop/instrumentation-cohere";
|
|
72
|
+
import { LangChainInstrumentation } from "@traceloop/instrumentation-langchain";
|
|
73
|
+
import { LlamaIndexInstrumentation } from "@traceloop/instrumentation-llamaindex";
|
|
74
|
+
import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
|
|
75
|
+
import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
|
|
76
|
+
import { AIPlatformInstrumentation, VertexAIInstrumentation } from "@traceloop/instrumentation-vertexai";
|
|
77
|
+
var INSTRUMENTATION_MAP = {
|
|
78
|
+
openai: { ctor: OpenAIInstrumentation, moduleName: "openai", defaultEnrichTokens: true },
|
|
79
|
+
anthropic: { ctor: AnthropicInstrumentation, moduleName: "@anthropic-ai/sdk" },
|
|
80
|
+
bedrock: { ctor: BedrockInstrumentation, moduleName: "@aws-sdk/client-bedrock-runtime" },
|
|
81
|
+
cohere: { ctor: CohereInstrumentation, moduleName: "cohere-ai" },
|
|
82
|
+
langchain: { ctor: LangChainInstrumentation, moduleName: "langchain" },
|
|
83
|
+
llamaindex: { ctor: LlamaIndexInstrumentation, moduleName: "llamaindex" },
|
|
84
|
+
togetherai: { ctor: TogetherInstrumentation, moduleName: "together-ai", defaultEnrichTokens: false },
|
|
85
|
+
vertexai: { ctor: VertexAIInstrumentation, moduleName: "@google-cloud/vertexai" },
|
|
86
|
+
aiplatform: { ctor: AIPlatformInstrumentation, moduleName: "@google-cloud/aiplatform" }
|
|
575
87
|
};
|
|
88
|
+
async function createLatitudeInstrumentations(options) {
|
|
89
|
+
const result = [];
|
|
90
|
+
for (const type of options.instrumentations) {
|
|
91
|
+
const config = INSTRUMENTATION_MAP[type];
|
|
92
|
+
if (!config) {
|
|
93
|
+
console.warn(`[Latitude] Unknown instrumentation type: ${type}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const enrichTokens = options.enrichTokens?.[type] ?? config.defaultEnrichTokens;
|
|
97
|
+
const inst = new config.ctor(enrichTokens !== void 0 ? { enrichTokens } : void 0);
|
|
98
|
+
const moduleRef = options.modules?.[type] ?? await tryRequire(config.moduleName);
|
|
99
|
+
if (!moduleRef) {
|
|
100
|
+
console.warn(
|
|
101
|
+
`[Latitude] Module not found for ${type}: ${config.moduleName}. Install it or pass it explicitly in 'modules'.`
|
|
102
|
+
);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
inst.manuallyInstrument?.(moduleRef);
|
|
106
|
+
result.push(inst);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
async function tryRequire(moduleName) {
|
|
111
|
+
try {
|
|
112
|
+
return __require(moduleName);
|
|
113
|
+
} catch {
|
|
114
|
+
try {
|
|
115
|
+
const mod = await import(moduleName);
|
|
116
|
+
return mod.default ?? mod;
|
|
117
|
+
} catch {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async function registerLatitudeInstrumentations(options) {
|
|
123
|
+
const instrumentations = await createLatitudeInstrumentations(options);
|
|
124
|
+
registerInstrumentations({
|
|
125
|
+
instrumentations,
|
|
126
|
+
tracerProvider: options.tracerProvider
|
|
127
|
+
});
|
|
128
|
+
}
|
|
576
129
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
})(EvaluationType || (EvaluationType = {}));
|
|
584
|
-
const EvaluationTypeSchema = z.enum(EvaluationType);
|
|
585
|
-
const EvaluationMetricSchema = z.union([
|
|
586
|
-
z.enum(RuleEvaluationMetric),
|
|
587
|
-
z.enum(LlmEvaluationMetric),
|
|
588
|
-
z.enum(HumanEvaluationMetric),
|
|
589
|
-
z.enum(CompositeEvaluationMetric),
|
|
590
|
-
]);
|
|
591
|
-
const EvaluationConfigurationSchema = z.custom();
|
|
592
|
-
// prettier-ignore
|
|
593
|
-
z.custom();
|
|
594
|
-
// prettier-ignore
|
|
595
|
-
z.custom();
|
|
596
|
-
({
|
|
597
|
-
[EvaluationType.Rule]: RuleEvaluationSpecification,
|
|
598
|
-
[EvaluationType.Llm]: LlmEvaluationSpecification,
|
|
599
|
-
[EvaluationType.Human]: HumanEvaluationSpecification,
|
|
600
|
-
[EvaluationType.Composite]: CompositeEvaluationSpecification,
|
|
601
|
-
});
|
|
602
|
-
z.object({
|
|
603
|
-
name: z.string(),
|
|
604
|
-
description: z.string(),
|
|
605
|
-
type: EvaluationTypeSchema,
|
|
606
|
-
metric: EvaluationMetricSchema,
|
|
607
|
-
configuration: EvaluationConfigurationSchema,
|
|
608
|
-
});
|
|
609
|
-
z.object({
|
|
610
|
-
evaluateLiveLogs: z.boolean().nullable().optional(),
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
var ChainEventTypes;
|
|
614
|
-
(function (ChainEventTypes) {
|
|
615
|
-
ChainEventTypes["ChainCompleted"] = "chain-completed";
|
|
616
|
-
ChainEventTypes["ChainError"] = "chain-error";
|
|
617
|
-
ChainEventTypes["ChainStarted"] = "chain-started";
|
|
618
|
-
ChainEventTypes["IntegrationWakingUp"] = "integration-waking-up";
|
|
619
|
-
ChainEventTypes["ProviderCompleted"] = "provider-completed";
|
|
620
|
-
ChainEventTypes["ProviderStarted"] = "provider-started";
|
|
621
|
-
ChainEventTypes["StepCompleted"] = "step-completed";
|
|
622
|
-
ChainEventTypes["StepStarted"] = "step-started";
|
|
623
|
-
ChainEventTypes["ToolCompleted"] = "tool-completed";
|
|
624
|
-
ChainEventTypes["ToolResult"] = "tool-result";
|
|
625
|
-
ChainEventTypes["ToolsStarted"] = "tools-started";
|
|
626
|
-
})(ChainEventTypes || (ChainEventTypes = {}));
|
|
627
|
-
|
|
628
|
-
z.object({
|
|
629
|
-
name: z.string(),
|
|
630
|
-
provider: z.string(),
|
|
631
|
-
model: z.string(),
|
|
632
|
-
temperature: z.number(),
|
|
633
|
-
});
|
|
634
|
-
// Experiment ran from a dataset
|
|
635
|
-
const experimentDatasetSourceSchema = z.object({
|
|
636
|
-
source: z.literal('dataset'),
|
|
637
|
-
datasetId: z.number(),
|
|
638
|
-
fromRow: z.number(),
|
|
639
|
-
toRow: z.number(),
|
|
640
|
-
datasetLabels: z.record(z.string(), z.string()),
|
|
641
|
-
parametersMap: z.record(z.string(), z.number()),
|
|
642
|
-
});
|
|
643
|
-
// Experiment ran from last logs (from commit and creation time of experiment)
|
|
644
|
-
const experimentLogsSourceSchema = z.object({
|
|
645
|
-
source: z.literal('logs'),
|
|
646
|
-
count: z.number(),
|
|
647
|
-
});
|
|
648
|
-
// Experiment ran with manual parameters (currently only used for prompts with no parameters)
|
|
649
|
-
const experimentManualSourceSchema = z.object({
|
|
650
|
-
source: z.literal('manual'),
|
|
651
|
-
count: z.number(),
|
|
652
|
-
parametersMap: z.record(z.string(), z.number()),
|
|
653
|
-
});
|
|
654
|
-
z.discriminatedUnion('source', [
|
|
655
|
-
experimentDatasetSourceSchema,
|
|
656
|
-
experimentLogsSourceSchema,
|
|
657
|
-
experimentManualSourceSchema,
|
|
658
|
-
]);
|
|
659
|
-
|
|
660
|
-
var QuotaType;
|
|
661
|
-
(function (QuotaType) {
|
|
662
|
-
QuotaType["Seats"] = "seats";
|
|
663
|
-
QuotaType["Runs"] = "runs";
|
|
664
|
-
QuotaType["Credits"] = "credits";
|
|
665
|
-
})(QuotaType || (QuotaType = {}));
|
|
666
|
-
var GrantSource;
|
|
667
|
-
(function (GrantSource) {
|
|
668
|
-
GrantSource["System"] = "system";
|
|
669
|
-
GrantSource["Subscription"] = "subscription";
|
|
670
|
-
GrantSource["Purchase"] = "purchase";
|
|
671
|
-
GrantSource["Reward"] = "reward";
|
|
672
|
-
GrantSource["Promocode"] = "promocode";
|
|
673
|
-
})(GrantSource || (GrantSource = {}));
|
|
674
|
-
|
|
675
|
-
var ModifiedDocumentType;
|
|
676
|
-
(function (ModifiedDocumentType) {
|
|
677
|
-
ModifiedDocumentType["Created"] = "created";
|
|
678
|
-
ModifiedDocumentType["Updated"] = "updated";
|
|
679
|
-
ModifiedDocumentType["UpdatedPath"] = "updated_path";
|
|
680
|
-
ModifiedDocumentType["Deleted"] = "deleted";
|
|
681
|
-
})(ModifiedDocumentType || (ModifiedDocumentType = {}));
|
|
682
|
-
|
|
683
|
-
var IntegrationType;
|
|
684
|
-
(function (IntegrationType) {
|
|
685
|
-
IntegrationType["Latitude"] = "latitude";
|
|
686
|
-
IntegrationType["ExternalMCP"] = "custom_mcp";
|
|
687
|
-
IntegrationType["Pipedream"] = "pipedream";
|
|
688
|
-
IntegrationType["HostedMCP"] = "mcp_server";
|
|
689
|
-
})(IntegrationType || (IntegrationType = {}));
|
|
690
|
-
var HostedIntegrationType;
|
|
691
|
-
(function (HostedIntegrationType) {
|
|
692
|
-
HostedIntegrationType["Stripe"] = "stripe";
|
|
693
|
-
HostedIntegrationType["Slack"] = "slack";
|
|
694
|
-
HostedIntegrationType["Github"] = "github";
|
|
695
|
-
HostedIntegrationType["Notion"] = "notion";
|
|
696
|
-
HostedIntegrationType["Twitter"] = "twitter";
|
|
697
|
-
HostedIntegrationType["Airtable"] = "airtable";
|
|
698
|
-
HostedIntegrationType["Linear"] = "linear";
|
|
699
|
-
HostedIntegrationType["YoutubeCaptions"] = "youtube_captions";
|
|
700
|
-
HostedIntegrationType["Reddit"] = "reddit";
|
|
701
|
-
HostedIntegrationType["Telegram"] = "telegram";
|
|
702
|
-
HostedIntegrationType["Tinybird"] = "tinybird";
|
|
703
|
-
HostedIntegrationType["Perplexity"] = "perplexity";
|
|
704
|
-
HostedIntegrationType["AwsKbRetrieval"] = "aws_kb_retrieval";
|
|
705
|
-
HostedIntegrationType["BraveSearch"] = "brave_search";
|
|
706
|
-
HostedIntegrationType["EverArt"] = "ever_art";
|
|
707
|
-
HostedIntegrationType["Fetch"] = "fetch";
|
|
708
|
-
HostedIntegrationType["GitLab"] = "gitlab";
|
|
709
|
-
HostedIntegrationType["GoogleMaps"] = "google_maps";
|
|
710
|
-
HostedIntegrationType["Sentry"] = "sentry";
|
|
711
|
-
HostedIntegrationType["Puppeteer"] = "puppeteer";
|
|
712
|
-
HostedIntegrationType["Time"] = "time";
|
|
713
|
-
HostedIntegrationType["browserbase"] = "browserbase";
|
|
714
|
-
HostedIntegrationType["Neon"] = "neon";
|
|
715
|
-
HostedIntegrationType["Postgres"] = "postgres";
|
|
716
|
-
HostedIntegrationType["Supabase"] = "supabase";
|
|
717
|
-
HostedIntegrationType["Redis"] = "redis";
|
|
718
|
-
HostedIntegrationType["Jira"] = "jira";
|
|
719
|
-
HostedIntegrationType["Attio"] = "attio";
|
|
720
|
-
HostedIntegrationType["Ghost"] = "ghost";
|
|
721
|
-
HostedIntegrationType["Figma"] = "figma";
|
|
722
|
-
HostedIntegrationType["Hyperbrowser"] = "hyperbrowser";
|
|
723
|
-
HostedIntegrationType["Audiense"] = "audiense";
|
|
724
|
-
HostedIntegrationType["Apify"] = "apify";
|
|
725
|
-
HostedIntegrationType["Exa"] = "exa";
|
|
726
|
-
HostedIntegrationType["YepCode"] = "yepcode";
|
|
727
|
-
HostedIntegrationType["Monday"] = "monday";
|
|
728
|
-
HostedIntegrationType["AgentQL"] = "agentql";
|
|
729
|
-
HostedIntegrationType["AgentRPC"] = "agentrpc";
|
|
730
|
-
HostedIntegrationType["AstraDB"] = "astra_db";
|
|
731
|
-
HostedIntegrationType["Bankless"] = "bankless";
|
|
732
|
-
HostedIntegrationType["Bicscan"] = "bicscan";
|
|
733
|
-
HostedIntegrationType["Chargebee"] = "chargebee";
|
|
734
|
-
HostedIntegrationType["Chronulus"] = "chronulus";
|
|
735
|
-
HostedIntegrationType["CircleCI"] = "circleci";
|
|
736
|
-
HostedIntegrationType["Codacy"] = "codacy";
|
|
737
|
-
HostedIntegrationType["CodeLogic"] = "codelogic";
|
|
738
|
-
HostedIntegrationType["Convex"] = "convex";
|
|
739
|
-
HostedIntegrationType["Dart"] = "dart";
|
|
740
|
-
HostedIntegrationType["DevHubCMS"] = "devhub_cms";
|
|
741
|
-
HostedIntegrationType["Elasticsearch"] = "elasticsearch";
|
|
742
|
-
HostedIntegrationType["ESignatures"] = "esignatures";
|
|
743
|
-
HostedIntegrationType["Fewsats"] = "fewsats";
|
|
744
|
-
HostedIntegrationType["Firecrawl"] = "firecrawl";
|
|
745
|
-
HostedIntegrationType["Graphlit"] = "graphlit";
|
|
746
|
-
HostedIntegrationType["Heroku"] = "heroku";
|
|
747
|
-
HostedIntegrationType["IntegrationAppHubspot"] = "integration_app_hubspot";
|
|
748
|
-
HostedIntegrationType["LaraTranslate"] = "lara_translate";
|
|
749
|
-
HostedIntegrationType["Logfire"] = "logfire";
|
|
750
|
-
HostedIntegrationType["Langfuse"] = "langfuse";
|
|
751
|
-
HostedIntegrationType["LingoSupabase"] = "lingo_supabase";
|
|
752
|
-
HostedIntegrationType["Make"] = "make";
|
|
753
|
-
HostedIntegrationType["Meilisearch"] = "meilisearch";
|
|
754
|
-
HostedIntegrationType["Momento"] = "momento";
|
|
755
|
-
HostedIntegrationType["Neo4jAura"] = "neo4j_aura";
|
|
756
|
-
HostedIntegrationType["Octagon"] = "octagon";
|
|
757
|
-
HostedIntegrationType["Paddle"] = "paddle";
|
|
758
|
-
HostedIntegrationType["PayPal"] = "paypal";
|
|
759
|
-
HostedIntegrationType["Qdrant"] = "qdrant";
|
|
760
|
-
HostedIntegrationType["Raygun"] = "raygun";
|
|
761
|
-
HostedIntegrationType["Rember"] = "rember";
|
|
762
|
-
HostedIntegrationType["Riza"] = "riza";
|
|
763
|
-
HostedIntegrationType["Search1API"] = "search1api";
|
|
764
|
-
HostedIntegrationType["Semgrep"] = "semgrep";
|
|
765
|
-
HostedIntegrationType["Tavily"] = "tavily";
|
|
766
|
-
HostedIntegrationType["Unstructured"] = "unstructured";
|
|
767
|
-
HostedIntegrationType["Vectorize"] = "vectorize";
|
|
768
|
-
HostedIntegrationType["Xero"] = "xero";
|
|
769
|
-
HostedIntegrationType["Readwise"] = "readwise";
|
|
770
|
-
HostedIntegrationType["Airbnb"] = "airbnb";
|
|
771
|
-
HostedIntegrationType["Mintlify"] = "mintlify";
|
|
772
|
-
// Require all auth file :point_down:
|
|
773
|
-
// Gmail = 'google_drive',
|
|
774
|
-
// GoogleCalendar = 'google_drive',
|
|
775
|
-
// GoogleDrive = 'google_drive',
|
|
776
|
-
// GoogleWorkspace = 'google_workspace', // env vars not supported (?)
|
|
777
|
-
// TODO: implement these
|
|
778
|
-
// Wordpress = 'wordpress', // Not on OpenTools
|
|
779
|
-
// Discord = 'discord', // Not on OpenTools
|
|
780
|
-
// Intercom = 'intercom', // Not on OpenTools
|
|
781
|
-
// Hubspot = 'hubspot', // Docker based
|
|
782
|
-
// Loops = 'loops', // Does not exist
|
|
783
|
-
})(HostedIntegrationType || (HostedIntegrationType = {}));
|
|
784
|
-
|
|
785
|
-
var LogSources;
|
|
786
|
-
(function (LogSources) {
|
|
787
|
-
LogSources["API"] = "api";
|
|
788
|
-
LogSources["AgentAsTool"] = "agent_as_tool";
|
|
789
|
-
LogSources["Copilot"] = "copilot";
|
|
790
|
-
LogSources["EmailTrigger"] = "email_trigger";
|
|
791
|
-
LogSources["Evaluation"] = "evaluation";
|
|
792
|
-
LogSources["Experiment"] = "experiment";
|
|
793
|
-
LogSources["IntegrationTrigger"] = "integration_trigger";
|
|
794
|
-
LogSources["Playground"] = "playground";
|
|
795
|
-
LogSources["ScheduledTrigger"] = "scheduled_trigger";
|
|
796
|
-
LogSources["SharedPrompt"] = "shared_prompt";
|
|
797
|
-
LogSources["ShadowTest"] = "shadow_test";
|
|
798
|
-
LogSources["ABTestChallenger"] = "ab_test_challenger";
|
|
799
|
-
LogSources["User"] = "user";
|
|
800
|
-
LogSources["Optimization"] = "optimization";
|
|
801
|
-
})(LogSources || (LogSources = {}));
|
|
802
|
-
|
|
803
|
-
var RunSourceGroup;
|
|
804
|
-
(function (RunSourceGroup) {
|
|
805
|
-
RunSourceGroup["Production"] = "production";
|
|
806
|
-
RunSourceGroup["Playground"] = "playground";
|
|
807
|
-
})(RunSourceGroup || (RunSourceGroup = {}));
|
|
808
|
-
({
|
|
809
|
-
[RunSourceGroup.Production]: [
|
|
810
|
-
LogSources.API,
|
|
811
|
-
LogSources.ShadowTest,
|
|
812
|
-
LogSources.ABTestChallenger,
|
|
813
|
-
LogSources.EmailTrigger,
|
|
814
|
-
LogSources.IntegrationTrigger,
|
|
815
|
-
LogSources.ScheduledTrigger,
|
|
816
|
-
LogSources.SharedPrompt,
|
|
817
|
-
LogSources.User,
|
|
818
|
-
],
|
|
819
|
-
[RunSourceGroup.Playground]: [LogSources.Playground, LogSources.Experiment],
|
|
820
|
-
});
|
|
130
|
+
// src/sdk/processor.ts
|
|
131
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
132
|
+
import {
|
|
133
|
+
BatchSpanProcessor,
|
|
134
|
+
SimpleSpanProcessor
|
|
135
|
+
} from "@opentelemetry/sdk-trace-node";
|
|
821
136
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
})(SpanKind || (SpanKind = {}));
|
|
830
|
-
// Note: loosely based on OpenTelemetry GenAI semantic conventions
|
|
831
|
-
var SpanType;
|
|
832
|
-
(function (SpanType) {
|
|
833
|
-
// Latitude wrappers
|
|
834
|
-
SpanType["Prompt"] = "prompt";
|
|
835
|
-
SpanType["Chat"] = "chat";
|
|
836
|
-
SpanType["External"] = "external";
|
|
837
|
-
SpanType["UnresolvedExternal"] = "unresolved_external";
|
|
838
|
-
// Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
|
|
839
|
-
SpanType["Http"] = "http";
|
|
840
|
-
// Any known span from supported specifications will be grouped into one of these types
|
|
841
|
-
SpanType["Completion"] = "completion";
|
|
842
|
-
SpanType["Tool"] = "tool";
|
|
843
|
-
SpanType["Embedding"] = "embedding";
|
|
844
|
-
SpanType["Unknown"] = "unknown";
|
|
845
|
-
})(SpanType || (SpanType = {}));
|
|
846
|
-
[
|
|
847
|
-
SpanType.Prompt,
|
|
848
|
-
SpanType.External,
|
|
849
|
-
SpanType.Chat,
|
|
850
|
-
];
|
|
851
|
-
const SPAN_SPECIFICATIONS = {
|
|
852
|
-
[SpanType.Prompt]: {
|
|
853
|
-
name: 'Prompt',
|
|
854
|
-
description: 'A prompt span',
|
|
855
|
-
isGenAI: false,
|
|
856
|
-
isHidden: false,
|
|
857
|
-
},
|
|
858
|
-
[SpanType.Chat]: {
|
|
859
|
-
name: 'Chat',
|
|
860
|
-
description: 'A chat continuation span',
|
|
861
|
-
isGenAI: false,
|
|
862
|
-
isHidden: false,
|
|
863
|
-
},
|
|
864
|
-
[SpanType.External]: {
|
|
865
|
-
name: 'External',
|
|
866
|
-
description: 'An external capture span',
|
|
867
|
-
isGenAI: false,
|
|
868
|
-
isHidden: false,
|
|
869
|
-
},
|
|
870
|
-
[SpanType.UnresolvedExternal]: {
|
|
871
|
-
name: 'Unresolved External',
|
|
872
|
-
description: 'An external span that needs path resolution before storage',
|
|
873
|
-
isGenAI: false,
|
|
874
|
-
isHidden: true,
|
|
875
|
-
},
|
|
876
|
-
[SpanType.Completion]: {
|
|
877
|
-
name: 'Completion',
|
|
878
|
-
description: 'A completion call',
|
|
879
|
-
isGenAI: true,
|
|
880
|
-
isHidden: false,
|
|
881
|
-
},
|
|
882
|
-
[SpanType.Embedding]: {
|
|
883
|
-
name: 'Embedding',
|
|
884
|
-
description: 'An embedding call',
|
|
885
|
-
isGenAI: true,
|
|
886
|
-
isHidden: false,
|
|
887
|
-
},
|
|
888
|
-
[SpanType.Tool]: {
|
|
889
|
-
name: 'Tool',
|
|
890
|
-
description: 'A tool call',
|
|
891
|
-
isGenAI: true,
|
|
892
|
-
isHidden: false,
|
|
893
|
-
},
|
|
894
|
-
[SpanType.Http]: {
|
|
895
|
-
name: 'HTTP',
|
|
896
|
-
description: 'An HTTP request',
|
|
897
|
-
isGenAI: false,
|
|
898
|
-
isHidden: true,
|
|
899
|
-
},
|
|
900
|
-
[SpanType.Unknown]: {
|
|
901
|
-
name: 'Unknown',
|
|
902
|
-
description: 'An unknown span',
|
|
903
|
-
isGenAI: false,
|
|
904
|
-
isHidden: true,
|
|
905
|
-
},
|
|
137
|
+
// src/constants/attributes.ts
|
|
138
|
+
var ATTRIBUTES = {
|
|
139
|
+
name: "latitude.capture.name",
|
|
140
|
+
tags: "latitude.tags",
|
|
141
|
+
metadata: "latitude.metadata",
|
|
142
|
+
sessionId: "session.id",
|
|
143
|
+
userId: "user.id"
|
|
906
144
|
};
|
|
907
|
-
var SpanStatus;
|
|
908
|
-
(function (SpanStatus) {
|
|
909
|
-
SpanStatus["Unset"] = "unset";
|
|
910
|
-
SpanStatus["Ok"] = "ok";
|
|
911
|
-
SpanStatus["Error"] = "error";
|
|
912
|
-
})(SpanStatus || (SpanStatus = {}));
|
|
913
|
-
new Set([
|
|
914
|
-
SpanType.Prompt,
|
|
915
|
-
SpanType.Chat,
|
|
916
|
-
SpanType.External,
|
|
917
|
-
]);
|
|
918
145
|
|
|
919
|
-
//
|
|
920
|
-
|
|
921
|
-
z.object({
|
|
922
|
-
traceparent: z.string(), // <version>-<trace-id>-<span-id>-<trace-flags>
|
|
923
|
-
tracestate: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
924
|
-
baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
925
|
-
});
|
|
146
|
+
// src/constants/scope.ts
|
|
147
|
+
var SCOPE_LATITUDE = "so.latitude.instrumentation";
|
|
926
148
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
previousTraceId: 'latitude.previous_trace_id',
|
|
941
|
-
// Custom additions to the GenAI semantic conventions (deprecated)
|
|
942
|
-
request: {
|
|
943
|
-
_root: 'gen_ai.request',
|
|
944
|
-
configuration: 'gen_ai.request.configuration',
|
|
945
|
-
template: 'gen_ai.request.template',
|
|
946
|
-
parameters: 'gen_ai.request.parameters'},
|
|
947
|
-
response: {
|
|
948
|
-
_root: 'gen_ai.response'},
|
|
949
|
-
usage: {
|
|
950
|
-
promptTokens: 'gen_ai.usage.prompt_tokens',
|
|
951
|
-
cachedTokens: 'gen_ai.usage.cached_tokens',
|
|
952
|
-
reasoningTokens: 'gen_ai.usage.reasoning_tokens',
|
|
953
|
-
completionTokens: 'gen_ai.usage.completion_tokens',
|
|
954
|
-
},
|
|
955
|
-
},
|
|
956
|
-
// Official OpenTelemetry semantic conventions
|
|
957
|
-
OPENTELEMETRY: {
|
|
958
|
-
HTTP: {
|
|
959
|
-
request: {
|
|
960
|
-
url: 'http.request.url',
|
|
961
|
-
body: 'http.request.body',
|
|
962
|
-
header: 'http.request.header',
|
|
963
|
-
method: ATTR_HTTP_REQUEST_METHOD,
|
|
964
|
-
},
|
|
965
|
-
response: {
|
|
966
|
-
body: 'http.response.body',
|
|
967
|
-
header: 'http.response.header',
|
|
968
|
-
statusCode: ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
969
|
-
},
|
|
970
|
-
},
|
|
971
|
-
// GenAI semantic conventions
|
|
972
|
-
// https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
|
|
973
|
-
GEN_AI: {
|
|
974
|
-
operation: ATTR_GEN_AI_OPERATION_NAME,
|
|
975
|
-
response: {
|
|
976
|
-
model: ATTR_GEN_AI_RESPONSE_MODEL,
|
|
977
|
-
finishReasons: ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
|
|
978
|
-
},
|
|
979
|
-
usage: {
|
|
980
|
-
inputTokens: ATTR_GEN_AI_USAGE_INPUT_TOKENS,
|
|
981
|
-
outputTokens: ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
982
|
-
},
|
|
983
|
-
systemInstructions: 'gen_ai.system.instructions', // Contains the PARTS of the "system message"
|
|
984
|
-
tool: {
|
|
985
|
-
call: {
|
|
986
|
-
id: ATTR_GEN_AI_TOOL_CALL_ID,
|
|
987
|
-
arguments: 'gen_ai.tool.call.arguments'}},
|
|
988
|
-
input: {
|
|
989
|
-
messages: 'gen_ai.input.messages',
|
|
990
|
-
},
|
|
991
|
-
output: {
|
|
992
|
-
messages: 'gen_ai.output.messages',
|
|
993
|
-
},
|
|
994
|
-
_deprecated: {
|
|
995
|
-
system: ATTR_GEN_AI_SYSTEM,
|
|
996
|
-
tool: {
|
|
997
|
-
name: ATTR_GEN_AI_TOOL_NAME,
|
|
998
|
-
type: ATTR_GEN_AI_TOOL_TYPE,
|
|
999
|
-
result: {
|
|
1000
|
-
value: 'gen_ai.tool.result.value',
|
|
1001
|
-
isError: 'gen_ai.tool.result.is_error',
|
|
1002
|
-
},
|
|
1003
|
-
}},
|
|
1004
|
-
},
|
|
1005
|
-
}};
|
|
1006
|
-
const VALUES = {
|
|
1007
|
-
OPENTELEMETRY: {
|
|
1008
|
-
GEN_AI: {
|
|
1009
|
-
response: {
|
|
1010
|
-
finishReasons: {
|
|
1011
|
-
stop: 'stop',
|
|
1012
|
-
toolCalls: 'tool_calls'},
|
|
1013
|
-
},
|
|
1014
|
-
tool: {
|
|
1015
|
-
type: {
|
|
1016
|
-
function: 'function',
|
|
1017
|
-
},
|
|
1018
|
-
}},
|
|
1019
|
-
}};
|
|
149
|
+
// src/env/env.ts
|
|
150
|
+
var DEFAULT_EXPORTER_URL = {
|
|
151
|
+
production: "https://ingest.latitude.so",
|
|
152
|
+
development: "http://localhost:3002",
|
|
153
|
+
test: "http://localhost:3002"
|
|
154
|
+
}[process.env.NODE_ENV ?? "development"] ?? "http://localhost:3002";
|
|
155
|
+
function getExporterUrl() {
|
|
156
|
+
if (process.env.LATITUDE_TELEMETRY_URL) {
|
|
157
|
+
return process.env.LATITUDE_TELEMETRY_URL;
|
|
158
|
+
}
|
|
159
|
+
return DEFAULT_EXPORTER_URL;
|
|
160
|
+
}
|
|
161
|
+
var env = { EXPORTER_URL: getExporterUrl() };
|
|
1020
162
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
(
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
(
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
.object({
|
|
1058
|
-
values: z.array(z.object({
|
|
1059
|
-
stringValue: z.string().optional(),
|
|
1060
|
-
intValue: z.number().optional(),
|
|
1061
|
-
boolValue: z.boolean().optional(),
|
|
1062
|
-
})),
|
|
1063
|
-
})
|
|
1064
|
-
.optional(),
|
|
1065
|
-
});
|
|
1066
|
-
Otlp.attributeSchema = z.object({
|
|
1067
|
-
key: z.string(),
|
|
1068
|
-
value: Otlp.attributeValueSchema,
|
|
1069
|
-
});
|
|
1070
|
-
Otlp.eventSchema = z.object({
|
|
1071
|
-
name: z.string(),
|
|
1072
|
-
timeUnixNano: z.string(),
|
|
1073
|
-
attributes: z.array(Otlp.attributeSchema).optional(),
|
|
1074
|
-
});
|
|
1075
|
-
Otlp.linkSchema = z.object({
|
|
1076
|
-
traceId: z.string(),
|
|
1077
|
-
spanId: z.string(),
|
|
1078
|
-
attributes: z.array(Otlp.attributeSchema).optional(),
|
|
1079
|
-
});
|
|
1080
|
-
(function (StatusCode) {
|
|
1081
|
-
StatusCode[StatusCode["Unset"] = 0] = "Unset";
|
|
1082
|
-
StatusCode[StatusCode["Ok"] = 1] = "Ok";
|
|
1083
|
-
StatusCode[StatusCode["Error"] = 2] = "Error";
|
|
1084
|
-
})(Otlp.StatusCode || (Otlp.StatusCode = {}));
|
|
1085
|
-
Otlp.statusSchema = z.object({
|
|
1086
|
-
code: z.number(),
|
|
1087
|
-
message: z.string().optional(),
|
|
163
|
+
// src/sdk/redact.ts
|
|
164
|
+
var RedactSpanProcessor = class {
|
|
165
|
+
options;
|
|
166
|
+
constructor(options) {
|
|
167
|
+
this.options = options;
|
|
168
|
+
if (!options.mask) {
|
|
169
|
+
this.options.mask = (_attribute, _value) => "******";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
onStart(_span, _context) {
|
|
173
|
+
}
|
|
174
|
+
onEnd(span) {
|
|
175
|
+
Object.assign(span.attributes, this.redactAttributes(span.attributes));
|
|
176
|
+
for (const event of span.events) {
|
|
177
|
+
if (!event.attributes) continue;
|
|
178
|
+
Object.assign(event.attributes, this.redactAttributes(event.attributes));
|
|
179
|
+
}
|
|
180
|
+
for (const link of span.links) {
|
|
181
|
+
if (!link.attributes) continue;
|
|
182
|
+
Object.assign(link.attributes, this.redactAttributes(link.attributes));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
forceFlush() {
|
|
186
|
+
return Promise.resolve();
|
|
187
|
+
}
|
|
188
|
+
shutdown() {
|
|
189
|
+
return Promise.resolve();
|
|
190
|
+
}
|
|
191
|
+
shouldRedact(attribute) {
|
|
192
|
+
return this.options.attributes.some((pattern) => {
|
|
193
|
+
if (typeof pattern === "string") {
|
|
194
|
+
return attribute === pattern;
|
|
195
|
+
} else if (pattern instanceof RegExp) {
|
|
196
|
+
return pattern.test(attribute);
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
1088
199
|
});
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
Otlp.scopeSchema = z.object({
|
|
1110
|
-
name: z.string(),
|
|
1111
|
-
version: z.string().optional(),
|
|
1112
|
-
});
|
|
1113
|
-
Otlp.scopeSpanSchema = z.object({
|
|
1114
|
-
scope: Otlp.scopeSchema,
|
|
1115
|
-
spans: z.array(Otlp.spanSchema),
|
|
1116
|
-
});
|
|
1117
|
-
Otlp.resourceSchema = z.object({
|
|
1118
|
-
attributes: z.array(Otlp.attributeSchema),
|
|
1119
|
-
});
|
|
1120
|
-
Otlp.resourceSpanSchema = z.object({
|
|
1121
|
-
resource: Otlp.resourceSchema,
|
|
1122
|
-
scopeSpans: z.array(Otlp.scopeSpanSchema),
|
|
1123
|
-
});
|
|
1124
|
-
Otlp.serviceRequestSchema = z.object({
|
|
1125
|
-
resourceSpans: z.array(Otlp.resourceSpanSchema),
|
|
1126
|
-
});
|
|
1127
|
-
})(Otlp || (Otlp = {}));
|
|
1128
|
-
|
|
1129
|
-
const MAX_SIMULATION_TURNS = 10;
|
|
1130
|
-
const globalGoalSourceSchema = z.object({
|
|
1131
|
-
type: z.literal('global'),
|
|
1132
|
-
value: z.string(),
|
|
1133
|
-
});
|
|
1134
|
-
const columnGoalSourceSchema = z.object({
|
|
1135
|
-
type: z.literal('column'),
|
|
1136
|
-
columnIndex: z.number(),
|
|
1137
|
-
});
|
|
1138
|
-
const simulatedUserGoalSourceSchema = z.discriminatedUnion('type', [
|
|
1139
|
-
globalGoalSourceSchema,
|
|
1140
|
-
columnGoalSourceSchema,
|
|
1141
|
-
]);
|
|
1142
|
-
const SimulationSettingsSchema = z.object({
|
|
1143
|
-
simulateToolResponses: z.boolean().optional(),
|
|
1144
|
-
simulatedTools: z.array(z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
|
|
1145
|
-
toolSimulationInstructions: z.string().optional(), // A prompt used to guide and generate the simulation result
|
|
1146
|
-
maxTurns: z.number().min(1).max(MAX_SIMULATION_TURNS).optional(), // The maximum number of turns to simulate. Default is 1, and any greater value will add a new user message to the simulated conversation.
|
|
1147
|
-
simulatedUserGoal: z.string().optional(), // Deprecated: Use simulatedUserGoalSource instead. Kept for backward compatibility.
|
|
1148
|
-
simulatedUserGoalSource: simulatedUserGoalSourceSchema.optional(), // The source for the simulated user goal (global text or dataset column).
|
|
1149
|
-
});
|
|
1150
|
-
|
|
1151
|
-
var OptimizationEngine;
|
|
1152
|
-
(function (OptimizationEngine) {
|
|
1153
|
-
OptimizationEngine["Identity"] = "identity";
|
|
1154
|
-
OptimizationEngine["Gepa"] = "gepa";
|
|
1155
|
-
})(OptimizationEngine || (OptimizationEngine = {}));
|
|
1156
|
-
const OptimizationBudgetSchema = z.object({
|
|
1157
|
-
time: z.number().min(0).optional(),
|
|
1158
|
-
tokens: z.number().min(0).optional(),
|
|
1159
|
-
});
|
|
1160
|
-
z.object({
|
|
1161
|
-
dataset: z
|
|
1162
|
-
.object({
|
|
1163
|
-
target: z.number().min(0).optional(), // Note: number of rows to curate when not provided by the user
|
|
1164
|
-
label: z.string().optional(), // Note: expected output column when using a labeled evaluation
|
|
1165
|
-
})
|
|
1166
|
-
.optional(),
|
|
1167
|
-
parameters: z
|
|
1168
|
-
.record(z.string(), z.object({
|
|
1169
|
-
column: z.string().optional(), // Note: corresponding column in the user-provided trainset and testset
|
|
1170
|
-
isPii: z.boolean().optional(),
|
|
1171
|
-
}))
|
|
1172
|
-
.optional(),
|
|
1173
|
-
simulation: SimulationSettingsSchema.optional(),
|
|
1174
|
-
scope: z
|
|
1175
|
-
.object({
|
|
1176
|
-
configuration: z.boolean().optional(),
|
|
1177
|
-
instructions: z.boolean().optional(),
|
|
1178
|
-
})
|
|
1179
|
-
.optional(),
|
|
1180
|
-
budget: OptimizationBudgetSchema.optional(),
|
|
1181
|
-
});
|
|
1182
|
-
|
|
1183
|
-
// TODO(tracing): deprecated
|
|
1184
|
-
const HEAD_COMMIT = 'live';
|
|
1185
|
-
var Providers;
|
|
1186
|
-
(function (Providers) {
|
|
1187
|
-
Providers["OpenAI"] = "openai";
|
|
1188
|
-
Providers["Anthropic"] = "anthropic";
|
|
1189
|
-
Providers["Groq"] = "groq";
|
|
1190
|
-
Providers["Mistral"] = "mistral";
|
|
1191
|
-
Providers["Azure"] = "azure";
|
|
1192
|
-
Providers["Google"] = "google";
|
|
1193
|
-
Providers["GoogleVertex"] = "google_vertex";
|
|
1194
|
-
Providers["AnthropicVertex"] = "anthropic_vertex";
|
|
1195
|
-
Providers["Custom"] = "custom";
|
|
1196
|
-
Providers["XAI"] = "xai";
|
|
1197
|
-
Providers["AmazonBedrock"] = "amazon_bedrock";
|
|
1198
|
-
Providers["DeepSeek"] = "deepseek";
|
|
1199
|
-
Providers["Perplexity"] = "perplexity";
|
|
1200
|
-
})(Providers || (Providers = {}));
|
|
1201
|
-
var DocumentType;
|
|
1202
|
-
(function (DocumentType) {
|
|
1203
|
-
DocumentType["Prompt"] = "prompt";
|
|
1204
|
-
DocumentType["Agent"] = "agent";
|
|
1205
|
-
})(DocumentType || (DocumentType = {}));
|
|
1206
|
-
var DocumentTriggerType;
|
|
1207
|
-
(function (DocumentTriggerType) {
|
|
1208
|
-
DocumentTriggerType["Email"] = "email";
|
|
1209
|
-
DocumentTriggerType["Scheduled"] = "scheduled";
|
|
1210
|
-
DocumentTriggerType["Integration"] = "integration";
|
|
1211
|
-
})(DocumentTriggerType || (DocumentTriggerType = {}));
|
|
1212
|
-
var DocumentTriggerStatus;
|
|
1213
|
-
(function (DocumentTriggerStatus) {
|
|
1214
|
-
DocumentTriggerStatus["Pending"] = "pending";
|
|
1215
|
-
DocumentTriggerStatus["Deployed"] = "deployed";
|
|
1216
|
-
DocumentTriggerStatus["Deprecated"] = "deprecated";
|
|
1217
|
-
})(DocumentTriggerStatus || (DocumentTriggerStatus = {}));
|
|
1218
|
-
var DocumentTriggerParameters;
|
|
1219
|
-
(function (DocumentTriggerParameters) {
|
|
1220
|
-
DocumentTriggerParameters["SenderEmail"] = "senderEmail";
|
|
1221
|
-
DocumentTriggerParameters["SenderName"] = "senderName";
|
|
1222
|
-
DocumentTriggerParameters["Subject"] = "subject";
|
|
1223
|
-
DocumentTriggerParameters["Body"] = "body";
|
|
1224
|
-
DocumentTriggerParameters["Attachments"] = "attachments";
|
|
1225
|
-
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
1226
|
-
const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
|
|
1227
|
-
|
|
1228
|
-
const translator = new Translator({
|
|
1229
|
-
filterEmptyMessages: true,
|
|
1230
|
-
providerMetadata: 'preserve',
|
|
200
|
+
}
|
|
201
|
+
redactAttributes(attributes) {
|
|
202
|
+
const redacted = {};
|
|
203
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
204
|
+
if (this.shouldRedact(key)) {
|
|
205
|
+
redacted[key] = this.options.mask?.(key, value);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return redacted;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
var DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
|
|
212
|
+
attributes: [
|
|
213
|
+
// HTTP security headers
|
|
214
|
+
/^http\.request\.header\.authorization$/i,
|
|
215
|
+
/^http\.request\.header\.cookie$/i,
|
|
216
|
+
/^http\.request\.header\.x[-_]api[-_]key$/i,
|
|
217
|
+
// Database statements may contain sensitive data
|
|
218
|
+
/^db\.statement$/i
|
|
219
|
+
]
|
|
1231
220
|
});
|
|
1232
|
-
class ManualInstrumentation {
|
|
1233
|
-
enabled;
|
|
1234
|
-
tracer;
|
|
1235
|
-
options;
|
|
1236
|
-
constructor(tracer, options) {
|
|
1237
|
-
this.enabled = false;
|
|
1238
|
-
this.tracer = tracer;
|
|
1239
|
-
this.options = options ?? {};
|
|
1240
|
-
}
|
|
1241
|
-
isEnabled() {
|
|
1242
|
-
return this.enabled;
|
|
1243
|
-
}
|
|
1244
|
-
enable() {
|
|
1245
|
-
this.enabled = true;
|
|
1246
|
-
}
|
|
1247
|
-
disable() {
|
|
1248
|
-
this.enabled = false;
|
|
1249
|
-
}
|
|
1250
|
-
resume(ctx) {
|
|
1251
|
-
const parts = ctx.traceparent.split('-');
|
|
1252
|
-
if (parts.length !== 4) {
|
|
1253
|
-
return otel.ROOT_CONTEXT;
|
|
1254
|
-
}
|
|
1255
|
-
const [, traceId, spanId, flags] = parts;
|
|
1256
|
-
if (!traceId || !spanId) {
|
|
1257
|
-
return otel.ROOT_CONTEXT;
|
|
1258
|
-
}
|
|
1259
|
-
const spanContext = {
|
|
1260
|
-
traceId,
|
|
1261
|
-
spanId,
|
|
1262
|
-
traceFlags: parseInt(flags ?? '01', 16),
|
|
1263
|
-
isRemote: true,
|
|
1264
|
-
};
|
|
1265
|
-
let context = trace.setSpanContext(otel.ROOT_CONTEXT, spanContext);
|
|
1266
|
-
if (ctx.baggage) {
|
|
1267
|
-
const baggageEntries = {};
|
|
1268
|
-
for (const pair of ctx.baggage.split(',')) {
|
|
1269
|
-
const [key, value] = pair.split('=');
|
|
1270
|
-
if (key && value) {
|
|
1271
|
-
baggageEntries[key] = { value: decodeURIComponent(value) };
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
const baggage = propagation.createBaggage(baggageEntries);
|
|
1275
|
-
context = propagation.setBaggage(context, baggage);
|
|
1276
|
-
}
|
|
1277
|
-
return context;
|
|
1278
|
-
}
|
|
1279
|
-
error(span, error, options) {
|
|
1280
|
-
options = options || {};
|
|
1281
|
-
span.recordException(error);
|
|
1282
|
-
span.setAttributes(options.attributes || {});
|
|
1283
|
-
span.setStatus({
|
|
1284
|
-
code: otel.SpanStatusCode.ERROR,
|
|
1285
|
-
message: error.message || undefined,
|
|
1286
|
-
});
|
|
1287
|
-
span.end();
|
|
1288
|
-
}
|
|
1289
|
-
span(ctx, name, type, options) {
|
|
1290
|
-
if (!this.enabled) {
|
|
1291
|
-
return {
|
|
1292
|
-
context: ctx,
|
|
1293
|
-
end: (_options) => { },
|
|
1294
|
-
fail: (_error, _options) => { },
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
const start = options || {};
|
|
1298
|
-
let operation = undefined;
|
|
1299
|
-
if (SPAN_SPECIFICATIONS[type].isGenAI) {
|
|
1300
|
-
operation = type;
|
|
1301
|
-
}
|
|
1302
|
-
const span = this.tracer.startSpan(name, {
|
|
1303
|
-
attributes: {
|
|
1304
|
-
[ATTRIBUTES.LATITUDE.type]: type,
|
|
1305
|
-
...(operation && {
|
|
1306
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
|
|
1307
|
-
}),
|
|
1308
|
-
...(start.attributes || {}),
|
|
1309
|
-
},
|
|
1310
|
-
kind: otel.SpanKind.CLIENT,
|
|
1311
|
-
}, ctx);
|
|
1312
|
-
const newCtx = trace.setSpan(ctx, span);
|
|
1313
|
-
return {
|
|
1314
|
-
context: newCtx,
|
|
1315
|
-
end: (options) => {
|
|
1316
|
-
const end = options || {};
|
|
1317
|
-
span.setAttributes(end.attributes || {});
|
|
1318
|
-
span.setStatus({ code: otel.SpanStatusCode.OK });
|
|
1319
|
-
span.end();
|
|
1320
|
-
},
|
|
1321
|
-
fail: (error, options) => {
|
|
1322
|
-
this.error(span, error, options);
|
|
1323
|
-
},
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
unknown(ctx, options) {
|
|
1327
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Unknown].name, SpanType.Unknown, options);
|
|
1328
|
-
}
|
|
1329
|
-
tool(ctx, options) {
|
|
1330
|
-
const start = options;
|
|
1331
|
-
let jsonArguments = '';
|
|
1332
|
-
try {
|
|
1333
|
-
jsonArguments = JSON.stringify(start.call.arguments);
|
|
1334
|
-
}
|
|
1335
|
-
catch (_error) {
|
|
1336
|
-
jsonArguments = '{}';
|
|
1337
|
-
}
|
|
1338
|
-
const span = this.span(ctx, start.name, SpanType.Tool, {
|
|
1339
|
-
attributes: {
|
|
1340
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
|
|
1341
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
|
|
1342
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
|
|
1343
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
|
|
1344
|
-
...(start.attributes || {}),
|
|
1345
|
-
},
|
|
1346
|
-
});
|
|
1347
|
-
return {
|
|
1348
|
-
...span,
|
|
1349
|
-
end: (options) => {
|
|
1350
|
-
const end = options;
|
|
1351
|
-
let stringResult = '';
|
|
1352
|
-
if (typeof end.result.value !== 'string') {
|
|
1353
|
-
try {
|
|
1354
|
-
stringResult = JSON.stringify(end.result.value);
|
|
1355
|
-
}
|
|
1356
|
-
catch (_error) {
|
|
1357
|
-
stringResult = '{}';
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
else {
|
|
1361
|
-
stringResult = end.result.value;
|
|
1362
|
-
}
|
|
1363
|
-
span.end({
|
|
1364
|
-
attributes: {
|
|
1365
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
|
|
1366
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
|
|
1367
|
-
...(end.attributes || {}),
|
|
1368
|
-
},
|
|
1369
|
-
});
|
|
1370
|
-
},
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
attribifyConfiguration(direction, configuration) {
|
|
1374
|
-
const prefix = direction === 'input'
|
|
1375
|
-
? ATTRIBUTES.LATITUDE.request._root
|
|
1376
|
-
: ATTRIBUTES.LATITUDE.response._root;
|
|
1377
|
-
const attributes = {};
|
|
1378
|
-
for (const key in configuration) {
|
|
1379
|
-
const field = toSnakeCase(key);
|
|
1380
|
-
let value = configuration[key];
|
|
1381
|
-
if (value === null || value === undefined)
|
|
1382
|
-
continue;
|
|
1383
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
1384
|
-
try {
|
|
1385
|
-
value = JSON.stringify(value);
|
|
1386
|
-
}
|
|
1387
|
-
catch (_error) {
|
|
1388
|
-
value = '{}';
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
attributes[`${prefix}.${field}`] = value;
|
|
1392
|
-
}
|
|
1393
|
-
return attributes;
|
|
1394
|
-
}
|
|
1395
|
-
completion(ctx, options) {
|
|
1396
|
-
const start = options;
|
|
1397
|
-
const configuration = {
|
|
1398
|
-
...(start.configuration ?? {}),
|
|
1399
|
-
model: start.model,
|
|
1400
|
-
};
|
|
1401
|
-
let jsonConfiguration = '';
|
|
1402
|
-
try {
|
|
1403
|
-
jsonConfiguration = JSON.stringify(configuration);
|
|
1404
|
-
}
|
|
1405
|
-
catch (_error) {
|
|
1406
|
-
jsonConfiguration = '{}';
|
|
1407
|
-
}
|
|
1408
|
-
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1409
|
-
const input = start.input ?? [];
|
|
1410
|
-
let jsonSystem = '';
|
|
1411
|
-
let jsonInput = '';
|
|
1412
|
-
try {
|
|
1413
|
-
const translated = translator.translate(input, {
|
|
1414
|
-
from: this.options.provider,
|
|
1415
|
-
to: Provider.GenAI,
|
|
1416
|
-
direction: 'input',
|
|
1417
|
-
});
|
|
1418
|
-
jsonSystem = JSON.stringify(translated.system ?? []);
|
|
1419
|
-
jsonInput = JSON.stringify(translated.messages ?? []);
|
|
1420
|
-
}
|
|
1421
|
-
catch (_error) {
|
|
1422
|
-
jsonSystem = '[]';
|
|
1423
|
-
jsonInput = '[]';
|
|
1424
|
-
}
|
|
1425
|
-
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1426
|
-
attributes: {
|
|
1427
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
|
|
1428
|
-
[ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
|
|
1429
|
-
...attrConfiguration,
|
|
1430
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.systemInstructions]: jsonSystem,
|
|
1431
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.input.messages]: jsonInput,
|
|
1432
|
-
...(start.attributes || {}),
|
|
1433
|
-
[ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
|
|
1434
|
-
[ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
|
|
1435
|
-
[ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
|
|
1436
|
-
},
|
|
1437
|
-
});
|
|
1438
|
-
return {
|
|
1439
|
-
...span,
|
|
1440
|
-
end: (options) => {
|
|
1441
|
-
const end = options ?? {};
|
|
1442
|
-
const output = end.output ?? [];
|
|
1443
|
-
let jsonOutput = '';
|
|
1444
|
-
try {
|
|
1445
|
-
const translated = translator.translate(output, {
|
|
1446
|
-
from: this.options.provider,
|
|
1447
|
-
to: Provider.GenAI,
|
|
1448
|
-
direction: 'output',
|
|
1449
|
-
});
|
|
1450
|
-
jsonOutput = JSON.stringify(translated.messages ?? []);
|
|
1451
|
-
}
|
|
1452
|
-
catch (_error) {
|
|
1453
|
-
jsonOutput = '[]';
|
|
1454
|
-
}
|
|
1455
|
-
const tokens = {
|
|
1456
|
-
prompt: end.tokens?.prompt ?? 0,
|
|
1457
|
-
cached: end.tokens?.cached ?? 0,
|
|
1458
|
-
reasoning: end.tokens?.reasoning ?? 0,
|
|
1459
|
-
completion: end.tokens?.completion ?? 0,
|
|
1460
|
-
};
|
|
1461
|
-
const inputTokens = tokens.prompt + tokens.cached;
|
|
1462
|
-
const outputTokens = tokens.reasoning + tokens.completion;
|
|
1463
|
-
const finishReason = end.finishReason ?? '';
|
|
1464
|
-
span.end({
|
|
1465
|
-
attributes: {
|
|
1466
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.output.messages]: jsonOutput,
|
|
1467
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
|
|
1468
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
|
|
1469
|
-
[ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
|
|
1470
|
-
[ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
|
|
1471
|
-
[ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
|
|
1472
|
-
[ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
|
|
1473
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
|
|
1474
|
-
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
|
|
1475
|
-
finishReason,
|
|
1476
|
-
],
|
|
1477
|
-
...(end.attributes || {}),
|
|
1478
|
-
},
|
|
1479
|
-
});
|
|
1480
|
-
},
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1483
|
-
embedding(ctx, options) {
|
|
1484
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
|
|
1485
|
-
}
|
|
1486
|
-
attribifyHeaders(direction, headers) {
|
|
1487
|
-
const prefix = direction === 'request'
|
|
1488
|
-
? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
|
|
1489
|
-
: ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
|
|
1490
|
-
const attributes = {};
|
|
1491
|
-
for (const key in headers) {
|
|
1492
|
-
const field = toKebabCase(key);
|
|
1493
|
-
const value = headers[key];
|
|
1494
|
-
if (value === null || value === undefined)
|
|
1495
|
-
continue;
|
|
1496
|
-
attributes[`${prefix}.${field}`] = value;
|
|
1497
|
-
}
|
|
1498
|
-
return attributes;
|
|
1499
|
-
}
|
|
1500
|
-
http(ctx, options) {
|
|
1501
|
-
const start = options;
|
|
1502
|
-
const method = start.request.method.toUpperCase();
|
|
1503
|
-
// Note: do not serialize headers as a single attribute because fields won't be redacted
|
|
1504
|
-
const attrHeaders = this.attribifyHeaders('request', start.request.headers);
|
|
1505
|
-
let finalBody = '';
|
|
1506
|
-
if (typeof start.request.body === 'string') {
|
|
1507
|
-
finalBody = start.request.body;
|
|
1508
|
-
}
|
|
1509
|
-
else {
|
|
1510
|
-
try {
|
|
1511
|
-
finalBody = JSON.stringify(start.request.body);
|
|
1512
|
-
}
|
|
1513
|
-
catch (_error) {
|
|
1514
|
-
finalBody = '{}';
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
|
|
1518
|
-
attributes: {
|
|
1519
|
-
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
|
|
1520
|
-
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
|
|
1521
|
-
...attrHeaders,
|
|
1522
|
-
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
|
|
1523
|
-
...(start.attributes || {}),
|
|
1524
|
-
},
|
|
1525
|
-
});
|
|
1526
|
-
return {
|
|
1527
|
-
...span,
|
|
1528
|
-
end: (options) => {
|
|
1529
|
-
const end = options;
|
|
1530
|
-
// Note: do not serialize headers as a single attribute because fields won't be redacted
|
|
1531
|
-
const attrHeaders = this.attribifyHeaders('response', end.response.headers);
|
|
1532
|
-
let finalBody = '';
|
|
1533
|
-
if (typeof end.response.body === 'string') {
|
|
1534
|
-
finalBody = end.response.body;
|
|
1535
|
-
}
|
|
1536
|
-
else {
|
|
1537
|
-
try {
|
|
1538
|
-
finalBody = JSON.stringify(end.response.body);
|
|
1539
|
-
}
|
|
1540
|
-
catch (_error) {
|
|
1541
|
-
finalBody = '{}';
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
span.end({
|
|
1545
|
-
attributes: {
|
|
1546
|
-
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
|
|
1547
|
-
...attrHeaders,
|
|
1548
|
-
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
|
|
1549
|
-
...(end.attributes || {}),
|
|
1550
|
-
},
|
|
1551
|
-
});
|
|
1552
|
-
},
|
|
1553
|
-
};
|
|
1554
|
-
}
|
|
1555
|
-
prompt(ctx, { documentLogUuid, versionUuid, promptUuid, projectId, experimentUuid, testDeploymentId, externalId, template, parameters, name, source, ...rest }) {
|
|
1556
|
-
let jsonParameters = '';
|
|
1557
|
-
try {
|
|
1558
|
-
jsonParameters = JSON.stringify(parameters || {});
|
|
1559
|
-
}
|
|
1560
|
-
catch (_error) {
|
|
1561
|
-
jsonParameters = '{}';
|
|
1562
|
-
}
|
|
1563
|
-
const attributes = {
|
|
1564
|
-
[ATTRIBUTES.LATITUDE.request.template]: template,
|
|
1565
|
-
[ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
|
|
1566
|
-
[ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
|
|
1567
|
-
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1568
|
-
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1569
|
-
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1570
|
-
...(experimentUuid && {
|
|
1571
|
-
[ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
|
|
1572
|
-
}),
|
|
1573
|
-
...(testDeploymentId && {
|
|
1574
|
-
[ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
|
|
1575
|
-
}),
|
|
1576
|
-
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1577
|
-
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1578
|
-
...(rest.attributes || {}),
|
|
1579
|
-
};
|
|
1580
|
-
return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
|
|
1581
|
-
attributes,
|
|
1582
|
-
});
|
|
1583
|
-
}
|
|
1584
|
-
chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
|
|
1585
|
-
const attributes = {
|
|
1586
|
-
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1587
|
-
[ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
|
|
1588
|
-
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1589
|
-
...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
|
|
1590
|
-
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1591
|
-
...(rest.attributes || {}),
|
|
1592
|
-
};
|
|
1593
|
-
return this.span(ctx, name || `chat-${documentLogUuid}`, SpanType.Chat, {
|
|
1594
|
-
attributes,
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
|
|
1598
|
-
const attributes = {
|
|
1599
|
-
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1600
|
-
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1601
|
-
[ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
|
|
1602
|
-
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1603
|
-
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1604
|
-
...(rest.attributes || {}),
|
|
1605
|
-
};
|
|
1606
|
-
return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
|
|
1607
|
-
attributes,
|
|
1608
|
-
});
|
|
1609
|
-
}
|
|
1610
|
-
// TODO(tracing): deprecate
|
|
1611
|
-
unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
|
|
1612
|
-
const attributes = {
|
|
1613
|
-
[ATTRIBUTES.LATITUDE.promptPath]: path,
|
|
1614
|
-
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1615
|
-
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1616
|
-
...(conversationUuid && {
|
|
1617
|
-
[ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
|
|
1618
|
-
}),
|
|
1619
|
-
...(rest.attributes || {}),
|
|
1620
|
-
};
|
|
1621
|
-
return this.span(ctx, name || `capture-${path}`, SpanType.UnresolvedExternal, { attributes });
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
class LatitudeInstrumentation {
|
|
1626
|
-
options;
|
|
1627
|
-
manualTelemetry;
|
|
1628
|
-
constructor(tracer, options) {
|
|
1629
|
-
this.manualTelemetry = new ManualInstrumentation(tracer);
|
|
1630
|
-
this.options = options;
|
|
1631
|
-
}
|
|
1632
|
-
isEnabled() {
|
|
1633
|
-
return this.manualTelemetry.isEnabled();
|
|
1634
|
-
}
|
|
1635
|
-
enable() {
|
|
1636
|
-
this.manualTelemetry.enable();
|
|
1637
|
-
this.options.module.instrument(this);
|
|
1638
|
-
}
|
|
1639
|
-
disable() {
|
|
1640
|
-
this.manualTelemetry.disable();
|
|
1641
|
-
this.options.module.uninstrument();
|
|
1642
|
-
}
|
|
1643
|
-
countTokens(messages) {
|
|
1644
|
-
let length = 0;
|
|
1645
|
-
for (const message of messages) {
|
|
1646
|
-
if (!('content' in message))
|
|
1647
|
-
continue;
|
|
1648
|
-
if (typeof message.content === 'string') {
|
|
1649
|
-
length += message.content.length;
|
|
1650
|
-
}
|
|
1651
|
-
else if (Array.isArray(message.content)) {
|
|
1652
|
-
for (const content of message.content) {
|
|
1653
|
-
if (content.type === 'text') {
|
|
1654
|
-
length += content.text.length;
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
// Note: this is an estimation to not bundle a tokenizer
|
|
1660
|
-
return Math.ceil(length / 4);
|
|
1661
|
-
}
|
|
1662
|
-
async wrapRenderChain(fn, ...args) {
|
|
1663
|
-
const { prompt, parameters } = args[0];
|
|
1664
|
-
const $prompt = this.manualTelemetry.prompt(context.active(), {
|
|
1665
|
-
documentLogUuid: v4(),
|
|
1666
|
-
versionUuid: prompt.versionUuid,
|
|
1667
|
-
promptUuid: prompt.uuid,
|
|
1668
|
-
template: prompt.content,
|
|
1669
|
-
parameters: parameters,
|
|
1670
|
-
});
|
|
1671
|
-
let result;
|
|
1672
|
-
try {
|
|
1673
|
-
result = await context.with($prompt.context, async () => await fn(...args));
|
|
1674
|
-
}
|
|
1675
|
-
catch (error) {
|
|
1676
|
-
$prompt.fail(error);
|
|
1677
|
-
throw error;
|
|
1678
|
-
}
|
|
1679
|
-
$prompt.end();
|
|
1680
|
-
return result;
|
|
1681
|
-
}
|
|
1682
|
-
async wrapRenderCompletion(fn, ...args) {
|
|
1683
|
-
if (!this.options.completions) {
|
|
1684
|
-
return await fn(...args);
|
|
1685
|
-
}
|
|
1686
|
-
const { provider, config, messages } = args[0];
|
|
1687
|
-
const model = config.model || 'unknown';
|
|
1688
|
-
const $completion = this.manualTelemetry.completion(context.active(), {
|
|
1689
|
-
name: `${provider} / ${model}`,
|
|
1690
|
-
provider: provider,
|
|
1691
|
-
model: model,
|
|
1692
|
-
configuration: config,
|
|
1693
|
-
input: messages,
|
|
1694
|
-
});
|
|
1695
|
-
let result;
|
|
1696
|
-
try {
|
|
1697
|
-
result = await context.with($completion.context, async () => await fn(...args));
|
|
1698
|
-
}
|
|
1699
|
-
catch (error) {
|
|
1700
|
-
$completion.fail(error);
|
|
1701
|
-
throw error;
|
|
1702
|
-
}
|
|
1703
|
-
// Note: enhance, this is just an estimation
|
|
1704
|
-
const promptTokens = this.countTokens(messages);
|
|
1705
|
-
const completionTokens = this.countTokens(result.messages);
|
|
1706
|
-
$completion.end({
|
|
1707
|
-
output: result.messages,
|
|
1708
|
-
tokens: {
|
|
1709
|
-
prompt: promptTokens,
|
|
1710
|
-
cached: 0,
|
|
1711
|
-
reasoning: 0,
|
|
1712
|
-
completion: completionTokens,
|
|
1713
|
-
},
|
|
1714
|
-
finishReason: result.toolRequests.length > 0
|
|
1715
|
-
? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
|
|
1716
|
-
: VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
|
|
1717
|
-
});
|
|
1718
|
-
return result;
|
|
1719
|
-
}
|
|
1720
|
-
async wrapRenderTool(fn, ...args) {
|
|
1721
|
-
const { toolRequest } = args[0];
|
|
1722
|
-
const $tool = this.manualTelemetry.tool(context.active(), {
|
|
1723
|
-
name: toolRequest.toolName,
|
|
1724
|
-
call: {
|
|
1725
|
-
id: toolRequest.toolCallId,
|
|
1726
|
-
arguments: toolRequest.toolArguments,
|
|
1727
|
-
},
|
|
1728
|
-
});
|
|
1729
|
-
let result;
|
|
1730
|
-
try {
|
|
1731
|
-
result = await context.with($tool.context, async () => await fn(...args));
|
|
1732
|
-
}
|
|
1733
|
-
catch (error) {
|
|
1734
|
-
$tool.fail(error);
|
|
1735
|
-
throw error;
|
|
1736
|
-
}
|
|
1737
|
-
$tool.end({
|
|
1738
|
-
result: {
|
|
1739
|
-
value: result.result,
|
|
1740
|
-
isError: result.isError,
|
|
1741
|
-
},
|
|
1742
|
-
});
|
|
1743
|
-
return result;
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
221
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
RunErrorCodes["PaymentRequiredError"] = "payment_required_error";
|
|
1781
|
-
RunErrorCodes["AbortError"] = "abort_error";
|
|
1782
|
-
// DEPRECATED, but do not delete
|
|
1783
|
-
RunErrorCodes["EvaluationRunMissingProviderLogError"] = "ev_run_missing_provider_log_error";
|
|
1784
|
-
RunErrorCodes["EvaluationRunMissingWorkspaceError"] = "ev_run_missing_workspace_error";
|
|
1785
|
-
RunErrorCodes["EvaluationRunResponseJsonFormatError"] = "ev_run_response_json_format_error";
|
|
1786
|
-
RunErrorCodes["EvaluationRunUnsupportedResultTypeError"] = "ev_run_unsupported_result_type_error";
|
|
1787
|
-
})(RunErrorCodes || (RunErrorCodes = {}));
|
|
1788
|
-
var ApiErrorCodes;
|
|
1789
|
-
(function (ApiErrorCodes) {
|
|
1790
|
-
ApiErrorCodes["HTTPException"] = "http_exception";
|
|
1791
|
-
ApiErrorCodes["InternalServerError"] = "internal_server_error";
|
|
1792
|
-
})(ApiErrorCodes || (ApiErrorCodes = {}));
|
|
1793
|
-
|
|
1794
|
-
class LatitudeError extends Error {
|
|
1795
|
-
statusCode = 500;
|
|
1796
|
-
name = LatitudeErrorCodes.UnexpectedError;
|
|
1797
|
-
headers = {};
|
|
1798
|
-
details;
|
|
1799
|
-
constructor(message, details, status, name) {
|
|
1800
|
-
super(message);
|
|
1801
|
-
this.details = details ?? {};
|
|
1802
|
-
this.statusCode = status ?? this.statusCode;
|
|
1803
|
-
this.name = name ?? this.constructor.name;
|
|
1804
|
-
}
|
|
1805
|
-
serialize() {
|
|
1806
|
-
return {
|
|
1807
|
-
name: this.name,
|
|
1808
|
-
code: this.name,
|
|
1809
|
-
status: this.statusCode,
|
|
1810
|
-
message: this.message,
|
|
1811
|
-
details: this.details,
|
|
1812
|
-
};
|
|
1813
|
-
}
|
|
1814
|
-
static deserialize(json) {
|
|
1815
|
-
return new LatitudeError(json.message, json.details, json.status, json.name);
|
|
1816
|
-
}
|
|
222
|
+
// src/sdk/span-filter.ts
|
|
223
|
+
var GEN_AI_PREFIX = "gen_ai.";
|
|
224
|
+
var LLM_PREFIX = "llm.";
|
|
225
|
+
var OPENINFERENCE_KIND = "openinference.span.kind";
|
|
226
|
+
var OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [
|
|
227
|
+
"opentelemetry.instrumentation.alephalpha",
|
|
228
|
+
"opentelemetry.instrumentation.anthropic",
|
|
229
|
+
"opentelemetry.instrumentation.bedrock",
|
|
230
|
+
"opentelemetry.instrumentation.cohere",
|
|
231
|
+
"opentelemetry.instrumentation.crewai",
|
|
232
|
+
"opentelemetry.instrumentation.google_generativeai",
|
|
233
|
+
"opentelemetry.instrumentation.groq",
|
|
234
|
+
"opentelemetry.instrumentation.haystack",
|
|
235
|
+
"opentelemetry.instrumentation.langchain",
|
|
236
|
+
"opentelemetry.instrumentation.llamaindex",
|
|
237
|
+
"opentelemetry.instrumentation.mistralai",
|
|
238
|
+
"opentelemetry.instrumentation.ollama",
|
|
239
|
+
"opentelemetry.instrumentation.openai",
|
|
240
|
+
"opentelemetry.instrumentation.replicate",
|
|
241
|
+
"opentelemetry.instrumentation.sagemaker",
|
|
242
|
+
"opentelemetry.instrumentation.together",
|
|
243
|
+
"opentelemetry.instrumentation.transformers",
|
|
244
|
+
"opentelemetry.instrumentation.vertexai",
|
|
245
|
+
"opentelemetry.instrumentation.watsonx",
|
|
246
|
+
"openinference.instrumentation"
|
|
247
|
+
];
|
|
248
|
+
var LLM_SCOPE_SUBSTRINGS = ["openinference", "traceloop", "langsmith", "litellm"];
|
|
249
|
+
function buildShouldExportSpanFromFields(fields) {
|
|
250
|
+
return buildShouldExportSpan({
|
|
251
|
+
...fields.disableSmartFilter !== void 0 ? { disableSmartFilter: fields.disableSmartFilter } : {},
|
|
252
|
+
...fields.shouldExportSpan !== void 0 ? { shouldExportSpan: fields.shouldExportSpan } : {},
|
|
253
|
+
...fields.blockedInstrumentationScopes !== void 0 ? { blockedInstrumentationScopes: fields.blockedInstrumentationScopes } : {}
|
|
254
|
+
});
|
|
1817
255
|
}
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
256
|
+
function attributeKeys(span) {
|
|
257
|
+
const attrs = span.attributes;
|
|
258
|
+
if (!attrs || typeof attrs !== "object") return [];
|
|
259
|
+
return Object.keys(attrs);
|
|
1821
260
|
}
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
const SERVICE_NAME = process.env.npm_package_name || 'unknown';
|
|
1825
|
-
const SCOPE_VERSION = process.env.npm_package_version || 'unknown';
|
|
1826
|
-
const BACKGROUND = () => otel.ROOT_CONTEXT;
|
|
1827
|
-
class SpanFactory {
|
|
1828
|
-
telemetry;
|
|
1829
|
-
constructor(telemetry) {
|
|
1830
|
-
this.telemetry = telemetry;
|
|
1831
|
-
}
|
|
1832
|
-
span(options, ctx) {
|
|
1833
|
-
return this.telemetry.unknown(ctx ?? context.active(), options);
|
|
1834
|
-
}
|
|
1835
|
-
tool(options, ctx) {
|
|
1836
|
-
return this.telemetry.tool(ctx ?? context.active(), options);
|
|
1837
|
-
}
|
|
1838
|
-
completion(options, ctx) {
|
|
1839
|
-
return this.telemetry.completion(ctx ?? context.active(), options);
|
|
1840
|
-
}
|
|
1841
|
-
embedding(options, ctx) {
|
|
1842
|
-
return this.telemetry.embedding(ctx ?? context.active(), options);
|
|
1843
|
-
}
|
|
1844
|
-
http(options, ctx) {
|
|
1845
|
-
return this.telemetry.http(ctx ?? context.active(), options);
|
|
1846
|
-
}
|
|
1847
|
-
prompt(options, ctx) {
|
|
1848
|
-
return this.telemetry.prompt(ctx ?? context.active(), options);
|
|
1849
|
-
}
|
|
1850
|
-
chat(options, ctx) {
|
|
1851
|
-
return this.telemetry.chat(ctx ?? context.active(), options);
|
|
1852
|
-
}
|
|
1853
|
-
external(options, ctx) {
|
|
1854
|
-
return this.telemetry.external(ctx ?? context.active(), options);
|
|
1855
|
-
}
|
|
261
|
+
function instrumentationScopeName(span) {
|
|
262
|
+
return span.instrumentationLibrary?.name ?? "";
|
|
1856
263
|
}
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
active() {
|
|
1866
|
-
return context.active();
|
|
1867
|
-
}
|
|
1868
|
-
with(ctx, fn, thisArg, ...args) {
|
|
1869
|
-
return context.with(ctx, fn, thisArg, ...args);
|
|
1870
|
-
}
|
|
264
|
+
function isGenAiOrLlmAttributeSpan(span) {
|
|
265
|
+
for (const key of attributeKeys(span)) {
|
|
266
|
+
if (key.startsWith(GEN_AI_PREFIX) || key.startsWith(LLM_PREFIX)) return true;
|
|
267
|
+
if (key === OPENINFERENCE_KIND || key.startsWith("openinference.")) return true;
|
|
268
|
+
if (key.startsWith("ai.")) return true;
|
|
269
|
+
if (key.startsWith("latitude.")) return true;
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
1871
272
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
this.instrumentations = instrumentations;
|
|
1876
|
-
}
|
|
1877
|
-
enable() {
|
|
1878
|
-
this.instrumentations.forEach((instrumentation) => {
|
|
1879
|
-
if (!instrumentation.isEnabled())
|
|
1880
|
-
instrumentation.enable();
|
|
1881
|
-
});
|
|
1882
|
-
}
|
|
1883
|
-
disable() {
|
|
1884
|
-
this.instrumentations.forEach((instrumentation) => {
|
|
1885
|
-
if (instrumentation.isEnabled())
|
|
1886
|
-
instrumentation.disable();
|
|
1887
|
-
});
|
|
1888
|
-
}
|
|
273
|
+
function isLatitudeInstrumentationSpan(span) {
|
|
274
|
+
const name = instrumentationScopeName(span);
|
|
275
|
+
return name === SCOPE_LATITUDE || name.startsWith(`${SCOPE_LATITUDE}.`);
|
|
1889
276
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
|
|
1902
|
-
}
|
|
277
|
+
function isKnownLlmInstrumentationScope(span) {
|
|
278
|
+
const name = instrumentationScopeName(span);
|
|
279
|
+
if (!name) return false;
|
|
280
|
+
for (const prefix of OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES) {
|
|
281
|
+
if (name === prefix || name.startsWith(`${prefix}.`)) return true;
|
|
282
|
+
}
|
|
283
|
+
const lower = name.toLowerCase();
|
|
284
|
+
for (const part of LLM_SCOPE_SUBSTRINGS) {
|
|
285
|
+
if (lower.includes(part)) return true;
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
1903
288
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
this.scope = scope;
|
|
1910
|
-
this.version = version;
|
|
1911
|
-
this.provider = provider;
|
|
1912
|
-
}
|
|
1913
|
-
getTracer(_name, _version, options) {
|
|
1914
|
-
return this.provider.getTracer(this.scope, this.version, options);
|
|
1915
|
-
}
|
|
289
|
+
function isDefaultExportSpan(span) {
|
|
290
|
+
if (isLatitudeInstrumentationSpan(span)) return true;
|
|
291
|
+
if (isGenAiOrLlmAttributeSpan(span)) return true;
|
|
292
|
+
if (isKnownLlmInstrumentationScope(span)) return true;
|
|
293
|
+
return false;
|
|
1916
294
|
}
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
async shutdown() {
|
|
1929
|
-
await this.flush();
|
|
1930
|
-
await this.nodeProvider.shutdown();
|
|
1931
|
-
await this.exporter.shutdown?.();
|
|
1932
|
-
}
|
|
295
|
+
function buildShouldExportSpan(options) {
|
|
296
|
+
if (options.disableSmartFilter) return () => true;
|
|
297
|
+
const blocked = new Set(options.blockedInstrumentationScopes ?? []);
|
|
298
|
+
const extra = options.shouldExportSpan;
|
|
299
|
+
return (span) => {
|
|
300
|
+
const scope = instrumentationScopeName(span);
|
|
301
|
+
if (blocked.has(scope)) return false;
|
|
302
|
+
if (isDefaultExportSpan(span)) return true;
|
|
303
|
+
if (extra?.(span)) return true;
|
|
304
|
+
return false;
|
|
305
|
+
};
|
|
1933
306
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
307
|
+
var ExportFilterSpanProcessor = class {
|
|
308
|
+
shouldExport;
|
|
309
|
+
inner;
|
|
310
|
+
constructor(shouldExport, inner) {
|
|
311
|
+
this.shouldExport = shouldExport;
|
|
312
|
+
this.inner = inner;
|
|
313
|
+
}
|
|
314
|
+
onStart(span, parentContext) {
|
|
315
|
+
this.inner.onStart(span, parentContext);
|
|
316
|
+
}
|
|
317
|
+
onEnd(span) {
|
|
318
|
+
if (!this.shouldExport(span)) return;
|
|
319
|
+
this.inner.onEnd(span);
|
|
320
|
+
}
|
|
321
|
+
forceFlush() {
|
|
322
|
+
return this.inner.forceFlush();
|
|
323
|
+
}
|
|
324
|
+
shutdown() {
|
|
325
|
+
return this.inner.shutdown();
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
var RedactThenExportSpanProcessor = class {
|
|
329
|
+
redact;
|
|
330
|
+
exportProcessor;
|
|
331
|
+
constructor(redact, exportProcessor) {
|
|
332
|
+
this.redact = redact;
|
|
333
|
+
this.exportProcessor = exportProcessor;
|
|
334
|
+
}
|
|
335
|
+
onStart(span, parentContext) {
|
|
336
|
+
this.redact?.onStart(span, parentContext);
|
|
337
|
+
this.exportProcessor.onStart(span, parentContext);
|
|
338
|
+
}
|
|
339
|
+
onEnd(span) {
|
|
340
|
+
this.redact?.onEnd(span);
|
|
341
|
+
this.exportProcessor.onEnd(span);
|
|
342
|
+
}
|
|
343
|
+
forceFlush() {
|
|
344
|
+
return this.exportProcessor.forceFlush();
|
|
345
|
+
}
|
|
346
|
+
shutdown() {
|
|
347
|
+
return this.exportProcessor.shutdown();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// src/sdk/processor.ts
|
|
352
|
+
var LatitudeSpanProcessor = class {
|
|
353
|
+
tail;
|
|
354
|
+
constructor(apiKey, projectSlug, options) {
|
|
355
|
+
if (!apiKey || apiKey.trim() === "") {
|
|
356
|
+
throw new Error("[Latitude] apiKey is required and cannot be empty");
|
|
357
|
+
}
|
|
358
|
+
if (!projectSlug || projectSlug.trim() === "") {
|
|
359
|
+
throw new Error("[Latitude] projectSlug is required and cannot be empty");
|
|
360
|
+
}
|
|
361
|
+
const exporter = options?.exporter ?? new OTLPTraceExporter({
|
|
362
|
+
url: `${env.EXPORTER_URL}/v1/traces`,
|
|
363
|
+
headers: {
|
|
1937
364
|
Authorization: `Bearer ${apiKey}`,
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
(
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
this.options.processors.forEach((processor) => {
|
|
1988
|
-
this.nodeProvider.addSpanProcessor(processor);
|
|
1989
|
-
});
|
|
1990
|
-
}
|
|
1991
|
-
else {
|
|
1992
|
-
this.nodeProvider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
|
|
1993
|
-
}
|
|
1994
|
-
if (this.options.disableBatch) {
|
|
1995
|
-
this.nodeProvider.addSpanProcessor(new SimpleSpanProcessor(this.options.exporter));
|
|
1996
|
-
}
|
|
1997
|
-
else {
|
|
1998
|
-
this.nodeProvider.addSpanProcessor(new BatchSpanProcessor(this.options.exporter));
|
|
1999
|
-
}
|
|
2000
|
-
this.nodeProvider.register();
|
|
2001
|
-
process.on('SIGTERM', async () => this.shutdown);
|
|
2002
|
-
process.on('SIGINT', async () => this.shutdown);
|
|
2003
|
-
this.manualInstrumentation = null;
|
|
2004
|
-
this.instrumentationsList = [];
|
|
2005
|
-
this.tracer = new TracerManager(this.nodeProvider, SCOPE_VERSION);
|
|
2006
|
-
this.initInstrumentations();
|
|
2007
|
-
this.instrumentation = new InstrumentationManager(this.instrumentationsList);
|
|
2008
|
-
this.instrumentation.enable();
|
|
2009
|
-
this.span = new SpanFactory(this.manualInstrumentation);
|
|
2010
|
-
this.context = new ContextManager(this.manualInstrumentation);
|
|
2011
|
-
}
|
|
2012
|
-
async flush() {
|
|
2013
|
-
await this.lifecycle.flush();
|
|
2014
|
-
}
|
|
2015
|
-
async shutdown() {
|
|
2016
|
-
await this.lifecycle.shutdown();
|
|
2017
|
-
}
|
|
2018
|
-
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
2019
|
-
initInstrumentations() {
|
|
2020
|
-
this.instrumentationsList = [];
|
|
2021
|
-
const tracer = this.tracer.get(Instrumentation.Manual);
|
|
2022
|
-
this.manualInstrumentation = new ManualInstrumentation(tracer, this.options.instrumentations?.manual);
|
|
2023
|
-
this.instrumentationsList.push(this.manualInstrumentation);
|
|
2024
|
-
const latitude = this.options.instrumentations?.latitude;
|
|
2025
|
-
if (latitude) {
|
|
2026
|
-
const tracer = this.tracer.get(Instrumentation.Latitude);
|
|
2027
|
-
const instrumentation = new LatitudeInstrumentation(tracer, typeof latitude === 'object' ? latitude : { module: latitude });
|
|
2028
|
-
this.instrumentationsList.push(instrumentation);
|
|
2029
|
-
}
|
|
2030
|
-
const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
|
|
2031
|
-
const providerPkg = this.options.instrumentations?.[instrumentationType];
|
|
2032
|
-
if (!providerPkg)
|
|
2033
|
-
return;
|
|
2034
|
-
const provider = this.tracer.provider(instrumentationType);
|
|
2035
|
-
const instrumentation = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
|
|
2036
|
-
instrumentation.setTracerProvider(provider);
|
|
2037
|
-
instrumentation.manuallyInstrument(providerPkg);
|
|
2038
|
-
registerInstrumentations({
|
|
2039
|
-
instrumentations: [instrumentation],
|
|
2040
|
-
tracerProvider: provider,
|
|
2041
|
-
});
|
|
2042
|
-
this.instrumentationsList.push(instrumentation);
|
|
2043
|
-
};
|
|
2044
|
-
configureInstrumentation(Instrumentation.Anthropic, AnthropicInstrumentation); // prettier-ignore
|
|
2045
|
-
configureInstrumentation(Instrumentation.AIPlatform, AIPlatformInstrumentation); // prettier-ignore
|
|
2046
|
-
configureInstrumentation(Instrumentation.Bedrock, BedrockInstrumentation); // prettier-ignore
|
|
2047
|
-
configureInstrumentation(Instrumentation.Cohere, CohereInstrumentation); // prettier-ignore
|
|
2048
|
-
configureInstrumentation(Instrumentation.Langchain, LangChainInstrumentation); // prettier-ignore
|
|
2049
|
-
configureInstrumentation(Instrumentation.LlamaIndex, LlamaIndexInstrumentation); // prettier-ignore
|
|
2050
|
-
// NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
|
|
2051
|
-
configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2052
|
-
configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2053
|
-
configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
|
|
2054
|
-
}
|
|
2055
|
-
async capture(options, fn) {
|
|
2056
|
-
if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
|
|
2057
|
-
throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
|
|
2058
|
-
}
|
|
2059
|
-
const captureBaggageEntries = {
|
|
2060
|
-
[ATTRIBUTES.LATITUDE.promptPath]: { value: options.path },
|
|
2061
|
-
[ATTRIBUTES.LATITUDE.projectId]: { value: String(options.projectId) },
|
|
2062
|
-
};
|
|
2063
|
-
if (options.versionUuid) {
|
|
2064
|
-
captureBaggageEntries[ATTRIBUTES.LATITUDE.commitUuid] = {
|
|
2065
|
-
value: options.versionUuid,
|
|
2066
|
-
};
|
|
2067
|
-
}
|
|
2068
|
-
if (options.conversationUuid) {
|
|
2069
|
-
captureBaggageEntries[ATTRIBUTES.LATITUDE.documentLogUuid] = {
|
|
2070
|
-
value: options.conversationUuid,
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
const captureContext = propagation.setBaggage(BACKGROUND(), propagation.createBaggage(captureBaggageEntries));
|
|
2074
|
-
const span = this.manualInstrumentation.unresolvedExternal(captureContext, options);
|
|
2075
|
-
let result;
|
|
2076
|
-
try {
|
|
2077
|
-
result = await context.with(span.context, async () => await fn(span.context));
|
|
2078
|
-
}
|
|
2079
|
-
catch (error) {
|
|
2080
|
-
span.fail(error);
|
|
2081
|
-
throw error;
|
|
2082
|
-
}
|
|
2083
|
-
span.end();
|
|
2084
|
-
return result;
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
365
|
+
"Content-Type": "application/json",
|
|
366
|
+
"X-Latitude-Project": projectSlug
|
|
367
|
+
},
|
|
368
|
+
timeoutMillis: 3e4
|
|
369
|
+
});
|
|
370
|
+
const redact = options?.disableRedact ? null : options?.redact ? new RedactSpanProcessor(options.redact) : DEFAULT_REDACT_SPAN_PROCESSOR();
|
|
371
|
+
const batchOrSimple = options?.disableBatch ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter);
|
|
372
|
+
const shouldExport = buildShouldExportSpanFromFields({
|
|
373
|
+
disableSmartFilter: options?.disableSmartFilter,
|
|
374
|
+
shouldExportSpan: options?.shouldExportSpan,
|
|
375
|
+
blockedInstrumentationScopes: options?.blockedInstrumentationScopes
|
|
376
|
+
});
|
|
377
|
+
const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple);
|
|
378
|
+
this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport);
|
|
379
|
+
}
|
|
380
|
+
onStart(span, parentContext) {
|
|
381
|
+
const latitudeData = getLatitudeContext(parentContext);
|
|
382
|
+
if (latitudeData) {
|
|
383
|
+
if (latitudeData.name) {
|
|
384
|
+
span.setAttribute(ATTRIBUTES.name, latitudeData.name);
|
|
385
|
+
if (span.attributes["latitude.capture.root"]) {
|
|
386
|
+
span.updateName(latitudeData.name);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (latitudeData.tags && latitudeData.tags.length > 0) {
|
|
390
|
+
span.setAttribute(ATTRIBUTES.tags, JSON.stringify(latitudeData.tags));
|
|
391
|
+
}
|
|
392
|
+
if (latitudeData.metadata && Object.keys(latitudeData.metadata).length > 0) {
|
|
393
|
+
span.setAttribute(ATTRIBUTES.metadata, JSON.stringify(latitudeData.metadata));
|
|
394
|
+
}
|
|
395
|
+
if (latitudeData.sessionId) {
|
|
396
|
+
span.setAttribute(ATTRIBUTES.sessionId, latitudeData.sessionId);
|
|
397
|
+
}
|
|
398
|
+
if (latitudeData.userId) {
|
|
399
|
+
span.setAttribute(ATTRIBUTES.userId, latitudeData.userId);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
this.tail.onStart(span, parentContext);
|
|
403
|
+
}
|
|
404
|
+
onEnd(span) {
|
|
405
|
+
this.tail.onEnd(span);
|
|
406
|
+
}
|
|
407
|
+
async forceFlush() {
|
|
408
|
+
await this.tail.forceFlush();
|
|
409
|
+
}
|
|
410
|
+
async shutdown() {
|
|
411
|
+
await this.tail.shutdown();
|
|
412
|
+
}
|
|
413
|
+
};
|
|
2087
414
|
|
|
2088
|
-
|
|
2089
|
-
|
|
415
|
+
// src/sdk/init.ts
|
|
416
|
+
var SERVICE_NAME = process.env.npm_package_name || "unknown";
|
|
417
|
+
var shutdownHandlersRegistered = false;
|
|
418
|
+
function initLatitude(options) {
|
|
419
|
+
const { apiKey, projectSlug, instrumentations = [], ...processorOptions } = options;
|
|
420
|
+
if (!apiKey || apiKey.trim() === "") {
|
|
421
|
+
throw new Error("[Latitude] apiKey is required and cannot be empty");
|
|
422
|
+
}
|
|
423
|
+
if (!projectSlug || projectSlug.trim() === "") {
|
|
424
|
+
throw new Error("[Latitude] projectSlug is required and cannot be empty");
|
|
425
|
+
}
|
|
426
|
+
const contextManager = new AsyncLocalStorageContextManager();
|
|
427
|
+
contextManager.enable();
|
|
428
|
+
const propagator = new CompositePropagator({
|
|
429
|
+
propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()]
|
|
430
|
+
});
|
|
431
|
+
context2.setGlobalContextManager(contextManager);
|
|
432
|
+
propagation.setGlobalPropagator(propagator);
|
|
433
|
+
const provider = new NodeTracerProvider({
|
|
434
|
+
resource: new Resource({
|
|
435
|
+
[ATTR_SERVICE_NAME]: SERVICE_NAME
|
|
436
|
+
}),
|
|
437
|
+
spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)]
|
|
438
|
+
});
|
|
439
|
+
provider.register();
|
|
440
|
+
const ready = registerLatitudeInstrumentations({
|
|
441
|
+
instrumentations,
|
|
442
|
+
tracerProvider: provider
|
|
443
|
+
}).catch((err) => {
|
|
444
|
+
console.warn("[Latitude] Failed to register instrumentations:", err);
|
|
445
|
+
});
|
|
446
|
+
const shutdown = async () => {
|
|
447
|
+
await provider.shutdown();
|
|
448
|
+
};
|
|
449
|
+
const flush = async () => {
|
|
450
|
+
await provider.forceFlush();
|
|
451
|
+
};
|
|
452
|
+
const handleShutdown = async () => {
|
|
453
|
+
try {
|
|
454
|
+
await shutdown();
|
|
455
|
+
} catch (err) {
|
|
456
|
+
console.error("Error during Latitude Telemetry shutdown:", err);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
if (!shutdownHandlersRegistered) {
|
|
460
|
+
process.once("SIGTERM", handleShutdown);
|
|
461
|
+
process.once("SIGINT", handleShutdown);
|
|
462
|
+
shutdownHandlersRegistered = true;
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
provider,
|
|
466
|
+
flush,
|
|
467
|
+
shutdown,
|
|
468
|
+
ready
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
export {
|
|
472
|
+
ExportFilterSpanProcessor,
|
|
473
|
+
LatitudeSpanProcessor,
|
|
474
|
+
RedactSpanProcessor,
|
|
475
|
+
RedactThenExportSpanProcessor,
|
|
476
|
+
buildShouldExportSpan,
|
|
477
|
+
buildShouldExportSpanFromFields,
|
|
478
|
+
capture,
|
|
479
|
+
initLatitude,
|
|
480
|
+
isDefaultExportSpan,
|
|
481
|
+
isGenAiOrLlmAttributeSpan,
|
|
482
|
+
isLatitudeInstrumentationSpan,
|
|
483
|
+
registerLatitudeInstrumentations
|
|
484
|
+
};
|
|
485
|
+
//# sourceMappingURL=index.js.map
|