@latitude-data/telemetry 2.0.4 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,2089 +1,396 @@
1
- import { z } from 'zod';
2
- import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
3
- import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
4
- import * as otel from '@opentelemetry/api';
5
- import { trace, propagation, context } from '@opentelemetry/api';
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
+ // src/sdk/redact.ts
2
+ var RedactSpanProcessor = class {
3
+ options;
4
+ constructor(options) {
5
+ this.options = options;
6
+ if (!options.mask) {
7
+ this.options.mask = (_attribute, _value) => "******";
8
+ }
9
+ }
10
+ onStart(_span, _context) {
11
+ }
12
+ onEnd(span) {
13
+ Object.assign(span.attributes, this.redactAttributes(span.attributes));
14
+ for (const event of span.events) {
15
+ if (!event.attributes) continue;
16
+ Object.assign(event.attributes, this.redactAttributes(event.attributes));
17
+ }
18
+ for (const link of span.links) {
19
+ if (!link.attributes) continue;
20
+ Object.assign(link.attributes, this.redactAttributes(link.attributes));
21
+ }
22
+ }
23
+ forceFlush() {
24
+ return Promise.resolve();
25
+ }
26
+ shutdown() {
27
+ return Promise.resolve();
28
+ }
29
+ shouldRedact(attribute) {
30
+ return this.options.attributes.some((pattern) => {
31
+ if (typeof pattern === "string") {
32
+ return attribute === pattern;
33
+ } else if (pattern instanceof RegExp) {
34
+ return pattern.test(attribute);
35
+ }
36
+ return false;
37
+ });
38
+ }
39
+ redactAttributes(attributes) {
40
+ const redacted = {};
41
+ for (const [key, value] of Object.entries(attributes)) {
42
+ if (this.shouldRedact(key)) {
43
+ redacted[key] = this.options.mask?.(key, value);
44
+ }
45
+ }
46
+ return redacted;
47
+ }
48
+ };
49
+ var DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
50
+ attributes: [
51
+ /^http\.request\.header\.authorization$/i,
52
+ /^http\.request\.header\.cookie$/i,
53
+ /^http\.request\.header\.x[-_]api[-_]key$/i,
54
+ /^db\.statement$/i
55
+ ]
101
56
  });
102
57
 
