@latitude-data/telemetry 0.0.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +52 -0
- package/dist/index.cjs +1916 -425
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +319 -132
- package/dist/index.js +1896 -424
- package/dist/index.js.map +1 -1
- package/package.json +59 -48
- package/LICENSE +0 -157
package/dist/index.cjs
CHANGED
|
@@ -1,487 +1,1978 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var otel = require('@opentelemetry/api');
|
|
5
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
6
|
+
var incubating = require('@opentelemetry/semantic-conventions/incubating');
|
|
7
|
+
var uuid = require('uuid');
|
|
8
|
+
var baggageSpanProcessor = require('@opentelemetry/baggage-span-processor');
|
|
9
|
+
var contextAsyncHooks = require('@opentelemetry/context-async-hooks');
|
|
3
10
|
var core = require('@opentelemetry/core');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
11
|
+
var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
|
|
12
|
+
var instrumentation = require('@opentelemetry/instrumentation');
|
|
13
|
+
var resources = require('@opentelemetry/resources');
|
|
7
14
|
var sdkTraceNode = require('@opentelemetry/sdk-trace-node');
|
|
8
15
|
var instrumentationAnthropic = require('@traceloop/instrumentation-anthropic');
|
|
9
|
-
var instrumentationOpenai = require('@traceloop/instrumentation-openai');
|
|
10
16
|
var instrumentationAzure = require('@traceloop/instrumentation-azure');
|
|
11
|
-
var instrumentationVertexai = require('@traceloop/instrumentation-vertexai');
|
|
12
17
|
var instrumentationBedrock = require('@traceloop/instrumentation-bedrock');
|
|
13
18
|
var instrumentationCohere = require('@traceloop/instrumentation-cohere');
|
|
14
|
-
var
|
|
15
|
-
var
|
|
19
|
+
var instrumentationLangchain = require('@traceloop/instrumentation-langchain');
|
|
20
|
+
var instrumentationLlamaindex = require('@traceloop/instrumentation-llamaindex');
|
|
21
|
+
var instrumentationOpenai = require('@traceloop/instrumentation-openai');
|
|
22
|
+
var instrumentationTogether = require('@traceloop/instrumentation-together');
|
|
23
|
+
var instrumentationVertexai = require('@traceloop/instrumentation-vertexai');
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
async export(spans, resultCallback) {
|
|
31
|
-
await this.send(spans, () => resultCallback({ code: core.ExportResultCode.SUCCESS }), (error) => {
|
|
32
|
-
resultCallback({ code: core.ExportResultCode.FAILED, error });
|
|
25
|
+
function _interopNamespaceDefault(e) {
|
|
26
|
+
var n = Object.create(null);
|
|
27
|
+
if (e) {
|
|
28
|
+
Object.keys(e).forEach(function (k) {
|
|
29
|
+
if (k !== 'default') {
|
|
30
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
31
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () { return e[k]; }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
33
36
|
});
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
n.default = e;
|
|
39
|
+
return Object.freeze(n);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var otel__namespace = /*#__PURE__*/_interopNamespaceDefault(otel);
|
|
43
|
+
|
|
44
|
+
class RedactSpanProcessor {
|
|
45
|
+
options;
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.options = options;
|
|
48
|
+
if (!options.mask) {
|
|
49
|
+
this.options.mask = (_attribute, _value) => '******';
|
|
50
|
+
}
|
|
40
51
|
}
|
|
41
|
-
|
|
42
|
-
//
|
|
52
|
+
onStart(_span, _context) {
|
|
53
|
+
// Noop
|
|
43
54
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const body = JSON.stringify(serviceRequest);
|
|
51
|
-
try {
|
|
52
|
-
const response = await fetch(this.url, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers: {
|
|
55
|
-
'Content-Type': 'application/json',
|
|
56
|
-
...this.headers,
|
|
57
|
-
},
|
|
58
|
-
body,
|
|
59
|
-
});
|
|
60
|
-
if (!response.ok || response.status >= 400) {
|
|
61
|
-
throw new Error(`${response.status} ${response.statusText}`);
|
|
62
|
-
}
|
|
63
|
-
onSuccess();
|
|
55
|
+
onEnd(span) {
|
|
56
|
+
Object.assign(span.attributes, this.redactAttributes(span.attributes));
|
|
57
|
+
for (const event of span.events) {
|
|
58
|
+
if (!event.attributes)
|
|
59
|
+
continue;
|
|
60
|
+
Object.assign(event.attributes, this.redactAttributes(event.attributes));
|
|
64
61
|
}
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
for (const link of span.links) {
|
|
63
|
+
if (!link.attributes)
|
|
64
|
+
continue;
|
|
65
|
+
Object.assign(link.attributes, this.redactAttributes(link.attributes));
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
|
-
|
|
70
|
-
return
|
|
71
|
-
resourceSpans: [
|
|
72
|
-
{
|
|
73
|
-
resource: {
|
|
74
|
-
attributes: this.convertAttributes(spans[0]?.resource?.attributes || {}),
|
|
75
|
-
},
|
|
76
|
-
scopeSpans: [
|
|
77
|
-
{
|
|
78
|
-
spans: spans.map((span) => ({
|
|
79
|
-
traceId: span.spanContext().traceId,
|
|
80
|
-
spanId: span.spanContext().spanId,
|
|
81
|
-
parentSpanId: span.parentSpanId,
|
|
82
|
-
name: span.name,
|
|
83
|
-
kind: span.kind,
|
|
84
|
-
startTimeUnixNano: core.hrTimeToNanoseconds(span.startTime).toString(),
|
|
85
|
-
endTimeUnixNano: span.endTime
|
|
86
|
-
? core.hrTimeToNanoseconds(span.endTime).toString()
|
|
87
|
-
: undefined,
|
|
88
|
-
attributes: this.convertAttributes(span.attributes),
|
|
89
|
-
status: span.status && {
|
|
90
|
-
code: span.status.code,
|
|
91
|
-
message: span.status.message,
|
|
92
|
-
},
|
|
93
|
-
events: span.events?.map((event) => ({
|
|
94
|
-
timeUnixNano: core.hrTimeToNanoseconds(event.time).toString(),
|
|
95
|
-
name: event.name,
|
|
96
|
-
attributes: this.convertAttributes(event.attributes),
|
|
97
|
-
})),
|
|
98
|
-
links: span.links?.map((link) => ({
|
|
99
|
-
traceId: link.context.traceId,
|
|
100
|
-
spanId: link.context.spanId,
|
|
101
|
-
attributes: this.convertAttributes(link.attributes),
|
|
102
|
-
})),
|
|
103
|
-
})),
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
};
|
|
68
|
+
forceFlush() {
|
|
69
|
+
return Promise.resolve();
|
|
109
70
|
}
|
|
110
|
-
|
|
111
|
-
return
|
|
71
|
+
shutdown() {
|
|
72
|
+
return Promise.resolve();
|
|
112
73
|
}
|
|
113
|
-
|
|
114
|
-
return
|
|
74
|
+
shouldRedact(attribute) {
|
|
75
|
+
return this.options.attributes.some((pattern) => {
|
|
76
|
+
if (typeof pattern === 'string') {
|
|
77
|
+
return attribute === pattern;
|
|
78
|
+
}
|
|
79
|
+
else if (pattern instanceof RegExp) {
|
|
80
|
+
return pattern.test(attribute);
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
});
|
|
115
84
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
85
|
+
redactAttributes(attributes) {
|
|
86
|
+
const redacted = {};
|
|
87
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
88
|
+
if (this.shouldRedact(key)) {
|
|
89
|
+
redacted[key] = this.options.mask(key, value);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return redacted;
|
|
121
93
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
94
|
+
}
|
|
95
|
+
const DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
|
|
96
|
+
attributes: [
|
|
97
|
+
/^.*auth.*$/i,
|
|
98
|
+
/^.*authorization.*$/i,
|
|
99
|
+
/^(?!gen_ai\.).*token.*$/i,
|
|
100
|
+
/^.*secret.*$/i,
|
|
101
|
+
/^.*key.*$/i,
|
|
102
|
+
/^.*password.*$/i,
|
|
103
|
+
/^.*cookie.*$/i,
|
|
104
|
+
/^.*session.*$/i,
|
|
105
|
+
/^.*credential.*$/i,
|
|
106
|
+
/^.*signature.*$/i,
|
|
107
|
+
/^.*oauth.*$/i,
|
|
108
|
+
/^.*saml.*$/i,
|
|
109
|
+
/^.*openid.*$/i,
|
|
110
|
+
/^.*refresh.*$/i,
|
|
111
|
+
/^.*jwt.*$/i,
|
|
112
|
+
/^.*otp.*$/i,
|
|
113
|
+
/^.*mfa.*$/i,
|
|
114
|
+
/^.*csrf.*$/i,
|
|
115
|
+
/^.*xsrf.*$/i,
|
|
116
|
+
/^.*refresh.*$/i,
|
|
117
|
+
/^.*x[-_]forwarded[-_]for.*$/i,
|
|
118
|
+
/^.*x[-_]real[-_]ip.*$/i,
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const DEFAULT_GATEWAY_BASE_URL = {
|
|
123
|
+
production: 'https://gateway.latitude.so',
|
|
124
|
+
development: 'http://localhost:8787',
|
|
125
|
+
test: 'http://localhost:8787',
|
|
126
|
+
}["production"];
|
|
127
|
+
function GET_GATEWAY_BASE_URL() {
|
|
128
|
+
if (process.env.GATEWAY_BASE_URL) {
|
|
129
|
+
return process.env.GATEWAY_BASE_URL;
|
|
130
130
|
}
|
|
131
|
+
if (!process.env.GATEWAY_HOSTNAME) {
|
|
132
|
+
return DEFAULT_GATEWAY_BASE_URL;
|
|
133
|
+
}
|
|
134
|
+
const protocol = process.env.GATEWAY_SSL ? 'https' : 'http';
|
|
135
|
+
const port = process.env.GATEWAY_PORT ?? (process.env.GATEWAY_SSL ? 443 : 80);
|
|
136
|
+
const hostname = process.env.GATEWAY_HOSTNAME;
|
|
137
|
+
return `${protocol}://${hostname}:${port}`;
|
|
131
138
|
}
|
|
139
|
+
const env = { GATEWAY_BASE_URL: GET_GATEWAY_BASE_URL() };
|
|
132
140
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
141
|
+
var SegmentSource;
|
|
142
|
+
(function (SegmentSource) {
|
|
143
|
+
SegmentSource["API"] = "api";
|
|
144
|
+
SegmentSource["Playground"] = "playground";
|
|
145
|
+
SegmentSource["Evaluation"] = "evaluation";
|
|
146
|
+
SegmentSource["Experiment"] = "experiment";
|
|
147
|
+
SegmentSource["User"] = "user";
|
|
148
|
+
SegmentSource["SharedPrompt"] = "shared_prompt";
|
|
149
|
+
SegmentSource["AgentAsTool"] = "agent_as_tool";
|
|
150
|
+
SegmentSource["EmailTrigger"] = "email_trigger";
|
|
151
|
+
SegmentSource["ScheduledTrigger"] = "scheduled_trigger";
|
|
152
|
+
})(SegmentSource || (SegmentSource = {}));
|
|
153
|
+
var SegmentType;
|
|
154
|
+
(function (SegmentType) {
|
|
155
|
+
SegmentType["Document"] = "document";
|
|
156
|
+
SegmentType["Step"] = "step";
|
|
157
|
+
})(SegmentType || (SegmentType = {}));
|
|
158
|
+
const baseSegmentBaggageSchema = zod.z.object({
|
|
159
|
+
id: zod.z.string(),
|
|
160
|
+
parentId: zod.z.string().optional(),
|
|
161
|
+
source: zod.z.nativeEnum(SegmentSource),
|
|
162
|
+
});
|
|
163
|
+
zod.z.discriminatedUnion('type', [
|
|
164
|
+
baseSegmentBaggageSchema.extend({
|
|
165
|
+
type: zod.z.literal(SegmentType.Document),
|
|
166
|
+
data: zod.z.object({
|
|
167
|
+
logUuid: zod.z.string().optional(), // TODO(tracing): temporal related log, remove when observability is ready
|
|
168
|
+
commitUuid: zod.z.string(),
|
|
169
|
+
documentUuid: zod.z.string(),
|
|
170
|
+
experimentUuid: zod.z.string().optional(),
|
|
171
|
+
externalId: zod.z.string().optional(),
|
|
172
|
+
}),
|
|
173
|
+
}),
|
|
174
|
+
baseSegmentBaggageSchema.extend({
|
|
175
|
+
type: zod.z.literal(SegmentType.Step),
|
|
176
|
+
data: zod.z.undefined().optional(),
|
|
177
|
+
}),
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
var SpanKind;
|
|
181
|
+
(function (SpanKind) {
|
|
182
|
+
SpanKind["Internal"] = "internal";
|
|
183
|
+
SpanKind["Server"] = "server";
|
|
184
|
+
SpanKind["Client"] = "client";
|
|
185
|
+
SpanKind["Producer"] = "producer";
|
|
186
|
+
SpanKind["Consumer"] = "consumer";
|
|
187
|
+
})(SpanKind || (SpanKind = {}));
|
|
188
|
+
// Note: loosely based on OpenTelemetry GenAI semantic conventions
|
|
189
|
+
var SpanType;
|
|
190
|
+
(function (SpanType) {
|
|
191
|
+
SpanType["Tool"] = "tool";
|
|
192
|
+
SpanType["Completion"] = "completion";
|
|
193
|
+
SpanType["Embedding"] = "embedding";
|
|
194
|
+
SpanType["Retrieval"] = "retrieval";
|
|
195
|
+
SpanType["Reranking"] = "reranking";
|
|
196
|
+
SpanType["Http"] = "http";
|
|
197
|
+
SpanType["Segment"] = "segment";
|
|
198
|
+
SpanType["Unknown"] = "unknown";
|
|
199
|
+
})(SpanType || (SpanType = {}));
|
|
200
|
+
const GENAI_SPANS = [
|
|
201
|
+
SpanType.Tool,
|
|
202
|
+
SpanType.Completion,
|
|
203
|
+
SpanType.Embedding,
|
|
204
|
+
SpanType.Retrieval,
|
|
205
|
+
SpanType.Reranking,
|
|
206
|
+
];
|
|
207
|
+
[SpanType.Http, SpanType.Segment, SpanType.Unknown];
|
|
208
|
+
var SpanStatus;
|
|
209
|
+
(function (SpanStatus) {
|
|
210
|
+
SpanStatus["Unset"] = "unset";
|
|
211
|
+
SpanStatus["Ok"] = "ok";
|
|
212
|
+
SpanStatus["Error"] = "error";
|
|
213
|
+
})(SpanStatus || (SpanStatus = {}));
|
|
214
|
+
|
|
215
|
+
// Note: Traces are unmaterialized but this context is used to propagate the trace
|
|
216
|
+
// See www.w3.org/TR/trace-context and w3c.github.io/baggage
|
|
217
|
+
zod.z.object({
|
|
218
|
+
traceparent: zod.z.string(), // <version>-<trace-id>-<span-id>-<trace-flags>
|
|
219
|
+
tracestate: zod.z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
220
|
+
baggage: zod.z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
/* Note: Instrumentation scopes from all language SDKs */
|
|
224
|
+
const SCOPE_LATITUDE = 'so.latitude.instrumentation';
|
|
225
|
+
var InstrumentationScope;
|
|
226
|
+
(function (InstrumentationScope) {
|
|
227
|
+
InstrumentationScope["Manual"] = "manual";
|
|
228
|
+
InstrumentationScope["Latitude"] = "latitude";
|
|
229
|
+
InstrumentationScope["OpenAI"] = "openai";
|
|
230
|
+
InstrumentationScope["Anthropic"] = "anthropic";
|
|
231
|
+
InstrumentationScope["AzureOpenAI"] = "azure";
|
|
232
|
+
InstrumentationScope["VercelAI"] = "vercelai";
|
|
233
|
+
InstrumentationScope["VertexAI"] = "vertexai";
|
|
234
|
+
InstrumentationScope["AIPlatform"] = "aiplatform";
|
|
235
|
+
InstrumentationScope["MistralAI"] = "mistralai";
|
|
236
|
+
InstrumentationScope["Bedrock"] = "bedrock";
|
|
237
|
+
InstrumentationScope["Sagemaker"] = "sagemaker";
|
|
238
|
+
InstrumentationScope["TogetherAI"] = "togetherai";
|
|
239
|
+
InstrumentationScope["Replicate"] = "replicate";
|
|
240
|
+
InstrumentationScope["Groq"] = "groq";
|
|
241
|
+
InstrumentationScope["Cohere"] = "cohere";
|
|
242
|
+
InstrumentationScope["LiteLLM"] = "litellm";
|
|
243
|
+
InstrumentationScope["Langchain"] = "langchain";
|
|
244
|
+
InstrumentationScope["LlamaIndex"] = "llamaindex";
|
|
245
|
+
InstrumentationScope["DSPy"] = "dspy";
|
|
246
|
+
InstrumentationScope["Haystack"] = "haystack";
|
|
247
|
+
InstrumentationScope["Ollama"] = "ollama";
|
|
248
|
+
InstrumentationScope["Transformers"] = "transformers";
|
|
249
|
+
InstrumentationScope["AlephAlpha"] = "alephalpha";
|
|
250
|
+
})(InstrumentationScope || (InstrumentationScope = {}));
|
|
251
|
+
/* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
|
|
252
|
+
const ATTR_LATITUDE = 'latitude';
|
|
253
|
+
const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
|
|
254
|
+
const ATTR_LATITUDE_SEGMENT_ID = `${ATTR_LATITUDE}.segment.id`;
|
|
255
|
+
const ATTR_LATITUDE_SEGMENT_PARENT_ID = `${ATTR_LATITUDE}.segment.parent_id`;
|
|
256
|
+
const ATTR_LATITUDE_SEGMENTS = `${ATTR_LATITUDE}.segments`;
|
|
257
|
+
const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
|
|
258
|
+
const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
|
|
259
|
+
const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
|
|
260
|
+
const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
|
|
261
|
+
const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
|
|
262
|
+
const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
|
|
263
|
+
const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
|
|
264
|
+
const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
|
|
265
|
+
const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
|
|
266
|
+
const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
|
|
267
|
+
const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
|
|
268
|
+
const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
|
|
269
|
+
const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
|
|
270
|
+
const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
|
|
271
|
+
const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
|
|
272
|
+
const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
|
|
273
|
+
const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
|
|
274
|
+
const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
|
|
275
|
+
const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
|
|
276
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
|
|
277
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
|
|
278
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
|
|
279
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
|
|
280
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
|
|
281
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
|
|
282
|
+
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
|
|
283
|
+
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
|
|
284
|
+
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
|
|
285
|
+
const ATTR_HTTP_REQUEST_URL = 'http.request.url';
|
|
286
|
+
const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
|
|
287
|
+
const ATTR_HTTP_REQUEST_HEADERS = 'http.request.header';
|
|
288
|
+
const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
|
|
289
|
+
const ATTR_HTTP_RESPONSE_HEADERS = 'http.response.header';
|
|
290
|
+
/* Note: Schemas for span ingestion following OpenTelemetry service request specification */
|
|
291
|
+
var Otlp;
|
|
292
|
+
(function (Otlp) {
|
|
293
|
+
Otlp.attributeValueSchema = zod.z.object({
|
|
294
|
+
stringValue: zod.z.string().optional(),
|
|
295
|
+
intValue: zod.z.number().optional(),
|
|
296
|
+
boolValue: zod.z.boolean().optional(),
|
|
297
|
+
arrayValue: zod.z
|
|
298
|
+
.object({
|
|
299
|
+
values: zod.z.array(zod.z.object({
|
|
300
|
+
stringValue: zod.z.string().optional(),
|
|
301
|
+
intValue: zod.z.number().optional(),
|
|
302
|
+
boolValue: zod.z.boolean().optional(),
|
|
303
|
+
})),
|
|
304
|
+
})
|
|
305
|
+
.optional(),
|
|
306
|
+
});
|
|
307
|
+
Otlp.attributeSchema = zod.z.object({
|
|
308
|
+
key: zod.z.string(),
|
|
309
|
+
value: Otlp.attributeValueSchema,
|
|
310
|
+
});
|
|
311
|
+
Otlp.eventSchema = zod.z.object({
|
|
312
|
+
name: zod.z.string(),
|
|
313
|
+
timeUnixNano: zod.z.string(),
|
|
314
|
+
attributes: zod.z.array(Otlp.attributeSchema).optional(),
|
|
315
|
+
});
|
|
316
|
+
Otlp.linkSchema = zod.z.object({
|
|
317
|
+
traceId: zod.z.string(),
|
|
318
|
+
spanId: zod.z.string(),
|
|
319
|
+
attributes: zod.z.array(Otlp.attributeSchema).optional(),
|
|
320
|
+
});
|
|
321
|
+
Otlp.statusSchema = zod.z.object({
|
|
322
|
+
code: zod.z.number(),
|
|
323
|
+
message: zod.z.string().optional(),
|
|
324
|
+
});
|
|
325
|
+
Otlp.spanSchema = zod.z.object({
|
|
326
|
+
traceId: zod.z.string(),
|
|
327
|
+
spanId: zod.z.string(),
|
|
328
|
+
parentSpanId: zod.z.string().optional(),
|
|
329
|
+
name: zod.z.string(),
|
|
330
|
+
kind: zod.z.number(),
|
|
331
|
+
startTimeUnixNano: zod.z.string(),
|
|
332
|
+
endTimeUnixNano: zod.z.string(),
|
|
333
|
+
status: Otlp.statusSchema.optional(),
|
|
334
|
+
events: zod.z.array(Otlp.eventSchema).optional(),
|
|
335
|
+
links: zod.z.array(Otlp.linkSchema).optional(),
|
|
336
|
+
attributes: zod.z.array(Otlp.attributeSchema).optional(),
|
|
337
|
+
});
|
|
338
|
+
Otlp.scopeSchema = zod.z.object({
|
|
339
|
+
name: zod.z.string(),
|
|
340
|
+
version: zod.z.string().optional(),
|
|
341
|
+
});
|
|
342
|
+
Otlp.scopeSpanSchema = zod.z.object({
|
|
343
|
+
scope: Otlp.scopeSchema,
|
|
344
|
+
spans: zod.z.array(Otlp.spanSchema),
|
|
345
|
+
});
|
|
346
|
+
Otlp.resourceSchema = zod.z.object({
|
|
347
|
+
attributes: zod.z.array(Otlp.attributeSchema),
|
|
348
|
+
});
|
|
349
|
+
Otlp.resourceSpanSchema = zod.z.object({
|
|
350
|
+
resource: Otlp.resourceSchema,
|
|
351
|
+
scopeSpans: zod.z.array(Otlp.scopeSpanSchema),
|
|
352
|
+
});
|
|
353
|
+
Otlp.serviceRequestSchema = zod.z.object({
|
|
354
|
+
resourceSpans: zod.z.array(Otlp.resourceSpanSchema),
|
|
355
|
+
});
|
|
356
|
+
})(Otlp || (Otlp = {}));
|
|
357
|
+
|
|
358
|
+
var StreamEventTypes;
|
|
359
|
+
(function (StreamEventTypes) {
|
|
360
|
+
StreamEventTypes["Latitude"] = "latitude-event";
|
|
361
|
+
StreamEventTypes["Provider"] = "provider-event";
|
|
362
|
+
})(StreamEventTypes || (StreamEventTypes = {}));
|
|
363
|
+
zod.z.object({
|
|
364
|
+
id: zod.z.string(),
|
|
365
|
+
name: zod.z.string(),
|
|
366
|
+
result: zod.z.unknown(),
|
|
367
|
+
isError: zod.z.boolean().optional(),
|
|
368
|
+
text: zod.z.string().optional(),
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
var ParameterType;
|
|
372
|
+
(function (ParameterType) {
|
|
373
|
+
ParameterType["Text"] = "text";
|
|
374
|
+
ParameterType["Image"] = "image";
|
|
375
|
+
ParameterType["File"] = "file";
|
|
376
|
+
})(ParameterType || (ParameterType = {}));
|
|
377
|
+
var LatitudeTool;
|
|
378
|
+
(function (LatitudeTool) {
|
|
379
|
+
LatitudeTool["RunCode"] = "code";
|
|
380
|
+
LatitudeTool["WebSearch"] = "search";
|
|
381
|
+
LatitudeTool["WebExtract"] = "extract";
|
|
382
|
+
})(LatitudeTool || (LatitudeTool = {}));
|
|
383
|
+
var LatitudeToolInternalName;
|
|
384
|
+
(function (LatitudeToolInternalName) {
|
|
385
|
+
LatitudeToolInternalName["RunCode"] = "lat_tool_run_code";
|
|
386
|
+
LatitudeToolInternalName["WebSearch"] = "lat_tool_web_search";
|
|
387
|
+
LatitudeToolInternalName["WebExtract"] = "lat_tool_web_extract";
|
|
388
|
+
})(LatitudeToolInternalName || (LatitudeToolInternalName = {}));
|
|
389
|
+
|
|
390
|
+
const actualOutputConfiguration = zod.z.object({
|
|
391
|
+
messageSelection: zod.z.enum(['last', 'all']), // Which assistant messages to select
|
|
392
|
+
contentFilter: zod.z.enum(['text', 'image', 'file', 'tool_call']).optional(),
|
|
393
|
+
parsingFormat: zod.z.enum(['string', 'json']),
|
|
394
|
+
fieldAccessor: zod.z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
395
|
+
});
|
|
396
|
+
const expectedOutputConfiguration = zod.z.object({
|
|
397
|
+
parsingFormat: zod.z.enum(['string', 'json']),
|
|
398
|
+
fieldAccessor: zod.z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
399
|
+
});
|
|
400
|
+
const baseEvaluationConfiguration = zod.z.object({
|
|
401
|
+
reverseScale: zod.z.boolean(), // If true, lower is better, otherwise, higher is better
|
|
402
|
+
actualOutput: actualOutputConfiguration.optional(), // Optional for backwards compatibility
|
|
403
|
+
expectedOutput: expectedOutputConfiguration.optional(), // Optional for backwards compatibility
|
|
404
|
+
});
|
|
405
|
+
const baseEvaluationResultMetadata = zod.z.object({
|
|
406
|
+
// Configuration snapshot is defined in every metric specification
|
|
407
|
+
actualOutput: zod.z.string(),
|
|
408
|
+
expectedOutput: zod.z.string().optional(),
|
|
409
|
+
datasetLabel: zod.z.string().optional(),
|
|
410
|
+
});
|
|
411
|
+
const baseEvaluationResultError = zod.z.object({
|
|
412
|
+
message: zod.z.string(),
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
416
|
+
criteria: zod.z.string().optional(),
|
|
417
|
+
});
|
|
418
|
+
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
419
|
+
reason: zod.z.string().optional(),
|
|
420
|
+
});
|
|
421
|
+
const humanEvaluationResultError = baseEvaluationResultError.extend({});
|
|
422
|
+
// BINARY
|
|
423
|
+
const humanEvaluationBinaryConfiguration = humanEvaluationConfiguration.extend({
|
|
424
|
+
passDescription: zod.z.string().optional(),
|
|
425
|
+
failDescription: zod.z.string().optional(),
|
|
426
|
+
});
|
|
427
|
+
humanEvaluationResultMetadata.extend({
|
|
428
|
+
configuration: humanEvaluationBinaryConfiguration,
|
|
429
|
+
});
|
|
430
|
+
humanEvaluationResultError.extend({});
|
|
431
|
+
const HumanEvaluationBinarySpecification = {
|
|
432
|
+
};
|
|
433
|
+
// RATING
|
|
434
|
+
const humanEvaluationRatingConfiguration = humanEvaluationConfiguration.extend({
|
|
435
|
+
minRating: zod.z.number(),
|
|
436
|
+
minRatingDescription: zod.z.string().optional(),
|
|
437
|
+
maxRating: zod.z.number(),
|
|
438
|
+
maxRatingDescription: zod.z.string().optional(),
|
|
439
|
+
minThreshold: zod.z.number().optional(), // Threshold in rating range
|
|
440
|
+
maxThreshold: zod.z.number().optional(), // Threshold in rating range
|
|
441
|
+
});
|
|
442
|
+
humanEvaluationResultMetadata.extend({
|
|
443
|
+
configuration: humanEvaluationRatingConfiguration,
|
|
444
|
+
});
|
|
445
|
+
humanEvaluationResultError.extend({});
|
|
446
|
+
const HumanEvaluationRatingSpecification = {
|
|
447
|
+
};
|
|
448
|
+
/* ------------------------------------------------------------------------- */
|
|
449
|
+
var HumanEvaluationMetric;
|
|
450
|
+
(function (HumanEvaluationMetric) {
|
|
451
|
+
HumanEvaluationMetric["Binary"] = "binary";
|
|
452
|
+
HumanEvaluationMetric["Rating"] = "rating";
|
|
453
|
+
})(HumanEvaluationMetric || (HumanEvaluationMetric = {}));
|
|
454
|
+
const HumanEvaluationSpecification = {
|
|
455
|
+
// prettier-ignore
|
|
456
|
+
metrics: {
|
|
457
|
+
[HumanEvaluationMetric.Binary]: HumanEvaluationBinarySpecification,
|
|
458
|
+
[HumanEvaluationMetric.Rating]: HumanEvaluationRatingSpecification,
|
|
459
|
+
},
|
|
158
460
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
461
|
+
|
|
462
|
+
const llmEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
463
|
+
provider: zod.z.string(),
|
|
464
|
+
model: zod.z.string(),
|
|
465
|
+
});
|
|
466
|
+
const llmEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
467
|
+
evaluationLogId: zod.z.number(),
|
|
468
|
+
reason: zod.z.string(),
|
|
469
|
+
tokens: zod.z.number(),
|
|
470
|
+
cost: zod.z.number(),
|
|
471
|
+
duration: zod.z.number(),
|
|
472
|
+
});
|
|
473
|
+
const llmEvaluationResultError = baseEvaluationResultError.extend({
|
|
474
|
+
runErrorId: zod.z.number().optional(),
|
|
475
|
+
});
|
|
476
|
+
// BINARY
|
|
477
|
+
const llmEvaluationBinaryConfiguration = llmEvaluationConfiguration.extend({
|
|
478
|
+
criteria: zod.z.string(),
|
|
479
|
+
passDescription: zod.z.string(),
|
|
480
|
+
failDescription: zod.z.string(),
|
|
481
|
+
});
|
|
482
|
+
llmEvaluationResultMetadata.extend({
|
|
483
|
+
configuration: llmEvaluationBinaryConfiguration,
|
|
484
|
+
});
|
|
485
|
+
llmEvaluationResultError.extend({});
|
|
486
|
+
const LlmEvaluationBinarySpecification = {
|
|
487
|
+
};
|
|
488
|
+
// RATING
|
|
489
|
+
const llmEvaluationRatingConfiguration = llmEvaluationConfiguration.extend({
|
|
490
|
+
criteria: zod.z.string(),
|
|
491
|
+
minRating: zod.z.number(),
|
|
492
|
+
minRatingDescription: zod.z.string(),
|
|
493
|
+
maxRating: zod.z.number(),
|
|
494
|
+
maxRatingDescription: zod.z.string(),
|
|
495
|
+
minThreshold: zod.z.number().optional(), // Threshold in rating range
|
|
496
|
+
maxThreshold: zod.z.number().optional(), // Threshold in rating range
|
|
497
|
+
});
|
|
498
|
+
llmEvaluationResultMetadata.extend({
|
|
499
|
+
configuration: llmEvaluationRatingConfiguration,
|
|
500
|
+
});
|
|
501
|
+
llmEvaluationResultError.extend({});
|
|
502
|
+
const LlmEvaluationRatingSpecification = {
|
|
503
|
+
};
|
|
504
|
+
// COMPARISON
|
|
505
|
+
const llmEvaluationComparisonConfiguration = llmEvaluationConfiguration.extend({
|
|
506
|
+
criteria: zod.z.string(),
|
|
507
|
+
passDescription: zod.z.string(),
|
|
508
|
+
failDescription: zod.z.string(),
|
|
509
|
+
minThreshold: zod.z.number().optional(), // Threshold percentage
|
|
510
|
+
maxThreshold: zod.z.number().optional(), // Threshold percentage
|
|
511
|
+
});
|
|
512
|
+
llmEvaluationResultMetadata.extend({
|
|
513
|
+
configuration: llmEvaluationComparisonConfiguration,
|
|
514
|
+
});
|
|
515
|
+
llmEvaluationResultError.extend({});
|
|
516
|
+
const LlmEvaluationComparisonSpecification = {
|
|
517
|
+
};
|
|
518
|
+
// CUSTOM
|
|
519
|
+
const llmEvaluationCustomConfiguration = llmEvaluationConfiguration.extend({
|
|
520
|
+
prompt: zod.z.string(),
|
|
521
|
+
minScore: zod.z.number(),
|
|
522
|
+
maxScore: zod.z.number(),
|
|
523
|
+
minThreshold: zod.z.number().optional(), // Threshold percentage
|
|
524
|
+
maxThreshold: zod.z.number().optional(), // Threshold percentage
|
|
525
|
+
});
|
|
526
|
+
llmEvaluationResultMetadata.extend({
|
|
527
|
+
configuration: llmEvaluationCustomConfiguration,
|
|
528
|
+
});
|
|
529
|
+
llmEvaluationResultError.extend({});
|
|
530
|
+
const LlmEvaluationCustomSpecification = {
|
|
531
|
+
};
|
|
532
|
+
// CUSTOM LABELED
|
|
533
|
+
const LlmEvaluationCustomLabeledSpecification = {
|
|
534
|
+
};
|
|
535
|
+
/* ------------------------------------------------------------------------- */
|
|
536
|
+
var LlmEvaluationMetric;
|
|
537
|
+
(function (LlmEvaluationMetric) {
|
|
538
|
+
LlmEvaluationMetric["Binary"] = "binary";
|
|
539
|
+
LlmEvaluationMetric["Rating"] = "rating";
|
|
540
|
+
LlmEvaluationMetric["Comparison"] = "comparison";
|
|
541
|
+
LlmEvaluationMetric["Custom"] = "custom";
|
|
542
|
+
LlmEvaluationMetric["CustomLabeled"] = "custom_labeled";
|
|
543
|
+
})(LlmEvaluationMetric || (LlmEvaluationMetric = {}));
|
|
544
|
+
const LlmEvaluationSpecification = {
|
|
545
|
+
// prettier-ignore
|
|
546
|
+
metrics: {
|
|
547
|
+
[LlmEvaluationMetric.Binary]: LlmEvaluationBinarySpecification,
|
|
548
|
+
[LlmEvaluationMetric.Rating]: LlmEvaluationRatingSpecification,
|
|
549
|
+
[LlmEvaluationMetric.Comparison]: LlmEvaluationComparisonSpecification,
|
|
550
|
+
[LlmEvaluationMetric.Custom]: LlmEvaluationCustomSpecification,
|
|
551
|
+
[LlmEvaluationMetric.CustomLabeled]: LlmEvaluationCustomLabeledSpecification,
|
|
552
|
+
},
|
|
164
553
|
};
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
554
|
+
|
|
555
|
+
const ruleEvaluationConfiguration = baseEvaluationConfiguration.extend({});
|
|
556
|
+
const ruleEvaluationResultMetadata = baseEvaluationResultMetadata.extend({});
|
|
557
|
+
const ruleEvaluationResultError = baseEvaluationResultError.extend({});
|
|
558
|
+
// EXACT MATCH
|
|
559
|
+
const ruleEvaluationExactMatchConfiguration = ruleEvaluationConfiguration.extend({
|
|
560
|
+
caseInsensitive: zod.z.boolean(),
|
|
561
|
+
});
|
|
562
|
+
ruleEvaluationResultMetadata.extend({
|
|
563
|
+
configuration: ruleEvaluationExactMatchConfiguration,
|
|
564
|
+
});
|
|
565
|
+
ruleEvaluationResultError.extend({});
|
|
566
|
+
const RuleEvaluationExactMatchSpecification = {
|
|
567
|
+
};
|
|
568
|
+
// REGULAR EXPRESSION
|
|
569
|
+
const ruleEvaluationRegularExpressionConfiguration = ruleEvaluationConfiguration.extend({
|
|
570
|
+
pattern: zod.z.string(),
|
|
571
|
+
});
|
|
572
|
+
ruleEvaluationResultMetadata.extend({
|
|
573
|
+
configuration: ruleEvaluationRegularExpressionConfiguration,
|
|
574
|
+
});
|
|
575
|
+
ruleEvaluationResultError.extend({});
|
|
576
|
+
const RuleEvaluationRegularExpressionSpecification = {
|
|
577
|
+
};
|
|
578
|
+
// SCHEMA VALIDATION
|
|
579
|
+
const ruleEvaluationSchemaValidationConfiguration = ruleEvaluationConfiguration.extend({
|
|
580
|
+
format: zod.z.enum(['json']),
|
|
581
|
+
schema: zod.z.string(),
|
|
582
|
+
});
|
|
583
|
+
ruleEvaluationResultMetadata.extend({
|
|
584
|
+
configuration: ruleEvaluationSchemaValidationConfiguration,
|
|
585
|
+
});
|
|
586
|
+
ruleEvaluationResultError.extend({});
|
|
587
|
+
const RuleEvaluationSchemaValidationSpecification = {
|
|
588
|
+
};
|
|
589
|
+
// LENGTH COUNT
|
|
590
|
+
const ruleEvaluationLengthCountConfiguration = ruleEvaluationConfiguration.extend({
|
|
591
|
+
algorithm: zod.z.enum(['character', 'word', 'sentence']),
|
|
592
|
+
minLength: zod.z.number().optional(),
|
|
593
|
+
maxLength: zod.z.number().optional(),
|
|
594
|
+
});
|
|
595
|
+
ruleEvaluationResultMetadata.extend({
|
|
596
|
+
configuration: ruleEvaluationLengthCountConfiguration,
|
|
597
|
+
});
|
|
598
|
+
ruleEvaluationResultError.extend({});
|
|
599
|
+
const RuleEvaluationLengthCountSpecification = {
|
|
600
|
+
};
|
|
601
|
+
// LEXICAL OVERLAP
|
|
602
|
+
const ruleEvaluationLexicalOverlapConfiguration = ruleEvaluationConfiguration.extend({
|
|
603
|
+
algorithm: zod.z.enum(['substring', 'levenshtein_distance', 'rouge']),
|
|
604
|
+
minOverlap: zod.z.number().optional(), // Percentage of overlap
|
|
605
|
+
maxOverlap: zod.z.number().optional(), // Percentage of overlap
|
|
606
|
+
});
|
|
607
|
+
ruleEvaluationResultMetadata.extend({
|
|
608
|
+
configuration: ruleEvaluationLexicalOverlapConfiguration,
|
|
609
|
+
});
|
|
610
|
+
ruleEvaluationResultError.extend({});
|
|
611
|
+
const RuleEvaluationLexicalOverlapSpecification = {
|
|
612
|
+
};
|
|
613
|
+
// SEMANTIC SIMILARITY
|
|
614
|
+
const ruleEvaluationSemanticSimilarityConfiguration = ruleEvaluationConfiguration.extend({
|
|
615
|
+
algorithm: zod.z.enum(['cosine_distance']),
|
|
616
|
+
minSimilarity: zod.z.number().optional(), // Percentage of similarity
|
|
617
|
+
maxSimilarity: zod.z.number().optional(), // Percentage of similarity
|
|
618
|
+
});
|
|
619
|
+
ruleEvaluationResultMetadata.extend({
|
|
620
|
+
configuration: ruleEvaluationSemanticSimilarityConfiguration,
|
|
621
|
+
});
|
|
622
|
+
ruleEvaluationResultError.extend({});
|
|
623
|
+
const RuleEvaluationSemanticSimilaritySpecification = {
|
|
624
|
+
};
|
|
625
|
+
// NUMERIC SIMILARITY
|
|
626
|
+
const ruleEvaluationNumericSimilarityConfiguration = ruleEvaluationConfiguration.extend({
|
|
627
|
+
algorithm: zod.z.enum(['relative_difference']),
|
|
628
|
+
minSimilarity: zod.z.number().optional(), // Percentage of similarity
|
|
629
|
+
maxSimilarity: zod.z.number().optional(), // Percentage of similarity
|
|
630
|
+
});
|
|
631
|
+
ruleEvaluationResultMetadata.extend({
|
|
632
|
+
configuration: ruleEvaluationNumericSimilarityConfiguration,
|
|
633
|
+
});
|
|
634
|
+
ruleEvaluationResultError.extend({});
|
|
635
|
+
const RuleEvaluationNumericSimilaritySpecification = {
|
|
636
|
+
};
|
|
637
|
+
/* ------------------------------------------------------------------------- */
|
|
638
|
+
var RuleEvaluationMetric;
|
|
639
|
+
(function (RuleEvaluationMetric) {
|
|
640
|
+
RuleEvaluationMetric["ExactMatch"] = "exact_match";
|
|
641
|
+
RuleEvaluationMetric["RegularExpression"] = "regular_expression";
|
|
642
|
+
RuleEvaluationMetric["SchemaValidation"] = "schema_validation";
|
|
643
|
+
RuleEvaluationMetric["LengthCount"] = "length_count";
|
|
644
|
+
RuleEvaluationMetric["LexicalOverlap"] = "lexical_overlap";
|
|
645
|
+
RuleEvaluationMetric["SemanticSimilarity"] = "semantic_similarity";
|
|
646
|
+
RuleEvaluationMetric["NumericSimilarity"] = "numeric_similarity";
|
|
647
|
+
})(RuleEvaluationMetric || (RuleEvaluationMetric = {}));
|
|
648
|
+
const RuleEvaluationSpecification = {
|
|
649
|
+
// prettier-ignore
|
|
650
|
+
metrics: {
|
|
651
|
+
[RuleEvaluationMetric.ExactMatch]: RuleEvaluationExactMatchSpecification,
|
|
652
|
+
[RuleEvaluationMetric.RegularExpression]: RuleEvaluationRegularExpressionSpecification,
|
|
653
|
+
[RuleEvaluationMetric.SchemaValidation]: RuleEvaluationSchemaValidationSpecification,
|
|
654
|
+
[RuleEvaluationMetric.LengthCount]: RuleEvaluationLengthCountSpecification,
|
|
655
|
+
[RuleEvaluationMetric.LexicalOverlap]: RuleEvaluationLexicalOverlapSpecification,
|
|
656
|
+
[RuleEvaluationMetric.SemanticSimilarity]: RuleEvaluationSemanticSimilaritySpecification,
|
|
657
|
+
[RuleEvaluationMetric.NumericSimilarity]: RuleEvaluationNumericSimilaritySpecification,
|
|
658
|
+
},
|
|
206
659
|
};
|
|
207
|
-
Object.freeze(Object.values(AISemanticConventions));
|
|
208
660
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
661
|
+
var EvaluationType;
|
|
662
|
+
(function (EvaluationType) {
|
|
663
|
+
EvaluationType["Rule"] = "rule";
|
|
664
|
+
EvaluationType["Llm"] = "llm";
|
|
665
|
+
EvaluationType["Human"] = "human";
|
|
666
|
+
})(EvaluationType || (EvaluationType = {}));
|
|
667
|
+
const EvaluationTypeSchema = zod.z.nativeEnum(EvaluationType);
|
|
668
|
+
const EvaluationMetricSchema = zod.z.union([
|
|
669
|
+
zod.z.nativeEnum(RuleEvaluationMetric),
|
|
670
|
+
zod.z.nativeEnum(LlmEvaluationMetric),
|
|
671
|
+
zod.z.nativeEnum(HumanEvaluationMetric),
|
|
672
|
+
]);
|
|
673
|
+
const EvaluationConfigurationSchema = zod.z.custom();
|
|
674
|
+
// prettier-ignore
|
|
675
|
+
zod.z.custom();
|
|
676
|
+
// prettier-ignore
|
|
677
|
+
zod.z.custom();
|
|
678
|
+
({
|
|
679
|
+
[EvaluationType.Rule]: RuleEvaluationSpecification,
|
|
680
|
+
[EvaluationType.Llm]: LlmEvaluationSpecification,
|
|
681
|
+
[EvaluationType.Human]: HumanEvaluationSpecification,
|
|
682
|
+
});
|
|
683
|
+
zod.z.object({
|
|
684
|
+
name: zod.z.string(),
|
|
685
|
+
description: zod.z.string(),
|
|
686
|
+
type: EvaluationTypeSchema,
|
|
687
|
+
metric: EvaluationMetricSchema,
|
|
688
|
+
configuration: EvaluationConfigurationSchema,
|
|
689
|
+
});
|
|
690
|
+
zod.z.object({
|
|
691
|
+
evaluateLiveLogs: zod.z.boolean().nullable().optional(),
|
|
692
|
+
enableSuggestions: zod.z.boolean().nullable().optional(),
|
|
693
|
+
autoApplySuggestions: zod.z.boolean().nullable().optional(),
|
|
694
|
+
});
|
|
695
|
+
Object.values(SegmentSource).filter((source) => source !== SegmentSource.Evaluation && source !== SegmentSource.Experiment);
|
|
696
|
+
|
|
697
|
+
var LegacyChainEventTypes;
|
|
698
|
+
(function (LegacyChainEventTypes) {
|
|
699
|
+
LegacyChainEventTypes["Error"] = "chain-error";
|
|
700
|
+
LegacyChainEventTypes["Step"] = "chain-step";
|
|
701
|
+
LegacyChainEventTypes["Complete"] = "chain-complete";
|
|
702
|
+
LegacyChainEventTypes["StepComplete"] = "chain-step-complete";
|
|
703
|
+
})(LegacyChainEventTypes || (LegacyChainEventTypes = {}));
|
|
704
|
+
|
|
705
|
+
var ChainEventTypes;
|
|
706
|
+
(function (ChainEventTypes) {
|
|
707
|
+
ChainEventTypes["ChainStarted"] = "chain-started";
|
|
708
|
+
ChainEventTypes["StepStarted"] = "step-started";
|
|
709
|
+
ChainEventTypes["ProviderStarted"] = "provider-started";
|
|
710
|
+
ChainEventTypes["ProviderCompleted"] = "provider-completed";
|
|
711
|
+
ChainEventTypes["ToolsStarted"] = "tools-started";
|
|
712
|
+
ChainEventTypes["ToolCompleted"] = "tool-completed";
|
|
713
|
+
ChainEventTypes["StepCompleted"] = "step-completed";
|
|
714
|
+
ChainEventTypes["ChainCompleted"] = "chain-completed";
|
|
715
|
+
ChainEventTypes["ChainError"] = "chain-error";
|
|
716
|
+
ChainEventTypes["ToolsRequested"] = "tools-requested";
|
|
717
|
+
ChainEventTypes["IntegrationWakingUp"] = "integration-waking-up";
|
|
718
|
+
})(ChainEventTypes || (ChainEventTypes = {}));
|
|
719
|
+
|
|
720
|
+
var IntegrationType;
|
|
721
|
+
(function (IntegrationType) {
|
|
722
|
+
IntegrationType["Latitude"] = "latitude";
|
|
723
|
+
IntegrationType["ExternalMCP"] = "custom_mcp";
|
|
724
|
+
IntegrationType["HostedMCP"] = "mcp_server";
|
|
725
|
+
})(IntegrationType || (IntegrationType = {}));
|
|
726
|
+
var HostedIntegrationType;
|
|
727
|
+
(function (HostedIntegrationType) {
|
|
728
|
+
HostedIntegrationType["Stripe"] = "stripe";
|
|
729
|
+
HostedIntegrationType["Slack"] = "slack";
|
|
730
|
+
HostedIntegrationType["Github"] = "github";
|
|
731
|
+
HostedIntegrationType["Notion"] = "notion";
|
|
732
|
+
HostedIntegrationType["Twitter"] = "twitter";
|
|
733
|
+
HostedIntegrationType["Airtable"] = "airtable";
|
|
734
|
+
HostedIntegrationType["Linear"] = "linear";
|
|
735
|
+
HostedIntegrationType["YoutubeCaptions"] = "youtube_captions";
|
|
736
|
+
HostedIntegrationType["Reddit"] = "reddit";
|
|
737
|
+
HostedIntegrationType["Telegram"] = "telegram";
|
|
738
|
+
HostedIntegrationType["Tinybird"] = "tinybird";
|
|
739
|
+
HostedIntegrationType["Perplexity"] = "perplexity";
|
|
740
|
+
HostedIntegrationType["AwsKbRetrieval"] = "aws_kb_retrieval";
|
|
741
|
+
HostedIntegrationType["BraveSearch"] = "brave_search";
|
|
742
|
+
HostedIntegrationType["EverArt"] = "ever_art";
|
|
743
|
+
HostedIntegrationType["Fetch"] = "fetch";
|
|
744
|
+
HostedIntegrationType["GitLab"] = "gitlab";
|
|
745
|
+
HostedIntegrationType["GoogleMaps"] = "google_maps";
|
|
746
|
+
HostedIntegrationType["Sentry"] = "sentry";
|
|
747
|
+
HostedIntegrationType["Puppeteer"] = "puppeteer";
|
|
748
|
+
HostedIntegrationType["Time"] = "time";
|
|
749
|
+
HostedIntegrationType["browserbase"] = "browserbase";
|
|
750
|
+
HostedIntegrationType["Neon"] = "neon";
|
|
751
|
+
HostedIntegrationType["Postgres"] = "postgres";
|
|
752
|
+
HostedIntegrationType["Supabase"] = "supabase";
|
|
753
|
+
HostedIntegrationType["Redis"] = "redis";
|
|
754
|
+
HostedIntegrationType["Jira"] = "jira";
|
|
755
|
+
HostedIntegrationType["Attio"] = "attio";
|
|
756
|
+
HostedIntegrationType["Ghost"] = "ghost";
|
|
757
|
+
HostedIntegrationType["Figma"] = "figma";
|
|
758
|
+
HostedIntegrationType["Hyperbrowser"] = "hyperbrowser";
|
|
759
|
+
HostedIntegrationType["Audiense"] = "audiense";
|
|
760
|
+
HostedIntegrationType["Apify"] = "apify";
|
|
761
|
+
HostedIntegrationType["Exa"] = "exa";
|
|
762
|
+
HostedIntegrationType["YepCode"] = "yepcode";
|
|
763
|
+
HostedIntegrationType["Monday"] = "monday";
|
|
764
|
+
HostedIntegrationType["AgentQL"] = "agentql";
|
|
765
|
+
HostedIntegrationType["AgentRPC"] = "agentrpc";
|
|
766
|
+
HostedIntegrationType["AstraDB"] = "astra_db";
|
|
767
|
+
HostedIntegrationType["Bankless"] = "bankless";
|
|
768
|
+
HostedIntegrationType["Bicscan"] = "bicscan";
|
|
769
|
+
HostedIntegrationType["Chargebee"] = "chargebee";
|
|
770
|
+
HostedIntegrationType["Chronulus"] = "chronulus";
|
|
771
|
+
HostedIntegrationType["CircleCI"] = "circleci";
|
|
772
|
+
HostedIntegrationType["Codacy"] = "codacy";
|
|
773
|
+
HostedIntegrationType["CodeLogic"] = "codelogic";
|
|
774
|
+
HostedIntegrationType["Convex"] = "convex";
|
|
775
|
+
HostedIntegrationType["Dart"] = "dart";
|
|
776
|
+
HostedIntegrationType["DevHubCMS"] = "devhub_cms";
|
|
777
|
+
HostedIntegrationType["Elasticsearch"] = "elasticsearch";
|
|
778
|
+
HostedIntegrationType["ESignatures"] = "esignatures";
|
|
779
|
+
HostedIntegrationType["Fewsats"] = "fewsats";
|
|
780
|
+
HostedIntegrationType["Firecrawl"] = "firecrawl";
|
|
781
|
+
HostedIntegrationType["Graphlit"] = "graphlit";
|
|
782
|
+
HostedIntegrationType["Heroku"] = "heroku";
|
|
783
|
+
HostedIntegrationType["IntegrationAppHubspot"] = "integration_app_hubspot";
|
|
784
|
+
HostedIntegrationType["LaraTranslate"] = "lara_translate";
|
|
785
|
+
HostedIntegrationType["Logfire"] = "logfire";
|
|
786
|
+
HostedIntegrationType["Langfuse"] = "langfuse";
|
|
787
|
+
HostedIntegrationType["LingoSupabase"] = "lingo_supabase";
|
|
788
|
+
HostedIntegrationType["Make"] = "make";
|
|
789
|
+
HostedIntegrationType["Meilisearch"] = "meilisearch";
|
|
790
|
+
HostedIntegrationType["Momento"] = "momento";
|
|
791
|
+
HostedIntegrationType["Neo4jAura"] = "neo4j_aura";
|
|
792
|
+
HostedIntegrationType["Octagon"] = "octagon";
|
|
793
|
+
HostedIntegrationType["Paddle"] = "paddle";
|
|
794
|
+
HostedIntegrationType["PayPal"] = "paypal";
|
|
795
|
+
HostedIntegrationType["Qdrant"] = "qdrant";
|
|
796
|
+
HostedIntegrationType["Raygun"] = "raygun";
|
|
797
|
+
HostedIntegrationType["Rember"] = "rember";
|
|
798
|
+
HostedIntegrationType["Riza"] = "riza";
|
|
799
|
+
HostedIntegrationType["Search1API"] = "search1api";
|
|
800
|
+
HostedIntegrationType["Semgrep"] = "semgrep";
|
|
801
|
+
HostedIntegrationType["Tavily"] = "tavily";
|
|
802
|
+
HostedIntegrationType["Unstructured"] = "unstructured";
|
|
803
|
+
HostedIntegrationType["Vectorize"] = "vectorize";
|
|
804
|
+
HostedIntegrationType["Xero"] = "xero";
|
|
805
|
+
HostedIntegrationType["Readwise"] = "readwise";
|
|
806
|
+
HostedIntegrationType["Airbnb"] = "airbnb";
|
|
807
|
+
HostedIntegrationType["Mintlify"] = "mintlify";
|
|
808
|
+
// Require all auth file :point_down:
|
|
809
|
+
// Gmail = 'google_drive',
|
|
810
|
+
// GoogleCalendar = 'google_drive',
|
|
811
|
+
// GoogleDrive = 'google_drive',
|
|
812
|
+
// GoogleWorkspace = 'google_workspace', // env vars not supported (?)
|
|
813
|
+
// TODO: implement these
|
|
814
|
+
// Wordpress = 'wordpress', // Not on OpenTools
|
|
815
|
+
// Discord = 'discord', // Not on OpenTools
|
|
816
|
+
// Intercom = 'intercom', // Not on OpenTools
|
|
817
|
+
// Hubspot = 'hubspot', // Docker based
|
|
818
|
+
// Loops = 'loops', // Does not exist
|
|
819
|
+
})(HostedIntegrationType || (HostedIntegrationType = {}));
|
|
820
|
+
|
|
821
|
+
// TODO(evalsv2): Remove
|
|
822
|
+
var EvaluationResultableType;
|
|
823
|
+
(function (EvaluationResultableType) {
|
|
824
|
+
EvaluationResultableType["Boolean"] = "evaluation_resultable_booleans";
|
|
825
|
+
EvaluationResultableType["Text"] = "evaluation_resultable_texts";
|
|
826
|
+
EvaluationResultableType["Number"] = "evaluation_resultable_numbers";
|
|
827
|
+
})(EvaluationResultableType || (EvaluationResultableType = {}));
|
|
828
|
+
|
|
829
|
+
var ModifiedDocumentType;
|
|
830
|
+
(function (ModifiedDocumentType) {
|
|
831
|
+
ModifiedDocumentType["Created"] = "created";
|
|
832
|
+
ModifiedDocumentType["Updated"] = "updated";
|
|
833
|
+
ModifiedDocumentType["UpdatedPath"] = "updated_path";
|
|
834
|
+
ModifiedDocumentType["Deleted"] = "deleted";
|
|
835
|
+
})(ModifiedDocumentType || (ModifiedDocumentType = {}));
|
|
836
|
+
|
|
837
|
+
// TODO(tracing): deprecated
|
|
838
|
+
const HEAD_COMMIT = 'live';
|
|
839
|
+
var Providers;
|
|
840
|
+
(function (Providers) {
|
|
841
|
+
Providers["OpenAI"] = "openai";
|
|
842
|
+
Providers["Anthropic"] = "anthropic";
|
|
843
|
+
Providers["Groq"] = "groq";
|
|
844
|
+
Providers["Mistral"] = "mistral";
|
|
845
|
+
Providers["Azure"] = "azure";
|
|
846
|
+
Providers["Google"] = "google";
|
|
847
|
+
Providers["GoogleVertex"] = "google_vertex";
|
|
848
|
+
Providers["AnthropicVertex"] = "anthropic_vertex";
|
|
849
|
+
Providers["Custom"] = "custom";
|
|
850
|
+
Providers["XAI"] = "xai";
|
|
851
|
+
Providers["AmazonBedrock"] = "amazon_bedrock";
|
|
852
|
+
Providers["DeepSeek"] = "deepseek";
|
|
853
|
+
Providers["Perplexity"] = "perplexity";
|
|
854
|
+
})(Providers || (Providers = {}));
|
|
855
|
+
var DocumentType;
|
|
856
|
+
(function (DocumentType) {
|
|
857
|
+
DocumentType["Prompt"] = "prompt";
|
|
858
|
+
DocumentType["Agent"] = "agent";
|
|
859
|
+
})(DocumentType || (DocumentType = {}));
|
|
860
|
+
var DocumentTriggerType;
|
|
861
|
+
(function (DocumentTriggerType) {
|
|
862
|
+
DocumentTriggerType["Email"] = "email";
|
|
863
|
+
DocumentTriggerType["Scheduled"] = "scheduled";
|
|
864
|
+
})(DocumentTriggerType || (DocumentTriggerType = {}));
|
|
865
|
+
var DocumentTriggerParameters;
|
|
866
|
+
(function (DocumentTriggerParameters) {
|
|
867
|
+
DocumentTriggerParameters["SenderEmail"] = "senderEmail";
|
|
868
|
+
DocumentTriggerParameters["SenderName"] = "senderName";
|
|
869
|
+
DocumentTriggerParameters["Subject"] = "subject";
|
|
870
|
+
DocumentTriggerParameters["Body"] = "body";
|
|
871
|
+
DocumentTriggerParameters["Attachments"] = "attachments";
|
|
872
|
+
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
873
|
+
|
|
874
|
+
class ManualInstrumentation {
|
|
875
|
+
enabled;
|
|
876
|
+
source;
|
|
877
|
+
tracer;
|
|
878
|
+
constructor(source, tracer) {
|
|
879
|
+
this.enabled = false;
|
|
880
|
+
this.source = source;
|
|
881
|
+
this.tracer = tracer;
|
|
216
882
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
onEnd(span) {
|
|
220
|
-
if (!shouldProcess(span))
|
|
221
|
-
return;
|
|
222
|
-
if (shouldConvertToLatitudeFormat(span))
|
|
223
|
-
convertToLatitudeFormat(span);
|
|
224
|
-
super.onEnd(span);
|
|
883
|
+
isEnabled() {
|
|
884
|
+
return this.enabled;
|
|
225
885
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return (Object.keys(span.attributes).some((k) => k.startsWith('latitude.')) ||
|
|
229
|
-
Object.keys(span.attributes).some((k) => k.startsWith('ai.')));
|
|
230
|
-
}
|
|
231
|
-
function shouldConvertToLatitudeFormat(span) {
|
|
232
|
-
return Object.keys(span.attributes).some((k) => k.startsWith('ai.'));
|
|
233
|
-
}
|
|
234
|
-
function convertToLatitudeFormat(span) {
|
|
235
|
-
try {
|
|
236
|
-
const computedAttrs = computeOpenLLMAttributes(span);
|
|
237
|
-
if (computedAttrs) {
|
|
238
|
-
;
|
|
239
|
-
span.attributes = {
|
|
240
|
-
...span.attributes,
|
|
241
|
-
...computedAttrs,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
886
|
+
enable() {
|
|
887
|
+
this.enabled = true;
|
|
244
888
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// do nothing
|
|
889
|
+
disable() {
|
|
890
|
+
this.enabled = false;
|
|
248
891
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const result = {};
|
|
253
|
-
// Extract model information
|
|
254
|
-
if (attrs[AISemanticConventions.MODEL_ID]) {
|
|
255
|
-
result['gen_ai.request.model'] = String(attrs[AISemanticConventions.MODEL_ID]);
|
|
256
|
-
result['gen_ai.response.model'] = String(attrs[AISemanticConventions.MODEL_ID]);
|
|
257
|
-
}
|
|
258
|
-
// Extract settings
|
|
259
|
-
try {
|
|
260
|
-
const settings = attrs[AISemanticConventions.SETTINGS]
|
|
261
|
-
? JSON.parse(String(attrs[AISemanticConventions.SETTINGS]))
|
|
262
|
-
: {};
|
|
263
|
-
if (settings) {
|
|
264
|
-
// Add max tokens if present
|
|
265
|
-
if (settings.maxTokens) {
|
|
266
|
-
result['gen_ai.request.max_tokens'] = settings.maxTokens;
|
|
267
|
-
}
|
|
268
|
-
if (!attrs['gen_ai.system'] && settings.provider) {
|
|
269
|
-
result['gen_ai.system'] = String(settings.provider);
|
|
270
|
-
}
|
|
892
|
+
baggage(ctx) {
|
|
893
|
+
if ('traceparent' in ctx) {
|
|
894
|
+
ctx = otel.propagation.extract(otel__namespace.ROOT_CONTEXT, ctx);
|
|
271
895
|
}
|
|
896
|
+
const baggage = Object.fromEntries(otel.propagation.getBaggage(ctx)?.getAllEntries() || []);
|
|
897
|
+
if (!(ATTR_LATITUDE_SEGMENT_ID in baggage) ||
|
|
898
|
+
!(ATTR_LATITUDE_SEGMENTS in baggage)) {
|
|
899
|
+
return undefined;
|
|
900
|
+
}
|
|
901
|
+
const segment = {
|
|
902
|
+
id: baggage[ATTR_LATITUDE_SEGMENT_ID].value,
|
|
903
|
+
parentId: baggage[ATTR_LATITUDE_SEGMENT_PARENT_ID]?.value,
|
|
904
|
+
};
|
|
905
|
+
let segments = [];
|
|
906
|
+
try {
|
|
907
|
+
segments = JSON.parse(baggage[ATTR_LATITUDE_SEGMENTS].value);
|
|
908
|
+
}
|
|
909
|
+
catch (error) {
|
|
910
|
+
return undefined;
|
|
911
|
+
}
|
|
912
|
+
if (segments.length < 1) {
|
|
913
|
+
return undefined;
|
|
914
|
+
}
|
|
915
|
+
return { segment, segments };
|
|
272
916
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
917
|
+
setBaggage(ctx, baggage, extra) {
|
|
918
|
+
let parent = Object.fromEntries(otel.propagation.getBaggage(ctx)?.getAllEntries() || []);
|
|
919
|
+
parent = Object.fromEntries(Object.entries(parent).filter(([attribute]) => attribute !== ATTR_LATITUDE_SEGMENT_ID &&
|
|
920
|
+
attribute !== ATTR_LATITUDE_SEGMENT_PARENT_ID &&
|
|
921
|
+
attribute !== ATTR_LATITUDE_SEGMENTS));
|
|
922
|
+
if (!baggage) {
|
|
923
|
+
const payload = otel.propagation.createBaggage({ ...parent, ...(extra || {}) });
|
|
924
|
+
return otel.propagation.setBaggage(ctx, payload);
|
|
925
|
+
}
|
|
926
|
+
let jsonSegments = '';
|
|
927
|
+
try {
|
|
928
|
+
jsonSegments = JSON.stringify(baggage.segments);
|
|
929
|
+
}
|
|
930
|
+
catch (error) {
|
|
931
|
+
jsonSegments = '[]';
|
|
932
|
+
}
|
|
933
|
+
const payload = otel.propagation.createBaggage({
|
|
934
|
+
...parent,
|
|
935
|
+
[ATTR_LATITUDE_SEGMENT_ID]: { value: baggage.segment.id },
|
|
936
|
+
...(baggage.segment.parentId && {
|
|
937
|
+
[ATTR_LATITUDE_SEGMENT_PARENT_ID]: { value: baggage.segment.parentId },
|
|
938
|
+
}),
|
|
939
|
+
[ATTR_LATITUDE_SEGMENTS]: { value: jsonSegments },
|
|
940
|
+
...(extra || {}),
|
|
290
941
|
});
|
|
942
|
+
return otel.propagation.setBaggage(ctx, payload);
|
|
291
943
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
944
|
+
pause(ctx) {
|
|
945
|
+
const baggage = this.baggage(ctx);
|
|
946
|
+
if (baggage) {
|
|
947
|
+
baggage.segments.at(-1).paused = true;
|
|
948
|
+
}
|
|
949
|
+
ctx = this.setBaggage(ctx, baggage);
|
|
950
|
+
let carrier = {};
|
|
951
|
+
otel.propagation.inject(ctx, carrier);
|
|
952
|
+
return carrier;
|
|
295
953
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const responseObject = attrs['ai.response.object'];
|
|
299
|
-
const responseToolCalls = attrs['ai.response.toolCalls'];
|
|
300
|
-
if (responseText) {
|
|
301
|
-
result[`gen_ai.completion.0.role`] = 'assistant';
|
|
302
|
-
result[`gen_ai.completion.0.content`] = String(responseText);
|
|
954
|
+
resume(ctx) {
|
|
955
|
+
return otel.propagation.extract(otel__namespace.ROOT_CONTEXT, ctx);
|
|
303
956
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (toolCalls.length > 0) {
|
|
308
|
-
result['gen_ai.completion.0.finish_reason'] = 'tool_calls';
|
|
309
|
-
result[`gen_ai.completion.0.role`] = 'assistant';
|
|
310
|
-
toolCalls.forEach((toolCall, toolCallIndex) => {
|
|
311
|
-
result[`gen_ai.completion.0.tool_calls.${toolCallIndex}.id`] =
|
|
312
|
-
toolCall.toolCallId;
|
|
313
|
-
result[`gen_ai.completion.0.tool_calls.${toolCallIndex}.name`] =
|
|
314
|
-
toolCall.toolName;
|
|
315
|
-
result[`gen_ai.completion.0.tool_calls.${toolCallIndex}.arguments`] =
|
|
316
|
-
toolCall.args;
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
catch (e) {
|
|
321
|
-
console.error('Error parsing tool calls', e);
|
|
322
|
-
}
|
|
957
|
+
restored(ctx) {
|
|
958
|
+
const baggage = this.baggage(ctx);
|
|
959
|
+
return !baggage?.segments.some((segment) => segment.paused);
|
|
323
960
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
961
|
+
restore(ctx) {
|
|
962
|
+
let baggage = this.baggage(ctx);
|
|
963
|
+
if (!baggage)
|
|
964
|
+
return ctx;
|
|
965
|
+
const segments = baggage.segments;
|
|
966
|
+
while (segments.at(-1)?.paused)
|
|
967
|
+
segments.pop();
|
|
968
|
+
const segment = segments.at(-1);
|
|
969
|
+
if (!segment)
|
|
970
|
+
return otel__namespace.ROOT_CONTEXT;
|
|
971
|
+
baggage = {
|
|
972
|
+
segment: { id: segment.id, parentId: segment.parentId },
|
|
973
|
+
segments: segments,
|
|
974
|
+
};
|
|
975
|
+
ctx = this.setBaggage(ctx, baggage);
|
|
976
|
+
let carrier = {};
|
|
977
|
+
otel.propagation.inject(ctx, carrier);
|
|
978
|
+
carrier.traceparent = segment.traceparent;
|
|
979
|
+
carrier.tracestate = segment.tracestate;
|
|
980
|
+
return this.resume(carrier);
|
|
327
981
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
result['gen_ai.usage.completion_tokens'] = completionTokens;
|
|
982
|
+
capitalize(str) {
|
|
983
|
+
if (str.length === 0)
|
|
984
|
+
return str;
|
|
985
|
+
return str.charAt(0).toUpperCase() + str.toLowerCase().slice(1);
|
|
333
986
|
}
|
|
334
|
-
|
|
335
|
-
|
|
987
|
+
toCamelCase(str) {
|
|
988
|
+
return str
|
|
989
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
990
|
+
.replace(/[^A-Za-z0-9]+/g, ' ')
|
|
991
|
+
.trim()
|
|
992
|
+
.split(' ')
|
|
993
|
+
.map((w, i) => (i ? this.capitalize(w) : w.toLowerCase()))
|
|
994
|
+
.join('');
|
|
336
995
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
996
|
+
toSnakeCase(str) {
|
|
997
|
+
return str
|
|
998
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
999
|
+
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
1000
|
+
.replace(/_+/g, '_')
|
|
1001
|
+
.replace(/^_+|_+$/g, '')
|
|
1002
|
+
.toLowerCase();
|
|
340
1003
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// @ts-ignore
|
|
357
|
-
openAIInstrumentation.manuallyInstrument(modules.openAI);
|
|
358
|
-
instrumentations.push(openAIInstrumentation);
|
|
359
|
-
}
|
|
360
|
-
if (modules?.anthropic) {
|
|
361
|
-
const anthropicInstrumentation = new instrumentationAnthropic.AnthropicInstrumentation();
|
|
362
|
-
anthropicInstrumentation.manuallyInstrument(modules.anthropic);
|
|
363
|
-
instrumentations.push(new instrumentationAnthropic.AnthropicInstrumentation());
|
|
364
|
-
}
|
|
365
|
-
if (modules?.azureOpenAI) {
|
|
366
|
-
const azureOpenAIInstrumentation = new instrumentationAzure.AzureOpenAIInstrumentation();
|
|
367
|
-
azureOpenAIInstrumentation.manuallyInstrument(modules.azureOpenAI);
|
|
368
|
-
instrumentations.push(azureOpenAIInstrumentation);
|
|
369
|
-
}
|
|
370
|
-
if (modules?.cohere) {
|
|
371
|
-
const cohereInstrumentation = new instrumentationCohere.CohereInstrumentation();
|
|
372
|
-
cohereInstrumentation.manuallyInstrument(modules.cohere);
|
|
373
|
-
instrumentations.push(cohereInstrumentation);
|
|
374
|
-
}
|
|
375
|
-
if (modules?.google_vertexai) {
|
|
376
|
-
const vertexAIInstrumentation = new instrumentationVertexai.VertexAIInstrumentation();
|
|
377
|
-
vertexAIInstrumentation.manuallyInstrument(modules.google_vertexai);
|
|
378
|
-
instrumentations.push(vertexAIInstrumentation);
|
|
379
|
-
}
|
|
380
|
-
if (modules?.google_aiplatform) {
|
|
381
|
-
const aiplatformInstrumentation = new instrumentationVertexai.AIPlatformInstrumentation();
|
|
382
|
-
aiplatformInstrumentation.manuallyInstrument(modules.google_aiplatform);
|
|
383
|
-
instrumentations.push(aiplatformInstrumentation);
|
|
384
|
-
}
|
|
385
|
-
if (modules?.bedrock) {
|
|
386
|
-
const bedrockInstrumentation = new instrumentationBedrock.BedrockInstrumentation();
|
|
387
|
-
bedrockInstrumentation.manuallyInstrument(modules.bedrock);
|
|
388
|
-
instrumentations.push(bedrockInstrumentation);
|
|
389
|
-
}
|
|
390
|
-
// TODO: Enable these once we have manually tested them
|
|
391
|
-
//if (modules?.langchain) {
|
|
392
|
-
// const langchainInstrumentation = new LangChainInstrumentation()
|
|
393
|
-
// langchainInstrumentation.manuallyInstrument(modules.langchain!)
|
|
394
|
-
// instrumentations.push(langchainInstrumentation)
|
|
395
|
-
//}
|
|
396
|
-
//
|
|
397
|
-
//if (modules?.llamaIndex) {
|
|
398
|
-
// const llamaindexInstrumentation = new LlamaIndexInstrumentation()
|
|
399
|
-
// llamaindexInstrumentation.manuallyInstrument(modules.llamaIndex!)
|
|
400
|
-
// instrumentations.push(llamaindexInstrumentation)
|
|
401
|
-
//}
|
|
402
|
-
//if (modules?.pinecone) {
|
|
403
|
-
// const pineconeInstrumentation = new PineconeInstrumentation()
|
|
404
|
-
// pineconeInstrumentation.manuallyInstrument(modules.pinecone!)
|
|
405
|
-
// instrumentations.push(pineconeInstrumentation)
|
|
406
|
-
//}
|
|
407
|
-
//if (modules?.chromadb) {
|
|
408
|
-
// const chromadbInstrumentation = new ChromaDBInstrumentation()
|
|
409
|
-
// chromadbInstrumentation.manuallyInstrument(modules.chromadb!)
|
|
410
|
-
// instrumentations.push(chromadbInstrumentation)
|
|
411
|
-
//}
|
|
412
|
-
//if (modules?.qdrant) {
|
|
413
|
-
// const qdrantInstrumentation = new QdrantInstrumentation()
|
|
414
|
-
// qdrantInstrumentation.manuallyInstrument(modules.qdrant!)
|
|
415
|
-
// instrumentations.push(qdrantInstrumentation)
|
|
416
|
-
//}
|
|
417
|
-
if (!instrumentations.length && !options?.processors?.length) {
|
|
418
|
-
console.warn('Latitude: No instrumentations or processors to initialize');
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
const processors = options?.disableBatch
|
|
422
|
-
? [
|
|
423
|
-
new sdkTraceNode.SimpleSpanProcessor(this.exporter),
|
|
424
|
-
...(options?.processors?.map((processor) => new processor(this.exporter)) || []),
|
|
425
|
-
]
|
|
426
|
-
: [
|
|
427
|
-
new sdkTraceNode.BatchSpanProcessor(this.exporter),
|
|
428
|
-
...(options?.processors?.map((processor) => new processor(this.exporter)) || []),
|
|
429
|
-
];
|
|
430
|
-
const sdk = new sdkNode.NodeSDK({
|
|
431
|
-
resource: new resources.Resource({
|
|
432
|
-
'service.name': process.env.npm_package_name,
|
|
433
|
-
}),
|
|
434
|
-
instrumentations,
|
|
435
|
-
traceExporter: this.exporter,
|
|
436
|
-
// @ts-ignore
|
|
437
|
-
spanProcessors: processors,
|
|
1004
|
+
toKebabCase(input) {
|
|
1005
|
+
return input
|
|
1006
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
1007
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
1008
|
+
.replace(/-+/g, '-')
|
|
1009
|
+
.replace(/^-+|-+$/g, '')
|
|
1010
|
+
.toLowerCase();
|
|
1011
|
+
}
|
|
1012
|
+
error(span, error, options) {
|
|
1013
|
+
options = options || {};
|
|
1014
|
+
span.recordException(error);
|
|
1015
|
+
span.setAttributes(options.attributes || {});
|
|
1016
|
+
span.setStatus({
|
|
1017
|
+
code: otel__namespace.SpanStatusCode.ERROR,
|
|
1018
|
+
message: error.message || undefined,
|
|
438
1019
|
});
|
|
439
|
-
|
|
1020
|
+
span.end();
|
|
440
1021
|
}
|
|
441
|
-
span(
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
1022
|
+
span(ctx, name, type, options) {
|
|
1023
|
+
if (!this.enabled) {
|
|
1024
|
+
return {
|
|
1025
|
+
context: ctx,
|
|
1026
|
+
end: (_options) => { },
|
|
1027
|
+
fail: (_error, _options) => { },
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
const start = options || {};
|
|
1031
|
+
let operation = undefined;
|
|
1032
|
+
if (GENAI_SPANS.includes(type)) {
|
|
1033
|
+
operation = type;
|
|
1034
|
+
}
|
|
1035
|
+
const span = this.tracer.startSpan(name, {
|
|
1036
|
+
attributes: {
|
|
1037
|
+
[ATTR_LATITUDE_TYPE]: type,
|
|
1038
|
+
...(operation && {
|
|
1039
|
+
[incubating.ATTR_GEN_AI_OPERATION_NAME]: operation,
|
|
1040
|
+
}),
|
|
1041
|
+
...(start.attributes || {}),
|
|
1042
|
+
},
|
|
1043
|
+
kind: otel__namespace.SpanKind.CLIENT,
|
|
1044
|
+
}, ctx);
|
|
1045
|
+
const newCtx = otel.trace.setSpan(ctx, span);
|
|
1046
|
+
return {
|
|
1047
|
+
context: newCtx,
|
|
1048
|
+
end: (options) => {
|
|
1049
|
+
const end = options || {};
|
|
1050
|
+
span.setAttributes(end.attributes || {});
|
|
1051
|
+
span.setStatus({ code: otel__namespace.SpanStatusCode.OK });
|
|
1052
|
+
span.end();
|
|
1053
|
+
},
|
|
1054
|
+
fail: (error, options) => {
|
|
1055
|
+
this.error(span, error, options);
|
|
1056
|
+
},
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
tool(ctx, options) {
|
|
1060
|
+
const start = options;
|
|
1061
|
+
let jsonArguments = '';
|
|
1062
|
+
try {
|
|
1063
|
+
jsonArguments = JSON.stringify(start.call.arguments);
|
|
1064
|
+
}
|
|
1065
|
+
catch (error) {
|
|
1066
|
+
jsonArguments = '{}';
|
|
1067
|
+
}
|
|
1068
|
+
const span = this.span(ctx, start.name, SpanType.Tool, {
|
|
1069
|
+
attributes: {
|
|
1070
|
+
[incubating.ATTR_GEN_AI_TOOL_NAME]: start.name,
|
|
1071
|
+
[incubating.ATTR_GEN_AI_TOOL_TYPE]: GEN_AI_TOOL_TYPE_VALUE_FUNCTION,
|
|
1072
|
+
[incubating.ATTR_GEN_AI_TOOL_CALL_ID]: start.call.id,
|
|
1073
|
+
[ATTR_GEN_AI_TOOL_CALL_ARGUMENTS]: jsonArguments,
|
|
1074
|
+
...(start.attributes || {}),
|
|
1075
|
+
},
|
|
1076
|
+
});
|
|
1077
|
+
return {
|
|
1078
|
+
context: span.context,
|
|
1079
|
+
end: (options) => {
|
|
1080
|
+
const end = options;
|
|
1081
|
+
let stringResult = '';
|
|
1082
|
+
if (typeof end.result.value !== 'string') {
|
|
448
1083
|
try {
|
|
449
|
-
|
|
1084
|
+
stringResult = JSON.stringify(end.result.value);
|
|
450
1085
|
}
|
|
451
|
-
catch (
|
|
452
|
-
|
|
1086
|
+
catch (error) {
|
|
1087
|
+
stringResult = '{}';
|
|
453
1088
|
}
|
|
454
1089
|
}
|
|
455
|
-
|
|
456
|
-
|
|
1090
|
+
else {
|
|
1091
|
+
stringResult = end.result.value;
|
|
457
1092
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
1093
|
+
span.end({
|
|
1094
|
+
attributes: {
|
|
1095
|
+
[ATTR_GEN_AI_TOOL_RESULT_VALUE]: stringResult,
|
|
1096
|
+
[ATTR_GEN_AI_TOOL_RESULT_IS_ERROR]: end.result.isError,
|
|
1097
|
+
...(end.attributes || {}),
|
|
1098
|
+
},
|
|
1099
|
+
});
|
|
1100
|
+
},
|
|
1101
|
+
fail: span.fail,
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
attribifyMessageToolCalls(prefix, toolCalls) {
|
|
1105
|
+
const attributes = {};
|
|
1106
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
1107
|
+
for (const key in toolCalls[i]) {
|
|
1108
|
+
const field = this.toCamelCase(key);
|
|
1109
|
+
let value = toolCalls[i][key];
|
|
1110
|
+
if (value === null || value === undefined)
|
|
1111
|
+
continue;
|
|
1112
|
+
switch (field) {
|
|
1113
|
+
case 'id':
|
|
1114
|
+
case 'toolCallId':
|
|
1115
|
+
case 'toolUseId': {
|
|
1116
|
+
if (typeof value !== 'string')
|
|
1117
|
+
continue;
|
|
1118
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID}`] = value;
|
|
1119
|
+
break;
|
|
1120
|
+
}
|
|
1121
|
+
case 'name':
|
|
1122
|
+
case 'toolName': {
|
|
1123
|
+
if (typeof value !== 'string')
|
|
1124
|
+
continue;
|
|
1125
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value;
|
|
1126
|
+
break;
|
|
461
1127
|
}
|
|
462
|
-
|
|
463
|
-
|
|
1128
|
+
case 'arguments':
|
|
1129
|
+
case 'toolArguments':
|
|
1130
|
+
case 'input': {
|
|
1131
|
+
if (typeof value === 'string') {
|
|
1132
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value;
|
|
1133
|
+
}
|
|
1134
|
+
else {
|
|
1135
|
+
try {
|
|
1136
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = JSON.stringify(value);
|
|
1137
|
+
}
|
|
1138
|
+
catch (error) {
|
|
1139
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = '{}';
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
break;
|
|
464
1143
|
}
|
|
1144
|
+
/* OpenAI function calls */
|
|
1145
|
+
case 'function': {
|
|
1146
|
+
if (typeof value !== 'object')
|
|
1147
|
+
continue;
|
|
1148
|
+
if (!('name' in value))
|
|
1149
|
+
continue;
|
|
1150
|
+
if (typeof value.name !== 'string')
|
|
1151
|
+
continue;
|
|
1152
|
+
if (!('arguments' in value))
|
|
1153
|
+
continue;
|
|
1154
|
+
if (typeof value.arguments !== 'string')
|
|
1155
|
+
continue;
|
|
1156
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value.name;
|
|
1157
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value.arguments;
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return attributes;
|
|
1164
|
+
}
|
|
1165
|
+
attribifyMessageContent(prefix, content) {
|
|
1166
|
+
let attributes = {};
|
|
1167
|
+
if (typeof content === 'string') {
|
|
1168
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
|
|
1169
|
+
return attributes;
|
|
1170
|
+
}
|
|
1171
|
+
try {
|
|
1172
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] =
|
|
1173
|
+
JSON.stringify(content);
|
|
1174
|
+
}
|
|
1175
|
+
catch (error) {
|
|
1176
|
+
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = '[]';
|
|
1177
|
+
}
|
|
1178
|
+
if (!Array.isArray(content))
|
|
1179
|
+
return attributes;
|
|
1180
|
+
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1181
|
+
const toolCalls = [];
|
|
1182
|
+
for (const item of content) {
|
|
1183
|
+
for (const key in item) {
|
|
1184
|
+
if (this.toCamelCase(key) !== 'type')
|
|
1185
|
+
continue;
|
|
1186
|
+
if (typeof item[key] !== 'string')
|
|
1187
|
+
continue;
|
|
1188
|
+
if (item[key] !== 'tool-call' && item[key] !== 'tool_use')
|
|
1189
|
+
continue;
|
|
1190
|
+
toolCalls.push(item);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (toolCalls.length > 0) {
|
|
1194
|
+
attributes = {
|
|
1195
|
+
...attributes,
|
|
1196
|
+
...this.attribifyMessageToolCalls(prefix, toolCalls),
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
return attributes;
|
|
1200
|
+
}
|
|
1201
|
+
attribifyMessages(direction, messages) {
|
|
1202
|
+
const prefix = direction === 'input' ? ATTR_GEN_AI_PROMPTS : ATTR_GEN_AI_COMPLETIONS;
|
|
1203
|
+
let attributes = {};
|
|
1204
|
+
for (let i = 0; i < messages.length; i++) {
|
|
1205
|
+
for (const key in messages[i]) {
|
|
1206
|
+
const field = this.toCamelCase(key);
|
|
1207
|
+
let value = messages[i][key];
|
|
1208
|
+
if (value === null || value === undefined)
|
|
1209
|
+
continue;
|
|
1210
|
+
switch (field) {
|
|
1211
|
+
case 'role': {
|
|
1212
|
+
if (typeof value !== 'string')
|
|
1213
|
+
continue;
|
|
1214
|
+
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_ROLE}`] = value;
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1218
|
+
case 'content': {
|
|
1219
|
+
attributes = {
|
|
1220
|
+
...attributes,
|
|
1221
|
+
...this.attribifyMessageContent(`${prefix}.${i}`, value),
|
|
1222
|
+
};
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1225
|
+
/* Tool calls for OpenAI */
|
|
1226
|
+
case 'toolCalls': {
|
|
1227
|
+
if (!Array.isArray(value))
|
|
1228
|
+
continue;
|
|
1229
|
+
attributes = {
|
|
1230
|
+
...attributes,
|
|
1231
|
+
...this.attribifyMessageToolCalls(`${prefix}.${i}`, value),
|
|
1232
|
+
};
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
/* Tool result for OpenAI / Anthropic / PromptL */
|
|
1236
|
+
case 'toolCallId':
|
|
1237
|
+
case 'toolId':
|
|
1238
|
+
case 'toolUseId': {
|
|
1239
|
+
if (typeof value !== 'string')
|
|
1240
|
+
continue;
|
|
1241
|
+
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID}`] =
|
|
1242
|
+
value;
|
|
1243
|
+
break;
|
|
1244
|
+
}
|
|
1245
|
+
case 'toolName': {
|
|
1246
|
+
if (typeof value !== 'string')
|
|
1247
|
+
continue;
|
|
1248
|
+
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_NAME}`] =
|
|
1249
|
+
value;
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
// Note: 'toolResult' is 'content' itself
|
|
1253
|
+
case 'isError': {
|
|
1254
|
+
if (typeof value !== 'boolean')
|
|
1255
|
+
continue;
|
|
1256
|
+
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR}`] = value;
|
|
1257
|
+
break;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
return attributes;
|
|
1263
|
+
}
|
|
1264
|
+
attribifyConfiguration(direction, configuration) {
|
|
1265
|
+
const prefix = direction === 'input' ? ATTR_GEN_AI_REQUEST : ATTR_GEN_AI_RESPONSE;
|
|
1266
|
+
const attributes = {};
|
|
1267
|
+
for (const key in configuration) {
|
|
1268
|
+
const field = this.toSnakeCase(key);
|
|
1269
|
+
let value = configuration[key];
|
|
1270
|
+
if (value === null || value === undefined)
|
|
1271
|
+
continue;
|
|
1272
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
1273
|
+
try {
|
|
1274
|
+
value = JSON.stringify(value);
|
|
1275
|
+
}
|
|
1276
|
+
catch (error) {
|
|
1277
|
+
value = '{}';
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
attributes[`${prefix}.${field}`] = value;
|
|
1281
|
+
}
|
|
1282
|
+
return attributes;
|
|
1283
|
+
}
|
|
1284
|
+
completion(ctx, options) {
|
|
1285
|
+
const start = options;
|
|
1286
|
+
const configuration = {
|
|
1287
|
+
...start.configuration,
|
|
1288
|
+
model: start.model,
|
|
1289
|
+
};
|
|
1290
|
+
let jsonConfiguration = '';
|
|
1291
|
+
try {
|
|
1292
|
+
jsonConfiguration = JSON.stringify(configuration);
|
|
1293
|
+
}
|
|
1294
|
+
catch (error) {
|
|
1295
|
+
jsonConfiguration = '{}';
|
|
1296
|
+
}
|
|
1297
|
+
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1298
|
+
let jsonInput = '';
|
|
1299
|
+
try {
|
|
1300
|
+
jsonInput = JSON.stringify(start.input);
|
|
1301
|
+
}
|
|
1302
|
+
catch (error) {
|
|
1303
|
+
jsonInput = '[]';
|
|
1304
|
+
}
|
|
1305
|
+
const attrInput = this.attribifyMessages('input', start.input);
|
|
1306
|
+
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1307
|
+
attributes: {
|
|
1308
|
+
[incubating.ATTR_GEN_AI_SYSTEM]: start.provider,
|
|
1309
|
+
[ATTR_GEN_AI_REQUEST_CONFIGURATION]: jsonConfiguration,
|
|
1310
|
+
...attrConfiguration,
|
|
1311
|
+
[ATTR_GEN_AI_REQUEST_MESSAGES]: jsonInput,
|
|
1312
|
+
...attrInput,
|
|
1313
|
+
...(start.attributes || {}),
|
|
1314
|
+
},
|
|
1315
|
+
});
|
|
1316
|
+
return {
|
|
1317
|
+
context: span.context,
|
|
1318
|
+
end: (options) => {
|
|
1319
|
+
const end = options;
|
|
1320
|
+
let jsonOutput = '';
|
|
1321
|
+
try {
|
|
1322
|
+
jsonOutput = JSON.stringify(end.output);
|
|
1323
|
+
}
|
|
1324
|
+
catch (error) {
|
|
1325
|
+
jsonOutput = '[]';
|
|
465
1326
|
}
|
|
1327
|
+
const attrOutput = this.attribifyMessages('output', end.output);
|
|
1328
|
+
const inputTokens = end.tokens.prompt + end.tokens.cached;
|
|
1329
|
+
const outputTokens = end.tokens.reasoning + end.tokens.completion;
|
|
1330
|
+
span.end({
|
|
1331
|
+
attributes: {
|
|
1332
|
+
[ATTR_GEN_AI_RESPONSE_MESSAGES]: jsonOutput,
|
|
1333
|
+
...attrOutput,
|
|
1334
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: inputTokens,
|
|
1335
|
+
[ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: end.tokens.prompt,
|
|
1336
|
+
[ATTR_GEN_AI_USAGE_CACHED_TOKENS]: end.tokens.cached,
|
|
1337
|
+
[ATTR_GEN_AI_USAGE_REASONING_TOKENS]: end.tokens.reasoning,
|
|
1338
|
+
[ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: end.tokens.completion,
|
|
1339
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: outputTokens,
|
|
1340
|
+
[incubating.ATTR_GEN_AI_RESPONSE_MODEL]: start.model,
|
|
1341
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [end.finishReason],
|
|
1342
|
+
...(end.attributes || {}),
|
|
1343
|
+
},
|
|
1344
|
+
});
|
|
1345
|
+
},
|
|
1346
|
+
fail: span.fail,
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
embedding(ctx, options) {
|
|
1350
|
+
return this.span(ctx, options?.name || 'Embedding', SpanType.Embedding, options);
|
|
1351
|
+
}
|
|
1352
|
+
retrieval(ctx, options) {
|
|
1353
|
+
return this.span(ctx, options?.name || 'Retrieval', SpanType.Retrieval, options);
|
|
1354
|
+
}
|
|
1355
|
+
reranking(ctx, options) {
|
|
1356
|
+
return this.span(ctx, options?.name || 'Reranking', SpanType.Reranking, options);
|
|
1357
|
+
}
|
|
1358
|
+
attribifyHeaders(direction, headers) {
|
|
1359
|
+
const prefix = direction === 'request'
|
|
1360
|
+
? ATTR_HTTP_REQUEST_HEADERS
|
|
1361
|
+
: ATTR_HTTP_RESPONSE_HEADERS;
|
|
1362
|
+
const attributes = {};
|
|
1363
|
+
for (const key in headers) {
|
|
1364
|
+
const field = this.toKebabCase(key);
|
|
1365
|
+
const value = headers[key];
|
|
1366
|
+
if (value === null || value === undefined)
|
|
1367
|
+
continue;
|
|
1368
|
+
attributes[`${prefix}.${field}`] = value;
|
|
1369
|
+
}
|
|
1370
|
+
return attributes;
|
|
1371
|
+
}
|
|
1372
|
+
http(ctx, options) {
|
|
1373
|
+
const start = options;
|
|
1374
|
+
const method = start.request.method.toUpperCase();
|
|
1375
|
+
const attrHeaders = this.attribifyHeaders('request', start.request.headers);
|
|
1376
|
+
let finalBody = '';
|
|
1377
|
+
if (typeof start.request.body === 'string') {
|
|
1378
|
+
finalBody = start.request.body;
|
|
1379
|
+
}
|
|
1380
|
+
else {
|
|
1381
|
+
try {
|
|
1382
|
+
finalBody = JSON.stringify(start.request.body);
|
|
466
1383
|
}
|
|
467
1384
|
catch (error) {
|
|
468
|
-
|
|
1385
|
+
finalBody = '{}';
|
|
469
1386
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
1387
|
+
}
|
|
1388
|
+
const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
|
|
1389
|
+
attributes: {
|
|
1390
|
+
[semanticConventions.ATTR_HTTP_REQUEST_METHOD]: method,
|
|
1391
|
+
[ATTR_HTTP_REQUEST_URL]: start.request.url,
|
|
1392
|
+
...attrHeaders,
|
|
1393
|
+
[ATTR_HTTP_REQUEST_BODY]: finalBody,
|
|
1394
|
+
...(start.attributes || {}),
|
|
1395
|
+
},
|
|
1396
|
+
});
|
|
1397
|
+
return {
|
|
1398
|
+
context: span.context,
|
|
1399
|
+
end: (options) => {
|
|
1400
|
+
const end = options;
|
|
1401
|
+
const attrHeaders = this.attribifyHeaders('response', end.response.headers);
|
|
1402
|
+
let finalBody = '';
|
|
1403
|
+
if (typeof end.response.body === 'string') {
|
|
1404
|
+
finalBody = end.response.body;
|
|
1405
|
+
}
|
|
1406
|
+
else {
|
|
1407
|
+
try {
|
|
1408
|
+
finalBody = JSON.stringify(end.response.body);
|
|
1409
|
+
}
|
|
1410
|
+
catch (error) {
|
|
1411
|
+
finalBody = '{}';
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
span.end({
|
|
1415
|
+
attributes: {
|
|
1416
|
+
[semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE]: end.response.status,
|
|
1417
|
+
...attrHeaders,
|
|
1418
|
+
[ATTR_HTTP_RESPONSE_BODY]: finalBody,
|
|
1419
|
+
...(end.attributes || {}),
|
|
1420
|
+
},
|
|
475
1421
|
});
|
|
1422
|
+
},
|
|
1423
|
+
fail: span.fail,
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
segment(ctx, type, data, options) {
|
|
1427
|
+
options = options || {};
|
|
1428
|
+
let baggage = this.baggage(ctx);
|
|
1429
|
+
const parent = baggage?.segments.at(-1);
|
|
1430
|
+
const segments = baggage?.segments || [];
|
|
1431
|
+
segments.push({
|
|
1432
|
+
...{
|
|
1433
|
+
id: options._internal?.id || uuid.v4(),
|
|
1434
|
+
...(parent?.id && { parentId: parent.id }),
|
|
1435
|
+
source: options._internal?.source || parent?.source || this.source,
|
|
1436
|
+
type: type,
|
|
1437
|
+
data: data,
|
|
1438
|
+
},
|
|
1439
|
+
traceparent: 'undefined',
|
|
1440
|
+
tracestate: undefined,
|
|
1441
|
+
});
|
|
1442
|
+
const segment = segments.at(-1);
|
|
1443
|
+
baggage = {
|
|
1444
|
+
segment: { id: segment.id, parentId: segment.parentId },
|
|
1445
|
+
segments: segments,
|
|
1446
|
+
};
|
|
1447
|
+
ctx = this.setBaggage(ctx, baggage, options.baggage);
|
|
1448
|
+
// Dummy wrapper to force the same trace and carry on some segment attributes
|
|
1449
|
+
const span = this.span(ctx, type, SpanType.Segment, {
|
|
1450
|
+
attributes: options.attributes,
|
|
1451
|
+
});
|
|
1452
|
+
let carrier = {};
|
|
1453
|
+
otel.propagation.inject(span.context, carrier);
|
|
1454
|
+
baggage.segments.at(-1).traceparent = carrier.traceparent;
|
|
1455
|
+
baggage.segments.at(-1).tracestate = carrier.tracestate;
|
|
1456
|
+
// Fix current segment span segments attribute now that we know the trace
|
|
1457
|
+
otel.trace
|
|
1458
|
+
.getSpan(span.context)
|
|
1459
|
+
.setAttribute(ATTR_LATITUDE_SEGMENTS, JSON.stringify(baggage.segments));
|
|
1460
|
+
ctx = this.setBaggage(span.context, baggage, options.baggage);
|
|
1461
|
+
return { context: ctx, end: span.end, fail: span.fail };
|
|
1462
|
+
}
|
|
1463
|
+
prompt(ctx, { logUuid, versionUuid, promptUuid, experimentUuid, externalId, template, parameters, ...rest }) {
|
|
1464
|
+
const baggage = {
|
|
1465
|
+
...(logUuid && { logUuid }), // TODO(tracing): temporal related log, remove when observability is ready
|
|
1466
|
+
commitUuid: versionUuid || HEAD_COMMIT,
|
|
1467
|
+
documentUuid: promptUuid,
|
|
1468
|
+
...(experimentUuid && { experimentUuid }),
|
|
1469
|
+
...(externalId && { externalId }),
|
|
1470
|
+
};
|
|
1471
|
+
let jsonParameters = '';
|
|
1472
|
+
try {
|
|
1473
|
+
jsonParameters = JSON.stringify(parameters || {});
|
|
1474
|
+
}
|
|
1475
|
+
catch (error) {
|
|
1476
|
+
jsonParameters = '{}';
|
|
1477
|
+
}
|
|
1478
|
+
const attributes = {
|
|
1479
|
+
[ATTR_GEN_AI_REQUEST_TEMPLATE]: template,
|
|
1480
|
+
[ATTR_GEN_AI_REQUEST_PARAMETERS]: jsonParameters,
|
|
1481
|
+
...(rest.attributes || {}),
|
|
1482
|
+
};
|
|
1483
|
+
return this.segment(ctx, SegmentType.Document, baggage, {
|
|
1484
|
+
...rest,
|
|
1485
|
+
attributes,
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
step(ctx, options) {
|
|
1489
|
+
return this.segment(ctx, SegmentType.Step, undefined, options);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
class LatitudeInstrumentation {
|
|
1494
|
+
options;
|
|
1495
|
+
telemetry;
|
|
1496
|
+
constructor(source, tracer, options) {
|
|
1497
|
+
this.telemetry = new ManualInstrumentation(source, tracer);
|
|
1498
|
+
this.options = options;
|
|
1499
|
+
}
|
|
1500
|
+
isEnabled() {
|
|
1501
|
+
return this.telemetry.isEnabled();
|
|
1502
|
+
}
|
|
1503
|
+
enable() {
|
|
1504
|
+
this.options.module.instrument(this);
|
|
1505
|
+
this.telemetry.enable();
|
|
1506
|
+
}
|
|
1507
|
+
disable() {
|
|
1508
|
+
this.telemetry.disable();
|
|
1509
|
+
this.options.module.uninstrument();
|
|
1510
|
+
}
|
|
1511
|
+
countTokens(messages) {
|
|
1512
|
+
let length = 0;
|
|
1513
|
+
for (const message of messages) {
|
|
1514
|
+
if (!('content' in message))
|
|
1515
|
+
continue;
|
|
1516
|
+
if (typeof message.content === 'string') {
|
|
1517
|
+
length += message.content.length;
|
|
476
1518
|
}
|
|
477
|
-
|
|
478
|
-
|
|
1519
|
+
else if (Array.isArray(message.content)) {
|
|
1520
|
+
for (const content of message.content) {
|
|
1521
|
+
if (content.type === 'text') {
|
|
1522
|
+
length += content.text.length;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
// Note: this is an estimation to not bundle a tokenizer
|
|
1528
|
+
return Math.ceil(length / 4);
|
|
1529
|
+
}
|
|
1530
|
+
withTraceContext(ctx, fn) {
|
|
1531
|
+
return otel.context.with(this.telemetry.resume(ctx), fn);
|
|
1532
|
+
}
|
|
1533
|
+
async wrapToolHandler(fn, ...args) {
|
|
1534
|
+
const toolArguments = args[0];
|
|
1535
|
+
const { toolId, toolName } = args[1];
|
|
1536
|
+
const $tool = this.telemetry.tool(otel.context.active(), {
|
|
1537
|
+
name: toolName,
|
|
1538
|
+
call: {
|
|
1539
|
+
id: toolId,
|
|
1540
|
+
arguments: toolArguments,
|
|
1541
|
+
},
|
|
1542
|
+
});
|
|
1543
|
+
let result;
|
|
1544
|
+
try {
|
|
1545
|
+
result = await otel.context.with($tool.context, async () => await fn(...args));
|
|
1546
|
+
}
|
|
1547
|
+
catch (error) {
|
|
1548
|
+
if (error.name === 'ToolExecutionPausedError') {
|
|
1549
|
+
$tool.fail(error);
|
|
1550
|
+
throw error;
|
|
1551
|
+
}
|
|
1552
|
+
$tool.end({
|
|
1553
|
+
result: {
|
|
1554
|
+
value: error.message,
|
|
1555
|
+
isError: true,
|
|
1556
|
+
},
|
|
1557
|
+
});
|
|
1558
|
+
throw error;
|
|
1559
|
+
}
|
|
1560
|
+
$tool.end({
|
|
1561
|
+
result: {
|
|
1562
|
+
value: result,
|
|
1563
|
+
isError: false,
|
|
1564
|
+
},
|
|
1565
|
+
});
|
|
1566
|
+
return result;
|
|
1567
|
+
}
|
|
1568
|
+
async wrapRenderChain(fn, ...args) {
|
|
1569
|
+
const { prompt, parameters } = args[0];
|
|
1570
|
+
const $prompt = this.telemetry.prompt(otel.context.active(), {
|
|
1571
|
+
versionUuid: prompt.versionUuid,
|
|
1572
|
+
promptUuid: prompt.uuid,
|
|
1573
|
+
template: prompt.content,
|
|
1574
|
+
parameters: parameters,
|
|
1575
|
+
});
|
|
1576
|
+
let result;
|
|
1577
|
+
try {
|
|
1578
|
+
result = await otel.context.with($prompt.context, async () => await fn(...args));
|
|
1579
|
+
}
|
|
1580
|
+
catch (error) {
|
|
1581
|
+
$prompt.fail(error);
|
|
1582
|
+
throw error;
|
|
1583
|
+
}
|
|
1584
|
+
$prompt.end();
|
|
1585
|
+
return result;
|
|
1586
|
+
}
|
|
1587
|
+
async wrapRenderAgent(fn, ...args) {
|
|
1588
|
+
const { prompt, parameters } = args[0];
|
|
1589
|
+
const $prompt = this.telemetry.prompt(otel.context.active(), {
|
|
1590
|
+
versionUuid: prompt.versionUuid,
|
|
1591
|
+
promptUuid: prompt.uuid,
|
|
1592
|
+
template: prompt.content,
|
|
1593
|
+
parameters: parameters,
|
|
1594
|
+
});
|
|
1595
|
+
let result;
|
|
1596
|
+
try {
|
|
1597
|
+
result = await otel.context.with($prompt.context, async () => await fn(...args));
|
|
1598
|
+
}
|
|
1599
|
+
catch (error) {
|
|
1600
|
+
$prompt.fail(error);
|
|
1601
|
+
throw error;
|
|
1602
|
+
}
|
|
1603
|
+
$prompt.end();
|
|
1604
|
+
return result;
|
|
1605
|
+
}
|
|
1606
|
+
async wrapRenderStep(fn, ...args) {
|
|
1607
|
+
const $step = this.telemetry.step(otel.context.active());
|
|
1608
|
+
let result;
|
|
1609
|
+
try {
|
|
1610
|
+
result = await otel.context.with($step.context, async () => await fn(...args));
|
|
1611
|
+
}
|
|
1612
|
+
catch (error) {
|
|
1613
|
+
$step.fail(error);
|
|
1614
|
+
throw error;
|
|
1615
|
+
}
|
|
1616
|
+
$step.end();
|
|
1617
|
+
return result;
|
|
1618
|
+
}
|
|
1619
|
+
async wrapRenderCompletion(fn, ...args) {
|
|
1620
|
+
if (!this.options.completions) {
|
|
1621
|
+
return await fn(...args);
|
|
1622
|
+
}
|
|
1623
|
+
const { provider, config, messages } = args[0];
|
|
1624
|
+
const model = config.model || 'unknown';
|
|
1625
|
+
const $completion = this.telemetry.completion(otel.context.active(), {
|
|
1626
|
+
name: `${provider} / ${model}`,
|
|
1627
|
+
provider: provider,
|
|
1628
|
+
model: model,
|
|
1629
|
+
configuration: config,
|
|
1630
|
+
input: messages,
|
|
1631
|
+
});
|
|
1632
|
+
let result;
|
|
1633
|
+
try {
|
|
1634
|
+
result = await otel.context.with($completion.context, async () => await fn(...args));
|
|
1635
|
+
}
|
|
1636
|
+
catch (error) {
|
|
1637
|
+
$completion.fail(error);
|
|
1638
|
+
throw error;
|
|
1639
|
+
}
|
|
1640
|
+
// Note: enhance, this is just an estimation
|
|
1641
|
+
const promptTokens = this.countTokens(messages);
|
|
1642
|
+
const completionTokens = this.countTokens(result.messages);
|
|
1643
|
+
$completion.end({
|
|
1644
|
+
output: result.messages,
|
|
1645
|
+
tokens: {
|
|
1646
|
+
prompt: promptTokens,
|
|
1647
|
+
cached: 0,
|
|
1648
|
+
reasoning: 0,
|
|
1649
|
+
completion: completionTokens,
|
|
1650
|
+
},
|
|
1651
|
+
finishReason: result.toolRequests.length > 0
|
|
1652
|
+
? GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS
|
|
1653
|
+
: GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP,
|
|
1654
|
+
});
|
|
1655
|
+
return result;
|
|
1656
|
+
}
|
|
1657
|
+
async wrapRenderTool(fn, ...args) {
|
|
1658
|
+
const { toolRequest } = args[0];
|
|
1659
|
+
const $tool = this.telemetry.tool(otel.context.active(), {
|
|
1660
|
+
name: toolRequest.toolName,
|
|
1661
|
+
call: {
|
|
1662
|
+
id: toolRequest.toolCallId,
|
|
1663
|
+
arguments: toolRequest.toolArguments,
|
|
1664
|
+
},
|
|
1665
|
+
});
|
|
1666
|
+
let result;
|
|
1667
|
+
try {
|
|
1668
|
+
result = await otel.context.with($tool.context, async () => await fn(...args));
|
|
1669
|
+
}
|
|
1670
|
+
catch (error) {
|
|
1671
|
+
$tool.fail(error);
|
|
1672
|
+
throw error;
|
|
1673
|
+
}
|
|
1674
|
+
$tool.end({
|
|
1675
|
+
result: {
|
|
1676
|
+
value: result,
|
|
1677
|
+
isError: false, // Note: currently unknown
|
|
1678
|
+
},
|
|
1679
|
+
});
|
|
1680
|
+
return result;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
const TRACES_URL = `${env.GATEWAY_BASE_URL}/api/v3/otlp/v1/traces`;
|
|
1685
|
+
const SERVICE_NAME = process.env.npm_package_name || 'unknown';
|
|
1686
|
+
const SCOPE_VERSION = process.env.npm_package_version || 'unknown';
|
|
1687
|
+
const BACKGROUND = () => otel__namespace.ROOT_CONTEXT;
|
|
1688
|
+
class ScopedTracerProvider {
|
|
1689
|
+
scope;
|
|
1690
|
+
version;
|
|
1691
|
+
provider;
|
|
1692
|
+
constructor(scope, version, provider) {
|
|
1693
|
+
this.scope = scope;
|
|
1694
|
+
this.version = version;
|
|
1695
|
+
this.provider = provider;
|
|
1696
|
+
}
|
|
1697
|
+
getTracer(_name, _version, options) {
|
|
1698
|
+
return this.provider.getTracer(this.scope, this.version, options);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
const DEFAULT_SPAN_EXPORTER = (apiKey) => new exporterTraceOtlpHttp.OTLPTraceExporter({
|
|
1702
|
+
url: TRACES_URL,
|
|
1703
|
+
headers: {
|
|
1704
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1705
|
+
'Content-Type': 'application/json',
|
|
1706
|
+
},
|
|
1707
|
+
timeoutMillis: 30 * 1000,
|
|
1708
|
+
});
|
|
1709
|
+
// Note: Only exporting typescript instrumentations
|
|
1710
|
+
exports.Instrumentation = void 0;
|
|
1711
|
+
(function (Instrumentation) {
|
|
1712
|
+
Instrumentation["Latitude"] = "latitude";
|
|
1713
|
+
Instrumentation["OpenAI"] = "openai";
|
|
1714
|
+
Instrumentation["Anthropic"] = "anthropic";
|
|
1715
|
+
Instrumentation["AzureOpenAI"] = "azure";
|
|
1716
|
+
Instrumentation["VercelAI"] = "vercelai";
|
|
1717
|
+
Instrumentation["VertexAI"] = "vertexai";
|
|
1718
|
+
Instrumentation["AIPlatform"] = "aiplatform";
|
|
1719
|
+
Instrumentation["Bedrock"] = "bedrock";
|
|
1720
|
+
Instrumentation["TogetherAI"] = "togetherai";
|
|
1721
|
+
Instrumentation["Cohere"] = "cohere";
|
|
1722
|
+
Instrumentation["Langchain"] = "langchain";
|
|
1723
|
+
Instrumentation["LlamaIndex"] = "llamaindex";
|
|
1724
|
+
})(exports.Instrumentation || (exports.Instrumentation = {}));
|
|
1725
|
+
class LatitudeTelemetry {
|
|
1726
|
+
options;
|
|
1727
|
+
provider;
|
|
1728
|
+
telemetry;
|
|
1729
|
+
instrumentations;
|
|
1730
|
+
constructor(apiKey, options) {
|
|
1731
|
+
this.options = options || {};
|
|
1732
|
+
if (!this.options.exporter) {
|
|
1733
|
+
this.options.exporter = DEFAULT_SPAN_EXPORTER(apiKey);
|
|
1734
|
+
}
|
|
1735
|
+
otel.context.setGlobalContextManager(new contextAsyncHooks.AsyncLocalStorageContextManager().enable());
|
|
1736
|
+
otel.propagation.setGlobalPropagator(new core.CompositePropagator({
|
|
1737
|
+
propagators: [
|
|
1738
|
+
...(this.options.propagators || []),
|
|
1739
|
+
new core.W3CTraceContextPropagator(),
|
|
1740
|
+
new core.W3CBaggagePropagator(),
|
|
1741
|
+
],
|
|
479
1742
|
}));
|
|
1743
|
+
this.provider = new sdkTraceNode.NodeTracerProvider({
|
|
1744
|
+
resource: new resources.Resource({ [semanticConventions.ATTR_SERVICE_NAME]: SERVICE_NAME }),
|
|
1745
|
+
});
|
|
1746
|
+
// Note: important, must run before the exporter span processors
|
|
1747
|
+
this.provider.addSpanProcessor(new baggageSpanProcessor.BaggageSpanProcessor(baggageSpanProcessor.ALLOW_ALL_BAGGAGE_KEYS));
|
|
1748
|
+
if (this.options.processors) {
|
|
1749
|
+
this.options.processors.forEach((processor) => {
|
|
1750
|
+
this.provider.addSpanProcessor(processor);
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
else {
|
|
1754
|
+
this.provider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
|
|
1755
|
+
}
|
|
1756
|
+
if (this.options.disableBatch) {
|
|
1757
|
+
this.provider.addSpanProcessor(new sdkTraceNode.SimpleSpanProcessor(this.options.exporter));
|
|
1758
|
+
}
|
|
1759
|
+
else {
|
|
1760
|
+
this.provider.addSpanProcessor(new sdkTraceNode.BatchSpanProcessor(this.options.exporter));
|
|
1761
|
+
}
|
|
1762
|
+
this.provider.register();
|
|
1763
|
+
process.on('SIGTERM', async () => this.shutdown);
|
|
1764
|
+
process.on('SIGINT', async () => this.shutdown);
|
|
1765
|
+
this.telemetry = null;
|
|
1766
|
+
this.instrumentations = [];
|
|
1767
|
+
this.initInstrumentations();
|
|
1768
|
+
this.instrument();
|
|
1769
|
+
}
|
|
1770
|
+
async flush() {
|
|
1771
|
+
await this.provider.forceFlush();
|
|
1772
|
+
await this.options.exporter.forceFlush?.();
|
|
1773
|
+
}
|
|
1774
|
+
async shutdown() {
|
|
1775
|
+
await this.flush();
|
|
1776
|
+
await this.provider.shutdown();
|
|
1777
|
+
await this.options.exporter.shutdown?.();
|
|
1778
|
+
}
|
|
1779
|
+
tracerProvider(instrumentation) {
|
|
1780
|
+
return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${instrumentation}`, SCOPE_VERSION, this.provider);
|
|
1781
|
+
}
|
|
1782
|
+
tracer(instrumentation) {
|
|
1783
|
+
return this.tracerProvider(instrumentation).getTracer('');
|
|
1784
|
+
}
|
|
1785
|
+
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
1786
|
+
initInstrumentations() {
|
|
1787
|
+
this.instrumentations = [];
|
|
1788
|
+
const tracer = this.tracer(InstrumentationScope.Manual);
|
|
1789
|
+
this.telemetry = new ManualInstrumentation(SegmentSource.API, tracer);
|
|
1790
|
+
this.instrumentations.push(this.telemetry);
|
|
1791
|
+
const latitude = this.options.instrumentations?.latitude;
|
|
1792
|
+
if (latitude) {
|
|
1793
|
+
const tracer = this.tracer(exports.Instrumentation.Latitude);
|
|
1794
|
+
const instrumentation = new LatitudeInstrumentation(SegmentSource.API, tracer, typeof latitude === 'object' ? latitude : { module: latitude });
|
|
1795
|
+
this.instrumentations.push(instrumentation);
|
|
1796
|
+
}
|
|
1797
|
+
const openai = this.options.instrumentations?.openai;
|
|
1798
|
+
if (openai) {
|
|
1799
|
+
const provider = this.tracerProvider(exports.Instrumentation.OpenAI);
|
|
1800
|
+
const instrumentation$1 = new instrumentationOpenai.OpenAIInstrumentation({ enrichTokens: true });
|
|
1801
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1802
|
+
instrumentation$1.manuallyInstrument(openai);
|
|
1803
|
+
instrumentation.registerInstrumentations({
|
|
1804
|
+
instrumentations: [instrumentation$1],
|
|
1805
|
+
tracerProvider: provider,
|
|
1806
|
+
});
|
|
1807
|
+
this.instrumentations.push(instrumentation$1);
|
|
1808
|
+
}
|
|
1809
|
+
const anthropic = this.options.instrumentations?.anthropic;
|
|
1810
|
+
if (anthropic) {
|
|
1811
|
+
const provider = this.tracerProvider(exports.Instrumentation.Anthropic);
|
|
1812
|
+
const instrumentation$1 = new instrumentationAnthropic.AnthropicInstrumentation();
|
|
1813
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1814
|
+
instrumentation$1.manuallyInstrument(anthropic);
|
|
1815
|
+
instrumentation.registerInstrumentations({
|
|
1816
|
+
instrumentations: [instrumentation$1],
|
|
1817
|
+
tracerProvider: provider,
|
|
1818
|
+
});
|
|
1819
|
+
this.instrumentations.push(instrumentation$1);
|
|
1820
|
+
}
|
|
1821
|
+
const azure = this.options.instrumentations?.azure;
|
|
1822
|
+
if (azure) {
|
|
1823
|
+
const provider = this.tracerProvider(exports.Instrumentation.AzureOpenAI);
|
|
1824
|
+
const instrumentation$1 = new instrumentationAzure.AzureOpenAIInstrumentation();
|
|
1825
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1826
|
+
instrumentation$1.manuallyInstrument(azure);
|
|
1827
|
+
instrumentation.registerInstrumentations({
|
|
1828
|
+
instrumentations: [instrumentation$1],
|
|
1829
|
+
tracerProvider: provider,
|
|
1830
|
+
});
|
|
1831
|
+
this.instrumentations.push(instrumentation$1);
|
|
1832
|
+
}
|
|
1833
|
+
const vertexai = this.options.instrumentations?.vertexai;
|
|
1834
|
+
if (vertexai) {
|
|
1835
|
+
const provider = this.tracerProvider(exports.Instrumentation.VertexAI);
|
|
1836
|
+
const instrumentation$1 = new instrumentationVertexai.VertexAIInstrumentation();
|
|
1837
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1838
|
+
instrumentation$1.manuallyInstrument(vertexai);
|
|
1839
|
+
instrumentation.registerInstrumentations({
|
|
1840
|
+
instrumentations: [instrumentation$1],
|
|
1841
|
+
tracerProvider: provider,
|
|
1842
|
+
});
|
|
1843
|
+
this.instrumentations.push(instrumentation$1);
|
|
1844
|
+
}
|
|
1845
|
+
const aiplatform = this.options.instrumentations?.aiplatform;
|
|
1846
|
+
if (aiplatform) {
|
|
1847
|
+
const provider = this.tracerProvider(exports.Instrumentation.AIPlatform);
|
|
1848
|
+
const instrumentation$1 = new instrumentationVertexai.AIPlatformInstrumentation();
|
|
1849
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1850
|
+
instrumentation$1.manuallyInstrument(aiplatform);
|
|
1851
|
+
instrumentation.registerInstrumentations({
|
|
1852
|
+
instrumentations: [instrumentation$1],
|
|
1853
|
+
tracerProvider: provider,
|
|
1854
|
+
});
|
|
1855
|
+
this.instrumentations.push(instrumentation$1);
|
|
1856
|
+
}
|
|
1857
|
+
const bedrock = this.options.instrumentations?.bedrock;
|
|
1858
|
+
if (bedrock) {
|
|
1859
|
+
const provider = this.tracerProvider(exports.Instrumentation.Bedrock);
|
|
1860
|
+
const instrumentation$1 = new instrumentationBedrock.BedrockInstrumentation();
|
|
1861
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1862
|
+
instrumentation$1.manuallyInstrument(bedrock);
|
|
1863
|
+
instrumentation.registerInstrumentations({
|
|
1864
|
+
instrumentations: [instrumentation$1],
|
|
1865
|
+
tracerProvider: provider,
|
|
1866
|
+
});
|
|
1867
|
+
this.instrumentations.push(instrumentation$1);
|
|
1868
|
+
}
|
|
1869
|
+
const togetherai = this.options.instrumentations?.togetherai;
|
|
1870
|
+
if (togetherai) {
|
|
1871
|
+
const provider = this.tracerProvider(exports.Instrumentation.TogetherAI);
|
|
1872
|
+
const instrumentation$1 = new instrumentationTogether.TogetherInstrumentation({
|
|
1873
|
+
enrichTokens: true,
|
|
1874
|
+
});
|
|
1875
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1876
|
+
instrumentation$1.manuallyInstrument(togetherai);
|
|
1877
|
+
instrumentation.registerInstrumentations({
|
|
1878
|
+
instrumentations: [instrumentation$1],
|
|
1879
|
+
tracerProvider: provider,
|
|
1880
|
+
});
|
|
1881
|
+
this.instrumentations.push(instrumentation$1);
|
|
1882
|
+
}
|
|
1883
|
+
const cohere = this.options.instrumentations?.cohere;
|
|
1884
|
+
if (cohere) {
|
|
1885
|
+
const provider = this.tracerProvider(exports.Instrumentation.Cohere);
|
|
1886
|
+
const instrumentation$1 = new instrumentationCohere.CohereInstrumentation();
|
|
1887
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1888
|
+
instrumentation$1.manuallyInstrument(cohere);
|
|
1889
|
+
instrumentation.registerInstrumentations({
|
|
1890
|
+
instrumentations: [instrumentation$1],
|
|
1891
|
+
tracerProvider: provider,
|
|
1892
|
+
});
|
|
1893
|
+
this.instrumentations.push(instrumentation$1);
|
|
1894
|
+
}
|
|
1895
|
+
const langchain = this.options.instrumentations?.langchain;
|
|
1896
|
+
if (langchain) {
|
|
1897
|
+
const provider = this.tracerProvider(exports.Instrumentation.Langchain);
|
|
1898
|
+
const instrumentation$1 = new instrumentationLangchain.LangChainInstrumentation();
|
|
1899
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1900
|
+
instrumentation$1.manuallyInstrument(langchain);
|
|
1901
|
+
instrumentation.registerInstrumentations({
|
|
1902
|
+
instrumentations: [instrumentation$1],
|
|
1903
|
+
tracerProvider: provider,
|
|
1904
|
+
});
|
|
1905
|
+
this.instrumentations.push(instrumentation$1);
|
|
1906
|
+
}
|
|
1907
|
+
const llamaindex = this.options.instrumentations?.llamaindex;
|
|
1908
|
+
if (llamaindex) {
|
|
1909
|
+
const provider = this.tracerProvider(exports.Instrumentation.LlamaIndex);
|
|
1910
|
+
const instrumentation$1 = new instrumentationLlamaindex.LlamaIndexInstrumentation();
|
|
1911
|
+
instrumentation$1.setTracerProvider(provider);
|
|
1912
|
+
instrumentation$1.manuallyInstrument(llamaindex);
|
|
1913
|
+
instrumentation.registerInstrumentations({
|
|
1914
|
+
instrumentations: [instrumentation$1],
|
|
1915
|
+
tracerProvider: provider,
|
|
1916
|
+
});
|
|
1917
|
+
this.instrumentations.push(instrumentation$1);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
instrument() {
|
|
1921
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
1922
|
+
if (!instrumentation.isEnabled())
|
|
1923
|
+
instrumentation.enable();
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
uninstrument() {
|
|
1927
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
1928
|
+
if (instrumentation.isEnabled())
|
|
1929
|
+
instrumentation.disable();
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1932
|
+
baggage(ctx) {
|
|
1933
|
+
return this.telemetry.baggage(ctx);
|
|
1934
|
+
}
|
|
1935
|
+
pause(ctx) {
|
|
1936
|
+
return this.telemetry.pause(ctx);
|
|
1937
|
+
}
|
|
1938
|
+
resume(ctx) {
|
|
1939
|
+
return this.telemetry.resume(ctx);
|
|
1940
|
+
}
|
|
1941
|
+
restored(ctx) {
|
|
1942
|
+
return this.telemetry.restored(ctx);
|
|
1943
|
+
}
|
|
1944
|
+
restore(ctx) {
|
|
1945
|
+
return this.telemetry.restore(ctx);
|
|
1946
|
+
}
|
|
1947
|
+
tool(ctx, options) {
|
|
1948
|
+
return this.telemetry.tool(ctx, options);
|
|
1949
|
+
}
|
|
1950
|
+
completion(ctx, options) {
|
|
1951
|
+
return this.telemetry.completion(ctx, options);
|
|
1952
|
+
}
|
|
1953
|
+
embedding(ctx, options) {
|
|
1954
|
+
return this.telemetry.embedding(ctx, options);
|
|
1955
|
+
}
|
|
1956
|
+
retrieval(ctx, options) {
|
|
1957
|
+
return this.telemetry.retrieval(ctx, options);
|
|
1958
|
+
}
|
|
1959
|
+
reranking(ctx, options) {
|
|
1960
|
+
return this.telemetry.reranking(ctx, options);
|
|
1961
|
+
}
|
|
1962
|
+
http(ctx, options) {
|
|
1963
|
+
return this.telemetry.http(ctx, options);
|
|
1964
|
+
}
|
|
1965
|
+
prompt(ctx, options) {
|
|
1966
|
+
return this.telemetry.prompt(ctx, options);
|
|
1967
|
+
}
|
|
1968
|
+
step(ctx, options) {
|
|
1969
|
+
return this.telemetry.step(ctx, options);
|
|
480
1970
|
}
|
|
481
1971
|
}
|
|
482
1972
|
|
|
483
|
-
exports.
|
|
484
|
-
exports.
|
|
485
|
-
exports.
|
|
486
|
-
exports.
|
|
1973
|
+
exports.BACKGROUND = BACKGROUND;
|
|
1974
|
+
exports.DEFAULT_REDACT_SPAN_PROCESSOR = DEFAULT_REDACT_SPAN_PROCESSOR;
|
|
1975
|
+
exports.DEFAULT_SPAN_EXPORTER = DEFAULT_SPAN_EXPORTER;
|
|
1976
|
+
exports.LatitudeTelemetry = LatitudeTelemetry;
|
|
1977
|
+
exports.RedactSpanProcessor = RedactSpanProcessor;
|
|
487
1978
|
//# sourceMappingURL=index.cjs.map
|