103
- const DEFAULT_GATEWAY_BASE_URL = {
104
- production: 'https://gateway.latitude.so',
105
- development: 'http://localhost:8787',
106
- test: 'http://localhost:8787',
107
- }["production"];
108
- function GET_GATEWAY_BASE_URL() {
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}`;
119
- }
120
- const env = { GATEWAY_BASE_URL: GET_GATEWAY_BASE_URL() };
121
-
122
- function toSnakeCase(str) {
123
- return str
124
- .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
125
- .replace(/[^A-Za-z0-9]+/g, '_')
126
- .replace(/_+/g, '_')
127
- .replace(/^_+|_+$/g, '')
128
- .toLowerCase();
129
- }
130
- function toKebabCase(input) {
131
- return input
132
- .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
133
- .replace(/[^A-Za-z0-9]+/g, '-')
134
- .replace(/-+/g, '-')
135
- .replace(/^-+|-+$/g, '')
136
- .toLowerCase();
137
- }
58
+ // src/sdk/sdk.ts
59
+ import * as otel2 from "@opentelemetry/api";
60
+ import { context, propagation as propagation2 } from "@opentelemetry/api";
61
+ import { ALLOW_ALL_BAGGAGE_KEYS, BaggageSpanProcessor } from "@opentelemetry/baggage-span-processor";
62
+ import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
63
+ import { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from "@opentelemetry/core";
64
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
65
+ import { registerInstrumentations } from "@opentelemetry/instrumentation";
66
+ import { Resource } from "@opentelemetry/resources";
67
+ import {
68
+ BatchSpanProcessor,
69
+ NodeTracerProvider,
70
+ SimpleSpanProcessor
71
+ } from "@opentelemetry/sdk-trace-node";
72
+ import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
73
+ import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic";
74
+ import { BedrockInstrumentation } from "@traceloop/instrumentation-bedrock";
75
+ import { CohereInstrumentation } from "@traceloop/instrumentation-cohere";
76
+ import { LangChainInstrumentation } from "@traceloop/instrumentation-langchain";
77
+ import { LlamaIndexInstrumentation } from "@traceloop/instrumentation-llamaindex";
78
+ import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
79
+ import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
80
+ import { AIPlatformInstrumentation, VertexAIInstrumentation } from "@traceloop/instrumentation-vertexai";
138
81
 
139
- var StreamEventTypes;
140
- (function (StreamEventTypes) {
141
- StreamEventTypes["Latitude"] = "latitude-event";
142
- StreamEventTypes["Provider"] = "provider-event";
143
- })(StreamEventTypes || (StreamEventTypes = {}));
144
- z.object({
145
- id: z.string(),
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
- });
82
+ // src/constants/attributes.ts
83
+ var ATTRIBUTES = {
84
+ tags: "latitude.tags",
85
+ metadata: "latitude.metadata",
86
+ sessionId: "session.id",
87
+ userId: "user.id"
88
+ };
160
89
 
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
- ];
90
+ // src/constants/scope.ts
91
+ var SCOPE_LATITUDE = "so.latitude.instrumentation";
187
92
 
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
- });
93
+ // src/env/env.ts
94
+ var DEFAULT_EXPORTER_URL = {
95
+ production: "https://ingest.latitude.so",
96
+ development: "http://localhost:3002",
97
+ test: "http://localhost:3002"
98
+ }[process.env.NODE_ENV ?? "development"] ?? "http://localhost:3002";
99
+ function getExporterUrl() {
100
+ if (process.env.LATITUDE_TELEMETRY_URL) {
101
+ return process.env.LATITUDE_TELEMETRY_URL;
102
+ }
103
+ return DEFAULT_EXPORTER_URL;
104
+ }
105
+ var env = { EXPORTER_URL: getExporterUrl() };
234
106
 
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 = {
107
+ // src/instrumentations/manual.ts
108
+ import * as otel from "@opentelemetry/api";
109
+ import { propagation, trace } from "@opentelemetry/api";
110
+ var ManualInstrumentation = class {
111
+ enabled;
112
+ _tracer;
113
+ constructor(tracer) {
114
+ this.enabled = false;
115
+ this._tracer = tracer;
116
+ }
117
+ get tracer() {
118
+ return this._tracer;
119
+ }
120
+ isEnabled() {
121
+ return this.enabled;
122
+ }
123
+ enable() {
124
+ this.enabled = true;
125
+ }
126
+ disable() {
127
+ this.enabled = false;
128
+ }
129
+ resume(ctx) {
130
+ const parts = ctx.traceparent.split("-");
131
+ if (parts.length !== 4) {
132
+ return otel.ROOT_CONTEXT;
133
+ }
134
+ const [, traceId, spanId, flags] = parts;
135
+ if (!traceId || !spanId) {
136
+ return otel.ROOT_CONTEXT;
137
+ }
138
+ const spanContext = {
139
+ traceId,
140
+ spanId,
141
+ traceFlags: parseInt(flags ?? "01", 16),
142
+ isRemote: true
289
143
  };
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
- },
144
+ let context2 = trace.setSpanContext(otel.ROOT_CONTEXT, spanContext);
145
+ if (ctx.baggage) {
146
+ const baggageEntries = {};
147
+ for (const pair of ctx.baggage.split(",")) {
148
+ const [key, value] = pair.split("=", 2);
149
+ if (key && value) {
150
+ baggageEntries[decodeURIComponent(key)] = { value: decodeURIComponent(value) };
151
+ }
152
+ }
153
+ const baggage = propagation.createBaggage(baggageEntries);
154
+ context2 = propagation.setBaggage(context2, baggage);
155
+ }
156
+ return context2;
157
+ }
304
158
  };
305
159
 
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
- },
160
+ // src/sdk/sdk.ts
161
+ var TRACES_URL = `${env.EXPORTER_URL}/v1/traces`;
162
+ var SERVICE_NAME = process.env.npm_package_name || "unknown";
163
+ var SCOPE_VERSION = process.env.npm_package_version || "unknown";
164
+ var ContextManager = class {
165
+ telemetry;
166
+ constructor(telemetry) {
167
+ this.telemetry = telemetry;
168
+ }
169
+ resume(ctx) {
170
+ return this.telemetry.resume(ctx);
171
+ }
172
+ active() {
173
+ return context.active();
174
+ }
175
+ with(ctx, fn, thisArg, ...args) {
176
+ return context.with(ctx, fn, thisArg, ...args);
177
+ }
374
178
  };
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
- },
179
+ var InstrumentationManager = class {
180
+ instrumentations;
181
+ constructor(instrumentations) {
182
+ this.instrumentations = instrumentations;
183
+ }
184
+ enable() {
185
+ for (const instrumentation of this.instrumentations) {
186
+ if (!instrumentation.isEnabled()) instrumentation.enable();
187
+ }
188
+ }
189
+ disable() {
190
+ for (const instrumentation of this.instrumentations) {
191
+ if (instrumentation.isEnabled()) instrumentation.disable();
192
+ }
193
+ }
467
194
  };
468
-
469
- const ruleEvaluationConfiguration = baseEvaluationConfiguration.extend({});
470
- const ruleEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
471
- reason: z.string().optional(),
472
- });
473
- const ruleEvaluationResultError = baseEvaluationResultError.extend({});
474
- // EXACT MATCH
475
- const ruleEvaluationExactMatchConfiguration = ruleEvaluationConfiguration.extend({
476
- caseInsensitive: z.boolean(),
477
- });
478
- ruleEvaluationResultMetadata.extend({
479
- configuration: ruleEvaluationExactMatchConfiguration,
480
- });
481
- ruleEvaluationResultError.extend({});
482
- const RuleEvaluationExactMatchSpecification = {
483
- };
484
- // REGULAR EXPRESSION
485
- const ruleEvaluationRegularExpressionConfiguration = ruleEvaluationConfiguration.extend({
486
- pattern: z.string(),
487
- });
488
- ruleEvaluationResultMetadata.extend({
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
- },
195
+ var TracerManager = class {
196
+ nodeProvider;
197
+ scopeVersion;
198
+ constructor(nodeProvider, scopeVersion) {
199
+ this.nodeProvider = nodeProvider;
200
+ this.scopeVersion = scopeVersion;
201
+ }
202
+ get(scope) {
203
+ return this.provider(scope).getTracer("");
204
+ }
205
+ provider(scope) {
206
+ return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
207
+ }
575
208
  };
576
-
577
- var EvaluationType;
578
- (function (EvaluationType) {
579
- EvaluationType["Rule"] = "rule";
580
- EvaluationType["Llm"] = "llm";
581
- EvaluationType["Human"] = "human";
582
- EvaluationType["Composite"] = "composite";
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
- });
821
-
822
- var SpanKind;
823
- (function (SpanKind) {
824
- SpanKind["Internal"] = "internal";
825
- SpanKind["Server"] = "server";
826
- SpanKind["Client"] = "client";
827
- SpanKind["Producer"] = "producer";
828
- SpanKind["Consumer"] = "consumer";
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
- },
209
+ var ScopedTracerProvider = class {
210
+ scope;
211
+ version;
212
+ provider;
213
+ constructor(scope, version, provider) {
214
+ this.scope = scope;
215
+ this.version = version;
216
+ this.provider = provider;
217
+ }
218
+ getTracer(_name, _version, options) {
219
+ return this.provider.getTracer(this.scope, this.version, options);
220
+ }
906
221
  };
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
-
919
- // Note: Traces are unmaterialized but this context is used to propagate the trace
920
- // See www.w3.org/TR/trace-context and w3c.github.io/baggage
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
- });
926
-
927
- const ATTRIBUTES = {
928
- // Custom attributes added and used by Latitude spans (Prompt / External / Chat)
929
- LATITUDE: {
930
- type: 'latitude.type',
931
- documentUuid: 'latitude.document_uuid',
932
- promptPath: 'latitude.prompt_path',
933
- commitUuid: 'latitude.commit_uuid',
934
- documentLogUuid: 'latitude.document_log_uuid',
935
- projectId: 'latitude.project_id',
936
- experimentUuid: 'latitude.experiment_uuid',
937
- source: 'latitude.source',
938
- externalId: 'latitude.external_id',
939
- testDeploymentId: 'latitude.test_deployment_id',
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
- }};
1020
-
1021
- /* Note: Instrumentation scopes from all language SDKs */
1022
- const SCOPE_LATITUDE = 'so.latitude.instrumentation';
1023
- var InstrumentationScope;
1024
- (function (InstrumentationScope) {
1025
- InstrumentationScope["Manual"] = "manual";
1026
- InstrumentationScope["Latitude"] = "latitude";
1027
- InstrumentationScope["OpenAI"] = "openai";
1028
- InstrumentationScope["Anthropic"] = "anthropic";
1029
- InstrumentationScope["AzureOpenAI"] = "azure";
1030
- InstrumentationScope["VercelAI"] = "vercelai";
1031
- InstrumentationScope["VertexAI"] = "vertexai";
1032
- InstrumentationScope["AIPlatform"] = "aiplatform";
1033
- InstrumentationScope["MistralAI"] = "mistralai";
1034
- InstrumentationScope["Bedrock"] = "bedrock";
1035
- InstrumentationScope["Sagemaker"] = "sagemaker";
1036
- InstrumentationScope["TogetherAI"] = "togetherai";
1037
- InstrumentationScope["Replicate"] = "replicate";
1038
- InstrumentationScope["Groq"] = "groq";
1039
- InstrumentationScope["Cohere"] = "cohere";
1040
- InstrumentationScope["LiteLLM"] = "litellm";
1041
- InstrumentationScope["Langchain"] = "langchain";
1042
- InstrumentationScope["LlamaIndex"] = "llamaindex";
1043
- InstrumentationScope["DSPy"] = "dspy";
1044
- InstrumentationScope["Haystack"] = "haystack";
1045
- InstrumentationScope["Ollama"] = "ollama";
1046
- InstrumentationScope["Transformers"] = "transformers";
1047
- InstrumentationScope["AlephAlpha"] = "alephalpha";
1048
- })(InstrumentationScope || (InstrumentationScope = {}));
1049
- /* Note: Schemas for span ingestion following OpenTelemetry service request specification */
1050
- var Otlp;
1051
- (function (Otlp) {
1052
- Otlp.attributeValueSchema = z.object({
1053
- stringValue: z.string().optional(),
1054
- intValue: z.number().optional(),
1055
- boolValue: z.boolean().optional(),
1056
- arrayValue: z
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(),
1088
- });
1089
- (function (SpanKind) {
1090
- SpanKind[SpanKind["Internal"] = 0] = "Internal";
1091
- SpanKind[SpanKind["Server"] = 1] = "Server";
1092
- SpanKind[SpanKind["Client"] = 2] = "Client";
1093
- SpanKind[SpanKind["Producer"] = 3] = "Producer";
1094
- SpanKind[SpanKind["Consumer"] = 4] = "Consumer";
1095
- })(Otlp.SpanKind || (Otlp.SpanKind = {}));
1096
- Otlp.spanSchema = z.object({
1097
- traceId: z.string(),
1098
- spanId: z.string(),
1099
- parentSpanId: z.string().optional(),
1100
- name: z.string(),
1101
- kind: z.number(),
1102
- startTimeUnixNano: z.string(),
1103
- endTimeUnixNano: z.string(),
1104
- status: Otlp.statusSchema.optional(),
1105
- events: z.array(Otlp.eventSchema).optional(),
1106
- links: z.array(Otlp.linkSchema).optional(),
1107
- attributes: z.array(Otlp.attributeSchema).optional(),
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),
222
+ var LifecycleManager = class {
223
+ nodeProvider;
224
+ exporter;
225
+ constructor(nodeProvider, exporter) {
226
+ this.nodeProvider = nodeProvider;
227
+ this.exporter = exporter;
228
+ }
229
+ async flush() {
230
+ await this.nodeProvider.forceFlush();
231
+ await this.exporter.forceFlush?.();
232
+ }
233
+ async shutdown() {
234
+ await this.flush();
235
+ await this.nodeProvider.shutdown();
236
+ await this.exporter.shutdown?.();
237
+ }
238
+ };
239
+ var DEFAULT_SPAN_EXPORTER = (apiKey, projectSlug) => new OTLPTraceExporter({
240
+ url: TRACES_URL,
241
+ headers: {
242
+ Authorization: `Bearer ${apiKey}`,
243
+ "Content-Type": "application/json",
244
+ "X-Latitude-Project": projectSlug
245
+ },
246
+ timeoutMillis: 30 * 1e3
247
+ });
248
+ var Instrumentation = /* @__PURE__ */ ((Instrumentation2) => {
249
+ Instrumentation2["Anthropic"] = "anthropic";
250
+ Instrumentation2["AIPlatform"] = "aiplatform";
251
+ Instrumentation2["Bedrock"] = "bedrock";
252
+ Instrumentation2["Cohere"] = "cohere";
253
+ Instrumentation2["Langchain"] = "langchain";
254
+ Instrumentation2["LlamaIndex"] = "llamaindex";
255
+ Instrumentation2["Manual"] = "manual";
256
+ Instrumentation2["OpenAI"] = "openai";
257
+ Instrumentation2["TogetherAI"] = "togetherai";
258
+ Instrumentation2["VertexAI"] = "vertexai";
259
+ return Instrumentation2;
260
+ })(Instrumentation || {});
261
+ var LatitudeTelemetry = class {
262
+ options;
263
+ nodeProvider;
264
+ instrumentationsList;
265
+ /** OpenTelemetry tracer for creating custom spans. */
266
+ tracer;
267
+ context;
268
+ instrumentation;
269
+ lifecycle;
270
+ constructor(apiKey, projectSlug, options) {
271
+ this.options = options || {};
272
+ if (!this.options.exporter) {
273
+ this.options.exporter = DEFAULT_SPAN_EXPORTER(apiKey, projectSlug);
274
+ }
275
+ context.setGlobalContextManager(new AsyncLocalStorageContextManager().enable());
276
+ propagation2.setGlobalPropagator(
277
+ new CompositePropagator({
278
+ propagators: [...this.options.propagators || [], new W3CTraceContextPropagator(), new W3CBaggagePropagator()]
279
+ })
280
+ );
281
+ const spanProcessors = [
282
+ // Must run before the exporter span processors
283
+ new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS),
284
+ ...this.options.processors ?? [DEFAULT_REDACT_SPAN_PROCESSOR()],
285
+ this.options.disableBatch ? new SimpleSpanProcessor(this.options.exporter) : new BatchSpanProcessor(this.options.exporter)
286
+ ];
287
+ this.nodeProvider = new NodeTracerProvider({
288
+ resource: new Resource({ [ATTR_SERVICE_NAME]: this.options.serviceName || SERVICE_NAME }),
289
+ spanProcessors
1126
290
  });
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',
1231
- });
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
-
1747
- var LatitudeErrorCodes;
1748
- (function (LatitudeErrorCodes) {
1749
- LatitudeErrorCodes["UnexpectedError"] = "UnexpectedError";
1750
- LatitudeErrorCodes["OverloadedError"] = "OverloadedError";
1751
- LatitudeErrorCodes["RateLimitError"] = "RateLimitError";
1752
- LatitudeErrorCodes["UnauthorizedError"] = "UnauthorizedError";
1753
- LatitudeErrorCodes["ForbiddenError"] = "ForbiddenError";
1754
- LatitudeErrorCodes["BadRequestError"] = "BadRequestError";
1755
- LatitudeErrorCodes["NotFoundError"] = "NotFoundError";
1756
- LatitudeErrorCodes["ConflictError"] = "ConflictError";
1757
- LatitudeErrorCodes["UnprocessableEntityError"] = "UnprocessableEntityError";
1758
- LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
1759
- LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
1760
- LatitudeErrorCodes["AbortedError"] = "AbortedError";
1761
- LatitudeErrorCodes["BillingError"] = "BillingError";
1762
- })(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
1763
- // NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
1764
- var RunErrorCodes;
1765
- (function (RunErrorCodes) {
1766
- RunErrorCodes["AIProviderConfigError"] = "ai_provider_config_error";
1767
- RunErrorCodes["AIRunError"] = "ai_run_error";
1768
- RunErrorCodes["ChainCompileError"] = "chain_compile_error";
1769
- RunErrorCodes["DefaultProviderExceededQuota"] = "default_provider_exceeded_quota_error";
1770
- RunErrorCodes["DefaultProviderInvalidModel"] = "default_provider_invalid_model_error";
1771
- RunErrorCodes["DocumentConfigError"] = "document_config_error";
1772
- RunErrorCodes["ErrorGeneratingMockToolResult"] = "error_generating_mock_tool_result";
1773
- RunErrorCodes["FailedToWakeUpIntegrationError"] = "failed_to_wake_up_integration_error";
1774
- RunErrorCodes["InvalidResponseFormatError"] = "invalid_response_format_error";
1775
- RunErrorCodes["MaxStepCountExceededError"] = "max_step_count_exceeded_error";
1776
- RunErrorCodes["MissingProvider"] = "missing_provider_error";
1777
- RunErrorCodes["RateLimit"] = "rate_limit_error";
1778
- RunErrorCodes["Unknown"] = "unknown_error";
1779
- RunErrorCodes["UnsupportedProviderResponseTypeError"] = "unsupported_provider_response_type_error";
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
- }
1817
- }
1818
- class BadRequestError extends LatitudeError {
1819
- statusCode = 400;
1820
- name = LatitudeErrorCodes.BadRequestError;
1821
- }
1822
-
1823
- const TRACES_URL = `${env.GATEWAY_BASE_URL}/api/v3/traces`;
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
- }
1856
- }
1857
- class ContextManager {
1858
- telemetry;
1859
- constructor(telemetry) {
1860
- this.telemetry = telemetry;
1861
- }
1862
- resume(ctx) {
1863
- return this.telemetry.resume(ctx);
1864
- }
1865
- active() {
1866
- return context.active();
1867
- }
1868
- with(ctx, fn, thisArg, ...args) {
1869
- return context.with(ctx, fn, thisArg, ...args);
1870
- }
1871
- }
1872
- class InstrumentationManager {
1873
- instrumentations;
1874
- constructor(instrumentations) {
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
- }
1889
- }
1890
- class TracerManager {
1891
- nodeProvider;
1892
- scopeVersion;
1893
- constructor(nodeProvider, scopeVersion) {
1894
- this.nodeProvider = nodeProvider;
1895
- this.scopeVersion = scopeVersion;
1896
- }
1897
- get(scope) {
1898
- return this.provider(scope).getTracer('');
1899
- }
1900
- provider(scope) {
1901
- return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
1902
- }
1903
- }
1904
- class ScopedTracerProvider {
1905
- scope;
1906
- version;
1907
- provider;
1908
- constructor(scope, version, provider) {
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
- }
1916
- }
1917
- class LifecycleManager {
1918
- nodeProvider;
1919
- exporter;
1920
- constructor(nodeProvider, exporter) {
1921
- this.nodeProvider = nodeProvider;
1922
- this.exporter = exporter;
1923
- }
1924
- async flush() {
1925
- await this.nodeProvider.forceFlush();
1926
- await this.exporter.forceFlush?.();
1927
- }
1928
- async shutdown() {
1929
- await this.flush();
1930
- await this.nodeProvider.shutdown();
1931
- await this.exporter.shutdown?.();
1932
- }
1933
- }
1934
- const DEFAULT_SPAN_EXPORTER = (apiKey) => new OTLPTraceExporter({
1935
- url: TRACES_URL,
1936
- headers: {
1937
- Authorization: `Bearer ${apiKey}`,
1938
- 'Content-Type': 'application/json',
1939
- },
1940
- timeoutMillis: 30 * 1000,
1941
- });
1942
- // Note: Only exporting typescript instrumentations
1943
- var Instrumentation;
1944
- (function (Instrumentation) {
1945
- Instrumentation["Anthropic"] = "anthropic";
1946
- Instrumentation["AIPlatform"] = "aiplatform";
1947
- Instrumentation["Bedrock"] = "bedrock";
1948
- Instrumentation["Cohere"] = "cohere";
1949
- Instrumentation["Langchain"] = "langchain";
1950
- Instrumentation["Latitude"] = "latitude";
1951
- Instrumentation["LlamaIndex"] = "llamaindex";
1952
- Instrumentation["Manual"] = "manual";
1953
- Instrumentation["OpenAI"] = "openai";
1954
- Instrumentation["TogetherAI"] = "togetherai";
1955
- Instrumentation["VertexAI"] = "vertexai";
1956
- })(Instrumentation || (Instrumentation = {}));
1957
- class LatitudeTelemetry {
1958
- options;
1959
- nodeProvider;
1960
- manualInstrumentation;
1961
- instrumentationsList;
1962
- span;
1963
- context;
1964
- instrumentation;
1965
- tracer;
1966
- lifecycle;
1967
- constructor(apiKey, options) {
1968
- this.options = options || {};
1969
- if (!this.options.exporter) {
1970
- this.options.exporter = DEFAULT_SPAN_EXPORTER(apiKey);
1971
- }
1972
- context.setGlobalContextManager(new AsyncLocalStorageContextManager().enable());
1973
- propagation.setGlobalPropagator(new CompositePropagator({
1974
- propagators: [
1975
- ...(this.options.propagators || []),
1976
- new W3CTraceContextPropagator(),
1977
- new W3CBaggagePropagator(),
1978
- ],
1979
- }));
1980
- this.nodeProvider = new NodeTracerProvider({
1981
- resource: new Resource({ [ATTR_SERVICE_NAME]: SERVICE_NAME }),
1982
- });
1983
- this.lifecycle = new LifecycleManager(this.nodeProvider, this.options.exporter);
1984
- // Note: important, must run before the exporter span processors
1985
- this.nodeProvider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
1986
- if (this.options.processors) {
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;
291
+ this.lifecycle = new LifecycleManager(this.nodeProvider, this.options.exporter);
292
+ this.nodeProvider.register();
293
+ process.on("SIGTERM", () => this.shutdown());
294
+ process.on("SIGINT", () => this.shutdown());
295
+ this.instrumentationsList = [];
296
+ const tracerManager = new TracerManager(this.nodeProvider, SCOPE_VERSION);
297
+ const manualTracer = tracerManager.get("manual" /* Manual */);
298
+ const manualInstrumentation = new ManualInstrumentation(manualTracer);
299
+ this.instrumentationsList.push(manualInstrumentation);
300
+ this.tracer = manualTracer;
301
+ this.initProviderInstrumentations(tracerManager);
302
+ this.instrumentation = new InstrumentationManager(this.instrumentationsList);
303
+ this.instrumentation.enable();
304
+ this.context = new ContextManager(manualInstrumentation);
305
+ }
306
+ async flush() {
307
+ await this.lifecycle.flush();
308
+ }
309
+ async shutdown() {
310
+ await this.lifecycle.shutdown();
311
+ }
312
+ initProviderInstrumentations(tracerManager) {
313
+ const configure = (type, Ctor, opts) => {
314
+ const providerPkg = this.options.instrumentations?.[type];
315
+ if (!providerPkg) return;
316
+ const provider = tracerManager.provider(type);
317
+ const inst = new Ctor(opts);
318
+ inst.setTracerProvider(provider);
319
+ inst.manuallyInstrument(providerPkg);
320
+ registerInstrumentations({
321
+ instrumentations: [inst],
322
+ tracerProvider: provider
323
+ });
324
+ this.instrumentationsList.push(inst);
325
+ };
326
+ configure("anthropic" /* Anthropic */, AnthropicInstrumentation);
327
+ configure("aiplatform" /* AIPlatform */, AIPlatformInstrumentation);
328
+ configure("bedrock" /* Bedrock */, BedrockInstrumentation);
329
+ configure("cohere" /* Cohere */, CohereInstrumentation);
330
+ configure("langchain" /* Langchain */, LangChainInstrumentation);
331
+ configure("llamaindex" /* LlamaIndex */, LlamaIndexInstrumentation);
332
+ configure("openai" /* OpenAI */, OpenAIInstrumentation, { enrichTokens: true });
333
+ configure("togetherai" /* TogetherAI */, TogetherInstrumentation, { enrichTokens: false });
334
+ configure("vertexai" /* VertexAI */, VertexAIInstrumentation);
335
+ }
336
+ /**
337
+ * Wrap a block of code with trace-wide context attributes.
338
+ * Baggage entries (tags, metadata, sessionId, userId) are propagated
339
+ * to all spans created within the callback via BaggageSpanProcessor.
340
+ *
341
+ * If there is no active span, a root span is created so all child spans
342
+ * are grouped under a single trace. If a span is already active, only
343
+ * baggage is set without creating an extra wrapper span.
344
+ */
345
+ async capture(options, fn) {
346
+ const baggageEntries = {};
347
+ if (options.tags?.length) {
348
+ baggageEntries[ATTRIBUTES.tags] = { value: JSON.stringify(options.tags) };
349
+ }
350
+ if (options.metadata) {
351
+ baggageEntries[ATTRIBUTES.metadata] = { value: JSON.stringify(options.metadata) };
352
+ }
353
+ if (options.sessionId) {
354
+ baggageEntries[ATTRIBUTES.sessionId] = { value: options.sessionId };
355
+ }
356
+ if (options.userId) {
357
+ baggageEntries[ATTRIBUTES.userId] = { value: options.userId };
358
+ }
359
+ const baggage = propagation2.createBaggage(baggageEntries);
360
+ const activeSpan = otel2.trace.getSpan(context.active());
361
+ if (activeSpan) {
362
+ const ctx = propagation2.setBaggage(context.active(), baggage);
363
+ return await context.with(ctx, async () => await fn(ctx));
364
+ }
365
+ const rootContext = propagation2.setBaggage(otel2.ROOT_CONTEXT, baggage);
366
+ return await this.tracer.startActiveSpan(
367
+ "latitude.trace",
368
+ { kind: otel2.SpanKind.INTERNAL },
369
+ rootContext,
370
+ async (span) => {
2076
371
  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
- }
2087
-
2088
- export { BACKGROUND, DEFAULT_REDACT_SPAN_PROCESSOR, DEFAULT_SPAN_EXPORTER, Instrumentation, LatitudeTelemetry, RedactSpanProcessor };
2089
- //# sourceMappingURL=index.js.map
372
+ const result = await fn(context.active());
373
+ span.setStatus({ code: otel2.SpanStatusCode.OK });
374
+ return result;
375
+ } catch (error) {
376
+ span.setStatus({
377
+ code: otel2.SpanStatusCode.ERROR,
378
+ message: error instanceof Error ? error.message : String(error)
379
+ });
380
+ span.recordException(error instanceof Error ? error : new Error(String(error)));
381
+ throw error;
382
+ } finally {
383
+ span.end();
384
+ }
385
+ }
386
+ );
387
+ }
388
+ };
389
+ export {
390
+ DEFAULT_REDACT_SPAN_PROCESSOR,
391
+ DEFAULT_SPAN_EXPORTER,
392
+ Instrumentation,
393
+ LatitudeTelemetry,
394
+ RedactSpanProcessor
395
+ };
396
+ //# sourceMappingURL=index.js.map