@latitude-data/telemetry 1.1.0 → 2.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/dist/index.cjs +401 -441
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +57 -71
- package/dist/index.js +401 -441
- package/dist/index.js.map +1 -1
- package/package.json +12 -8
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
|
-
var otel = require('@opentelemetry/api');
|
|
5
|
-
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
6
4
|
var incubating = require('@opentelemetry/semantic-conventions/incubating');
|
|
5
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
6
|
+
var otel = require('@opentelemetry/api');
|
|
7
|
+
var rosettaAi = require('rosetta-ai');
|
|
7
8
|
var uuid = require('uuid');
|
|
8
9
|
var baggageSpanProcessor = require('@opentelemetry/baggage-span-processor');
|
|
9
10
|
var contextAsyncHooks = require('@opentelemetry/context-async-hooks');
|
|
@@ -138,6 +139,23 @@ function GET_GATEWAY_BASE_URL() {
|
|
|
138
139
|
}
|
|
139
140
|
const env = { GATEWAY_BASE_URL: GET_GATEWAY_BASE_URL() };
|
|
140
141
|
|
|
142
|
+
function toSnakeCase(str) {
|
|
143
|
+
return str
|
|
144
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
145
|
+
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
146
|
+
.replace(/_+/g, '_')
|
|
147
|
+
.replace(/^_+|_+$/g, '')
|
|
148
|
+
.toLowerCase();
|
|
149
|
+
}
|
|
150
|
+
function toKebabCase(input) {
|
|
151
|
+
return input
|
|
152
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
153
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
154
|
+
.replace(/-+/g, '-')
|
|
155
|
+
.replace(/^-+|-+$/g, '')
|
|
156
|
+
.toLowerCase();
|
|
157
|
+
}
|
|
158
|
+
|
|
141
159
|
var StreamEventTypes;
|
|
142
160
|
(function (StreamEventTypes) {
|
|
143
161
|
StreamEventTypes["Latitude"] = "latitude-event";
|
|
@@ -150,6 +168,15 @@ zod.z.object({
|
|
|
150
168
|
isError: zod.z.boolean().optional(),
|
|
151
169
|
text: zod.z.string().optional(),
|
|
152
170
|
});
|
|
171
|
+
zod.z.object({
|
|
172
|
+
inputTokens: zod.z.number(),
|
|
173
|
+
outputTokens: zod.z.number(),
|
|
174
|
+
promptTokens: zod.z.number(),
|
|
175
|
+
completionTokens: zod.z.number(),
|
|
176
|
+
totalTokens: zod.z.number(),
|
|
177
|
+
reasoningTokens: zod.z.number(),
|
|
178
|
+
cachedInputTokens: zod.z.number(),
|
|
179
|
+
});
|
|
153
180
|
|
|
154
181
|
var ParameterType;
|
|
155
182
|
(function (ParameterType) {
|
|
@@ -190,10 +217,24 @@ const expectedOutputConfiguration = zod.z.object({
|
|
|
190
217
|
parsingFormat: zod.z.enum(['string', 'json']),
|
|
191
218
|
fieldAccessor: zod.z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
192
219
|
});
|
|
220
|
+
const EVALUATION_TRIGGER_TARGETS = ['first', 'every', 'last'];
|
|
221
|
+
const DEFAULT_LAST_INTERACTION_DEBOUNCE_SECONDS = 120;
|
|
222
|
+
const LAST_INTERACTION_DEBOUNCE_MIN_SECONDS = 30;
|
|
223
|
+
const LAST_INTERACTION_DEBOUNCE_MAX_SECONDS = 60 * 60 * 24; // 1 day
|
|
224
|
+
const triggerConfiguration = zod.z.object({
|
|
225
|
+
target: zod.z.enum(EVALUATION_TRIGGER_TARGETS),
|
|
226
|
+
lastInteractionDebounce: zod.z
|
|
227
|
+
.number()
|
|
228
|
+
.min(LAST_INTERACTION_DEBOUNCE_MIN_SECONDS)
|
|
229
|
+
.max(LAST_INTERACTION_DEBOUNCE_MAX_SECONDS)
|
|
230
|
+
.optional()
|
|
231
|
+
.default(DEFAULT_LAST_INTERACTION_DEBOUNCE_SECONDS),
|
|
232
|
+
});
|
|
193
233
|
const baseEvaluationConfiguration = zod.z.object({
|
|
194
234
|
reverseScale: zod.z.boolean(), // If true, lower is better, otherwise, higher is better
|
|
195
235
|
actualOutput: actualOutputConfiguration,
|
|
196
236
|
expectedOutput: expectedOutputConfiguration.optional(),
|
|
237
|
+
trigger: triggerConfiguration.optional(),
|
|
197
238
|
});
|
|
198
239
|
const baseEvaluationResultMetadata = zod.z.object({
|
|
199
240
|
// configuration: Configuration snapshot is defined in every metric specification
|
|
@@ -209,7 +250,6 @@ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
|
209
250
|
evaluationUuids: zod.z.array(zod.z.string()),
|
|
210
251
|
minThreshold: zod.z.number().optional(), // Threshold percentage
|
|
211
252
|
maxThreshold: zod.z.number().optional(), // Threshold percentage
|
|
212
|
-
defaultTarget: zod.z.boolean().optional(), // Default for optimizations and distillations
|
|
213
253
|
});
|
|
214
254
|
const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
215
255
|
results: zod.z.record(zod.z.string(), // Evaluation uuid
|
|
@@ -276,12 +316,34 @@ const CompositeEvaluationSpecification = {
|
|
|
276
316
|
},
|
|
277
317
|
};
|
|
278
318
|
|
|
319
|
+
const selectedContextSchema = zod.z.object({
|
|
320
|
+
messageIndex: zod.z.number().int().nonnegative(),
|
|
321
|
+
contentBlockIndex: zod.z.number().int().nonnegative(),
|
|
322
|
+
contentType: zod.z.enum([
|
|
323
|
+
'text',
|
|
324
|
+
'reasoning',
|
|
325
|
+
'image',
|
|
326
|
+
'file',
|
|
327
|
+
'tool-call',
|
|
328
|
+
'tool-result',
|
|
329
|
+
]),
|
|
330
|
+
textRange: zod.z
|
|
331
|
+
.object({
|
|
332
|
+
start: zod.z.number().int().nonnegative(),
|
|
333
|
+
end: zod.z.number().int().nonnegative(),
|
|
334
|
+
})
|
|
335
|
+
.optional(),
|
|
336
|
+
selectedText: zod.z.string().optional(),
|
|
337
|
+
toolCallId: zod.z.string().optional(),
|
|
338
|
+
});
|
|
279
339
|
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
280
340
|
enableControls: zod.z.boolean().optional(), // UI annotation controls
|
|
281
341
|
criteria: zod.z.string().optional(),
|
|
282
342
|
});
|
|
283
343
|
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
284
344
|
reason: zod.z.string().optional(),
|
|
345
|
+
enrichedReason: zod.z.string().optional(),
|
|
346
|
+
selectedContexts: zod.z.array(selectedContextSchema).optional(),
|
|
285
347
|
});
|
|
286
348
|
const humanEvaluationResultError = baseEvaluationResultError.extend({});
|
|
287
349
|
// BINARY
|
|
@@ -559,18 +621,8 @@ zod.z.object({
|
|
|
559
621
|
});
|
|
560
622
|
zod.z.object({
|
|
561
623
|
evaluateLiveLogs: zod.z.boolean().nullable().optional(),
|
|
562
|
-
enableSuggestions: zod.z.boolean().nullable().optional(),
|
|
563
|
-
autoApplySuggestions: zod.z.boolean().nullable().optional(),
|
|
564
624
|
});
|
|
565
625
|
|
|
566
|
-
var LegacyChainEventTypes;
|
|
567
|
-
(function (LegacyChainEventTypes) {
|
|
568
|
-
LegacyChainEventTypes["Error"] = "chain-error";
|
|
569
|
-
LegacyChainEventTypes["Step"] = "chain-step";
|
|
570
|
-
LegacyChainEventTypes["Complete"] = "chain-complete";
|
|
571
|
-
LegacyChainEventTypes["StepComplete"] = "chain-step-complete";
|
|
572
|
-
})(LegacyChainEventTypes || (LegacyChainEventTypes = {}));
|
|
573
|
-
|
|
574
626
|
var ChainEventTypes;
|
|
575
627
|
(function (ChainEventTypes) {
|
|
576
628
|
ChainEventTypes["ChainCompleted"] = "chain-completed";
|
|
@@ -758,6 +810,7 @@ var LogSources;
|
|
|
758
810
|
LogSources["ShadowTest"] = "shadow_test";
|
|
759
811
|
LogSources["ABTestChallenger"] = "ab_test_challenger";
|
|
760
812
|
LogSources["User"] = "user";
|
|
813
|
+
LogSources["Optimization"] = "optimization";
|
|
761
814
|
})(LogSources || (LogSources = {}));
|
|
762
815
|
|
|
763
816
|
var RunSourceGroup;
|
|
@@ -768,7 +821,8 @@ var RunSourceGroup;
|
|
|
768
821
|
({
|
|
769
822
|
[RunSourceGroup.Production]: [
|
|
770
823
|
LogSources.API,
|
|
771
|
-
LogSources.
|
|
824
|
+
LogSources.ShadowTest,
|
|
825
|
+
LogSources.ABTestChallenger,
|
|
772
826
|
LogSources.EmailTrigger,
|
|
773
827
|
LogSources.IntegrationTrigger,
|
|
774
828
|
LogSources.ScheduledTrigger,
|
|
@@ -778,14 +832,6 @@ var RunSourceGroup;
|
|
|
778
832
|
[RunSourceGroup.Playground]: [LogSources.Playground, LogSources.Experiment],
|
|
779
833
|
});
|
|
780
834
|
|
|
781
|
-
var MessageRole;
|
|
782
|
-
(function (MessageRole) {
|
|
783
|
-
MessageRole["system"] = "system";
|
|
784
|
-
MessageRole["user"] = "user";
|
|
785
|
-
MessageRole["assistant"] = "assistant";
|
|
786
|
-
MessageRole["tool"] = "tool";
|
|
787
|
-
})(MessageRole || (MessageRole = {}));
|
|
788
|
-
|
|
789
835
|
var SpanKind;
|
|
790
836
|
(function (SpanKind) {
|
|
791
837
|
SpanKind["Internal"] = "internal";
|
|
@@ -797,26 +843,49 @@ var SpanKind;
|
|
|
797
843
|
// Note: loosely based on OpenTelemetry GenAI semantic conventions
|
|
798
844
|
var SpanType;
|
|
799
845
|
(function (SpanType) {
|
|
800
|
-
|
|
801
|
-
SpanType["Completion"] = "completion";
|
|
802
|
-
SpanType["Embedding"] = "embedding";
|
|
803
|
-
SpanType["Retrieval"] = "retrieval";
|
|
804
|
-
SpanType["Reranking"] = "reranking";
|
|
805
|
-
SpanType["Http"] = "http";
|
|
806
|
-
SpanType["Unknown"] = "unknown";
|
|
846
|
+
// Latitude wrappers
|
|
807
847
|
SpanType["Prompt"] = "prompt";
|
|
808
848
|
SpanType["Chat"] = "chat";
|
|
809
849
|
SpanType["External"] = "external";
|
|
810
850
|
SpanType["UnresolvedExternal"] = "unresolved_external";
|
|
811
|
-
|
|
851
|
+
// Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
|
|
852
|
+
SpanType["Http"] = "http";
|
|
853
|
+
// Any known span from supported specifications will be grouped into one of these types
|
|
854
|
+
SpanType["Completion"] = "completion";
|
|
855
|
+
SpanType["Tool"] = "tool";
|
|
856
|
+
SpanType["Embedding"] = "embedding";
|
|
857
|
+
SpanType["Unknown"] = "unknown";
|
|
812
858
|
})(SpanType || (SpanType = {}));
|
|
859
|
+
[
|
|
860
|
+
SpanType.Prompt,
|
|
861
|
+
SpanType.External,
|
|
862
|
+
SpanType.Chat,
|
|
863
|
+
];
|
|
813
864
|
const SPAN_SPECIFICATIONS = {
|
|
814
|
-
[SpanType.
|
|
815
|
-
name: '
|
|
816
|
-
description: 'A
|
|
817
|
-
isGenAI:
|
|
865
|
+
[SpanType.Prompt]: {
|
|
866
|
+
name: 'Prompt',
|
|
867
|
+
description: 'A prompt span',
|
|
868
|
+
isGenAI: false,
|
|
869
|
+
isHidden: false,
|
|
870
|
+
},
|
|
871
|
+
[SpanType.Chat]: {
|
|
872
|
+
name: 'Chat',
|
|
873
|
+
description: 'A chat continuation span',
|
|
874
|
+
isGenAI: false,
|
|
875
|
+
isHidden: false,
|
|
876
|
+
},
|
|
877
|
+
[SpanType.External]: {
|
|
878
|
+
name: 'External',
|
|
879
|
+
description: 'An external capture span',
|
|
880
|
+
isGenAI: false,
|
|
818
881
|
isHidden: false,
|
|
819
882
|
},
|
|
883
|
+
[SpanType.UnresolvedExternal]: {
|
|
884
|
+
name: 'Unresolved External',
|
|
885
|
+
description: 'An external span that needs path resolution before storage',
|
|
886
|
+
isGenAI: false,
|
|
887
|
+
isHidden: true,
|
|
888
|
+
},
|
|
820
889
|
[SpanType.Completion]: {
|
|
821
890
|
name: 'Completion',
|
|
822
891
|
description: 'A completion call',
|
|
@@ -829,15 +898,9 @@ const SPAN_SPECIFICATIONS = {
|
|
|
829
898
|
isGenAI: true,
|
|
830
899
|
isHidden: false,
|
|
831
900
|
},
|
|
832
|
-
[SpanType.
|
|
833
|
-
name: '
|
|
834
|
-
description: 'A
|
|
835
|
-
isGenAI: true,
|
|
836
|
-
isHidden: false,
|
|
837
|
-
},
|
|
838
|
-
[SpanType.Reranking]: {
|
|
839
|
-
name: 'Reranking',
|
|
840
|
-
description: 'A reranking call',
|
|
901
|
+
[SpanType.Tool]: {
|
|
902
|
+
name: 'Tool',
|
|
903
|
+
description: 'A tool call',
|
|
841
904
|
isGenAI: true,
|
|
842
905
|
isHidden: false,
|
|
843
906
|
},
|
|
@@ -853,36 +916,6 @@ const SPAN_SPECIFICATIONS = {
|
|
|
853
916
|
isGenAI: false,
|
|
854
917
|
isHidden: true,
|
|
855
918
|
},
|
|
856
|
-
[SpanType.Prompt]: {
|
|
857
|
-
name: 'Prompt',
|
|
858
|
-
description: 'A prompt span',
|
|
859
|
-
isGenAI: false,
|
|
860
|
-
isHidden: false,
|
|
861
|
-
},
|
|
862
|
-
[SpanType.Chat]: {
|
|
863
|
-
name: 'Chat',
|
|
864
|
-
description: 'A chat continuation span',
|
|
865
|
-
isGenAI: false,
|
|
866
|
-
isHidden: false,
|
|
867
|
-
},
|
|
868
|
-
[SpanType.External]: {
|
|
869
|
-
name: 'External',
|
|
870
|
-
description: 'An external capture span',
|
|
871
|
-
isGenAI: false,
|
|
872
|
-
isHidden: false,
|
|
873
|
-
},
|
|
874
|
-
[SpanType.UnresolvedExternal]: {
|
|
875
|
-
name: 'Unresolved External',
|
|
876
|
-
description: 'An external span that needs path resolution before storage',
|
|
877
|
-
isGenAI: false,
|
|
878
|
-
isHidden: true,
|
|
879
|
-
},
|
|
880
|
-
[SpanType.Step]: {
|
|
881
|
-
name: 'Step',
|
|
882
|
-
description: 'A step span',
|
|
883
|
-
isGenAI: false,
|
|
884
|
-
isHidden: false,
|
|
885
|
-
},
|
|
886
919
|
};
|
|
887
920
|
var SpanStatus;
|
|
888
921
|
(function (SpanStatus) {
|
|
@@ -890,6 +923,11 @@ var SpanStatus;
|
|
|
890
923
|
SpanStatus["Ok"] = "ok";
|
|
891
924
|
SpanStatus["Error"] = "error";
|
|
892
925
|
})(SpanStatus || (SpanStatus = {}));
|
|
926
|
+
new Set([
|
|
927
|
+
SpanType.Prompt,
|
|
928
|
+
SpanType.Chat,
|
|
929
|
+
SpanType.External,
|
|
930
|
+
]);
|
|
893
931
|
|
|
894
932
|
// Note: Traces are unmaterialized but this context is used to propagate the trace
|
|
895
933
|
// See www.w3.org/TR/trace-context and w3c.github.io/baggage
|
|
@@ -899,6 +937,100 @@ zod.z.object({
|
|
|
899
937
|
baggage: zod.z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
900
938
|
});
|
|
901
939
|
|
|
940
|
+
const ATTRIBUTES = {
|
|
941
|
+
// Custom attributes added and used by Latitude spans (Prompt / External / Chat)
|
|
942
|
+
LATITUDE: {
|
|
943
|
+
type: 'latitude.type',
|
|
944
|
+
documentUuid: 'latitude.document_uuid',
|
|
945
|
+
promptPath: 'latitude.prompt_path',
|
|
946
|
+
commitUuid: 'latitude.commit_uuid',
|
|
947
|
+
documentLogUuid: 'latitude.document_log_uuid',
|
|
948
|
+
projectId: 'latitude.project_id',
|
|
949
|
+
experimentUuid: 'latitude.experiment_uuid',
|
|
950
|
+
source: 'latitude.source',
|
|
951
|
+
externalId: 'latitude.external_id',
|
|
952
|
+
testDeploymentId: 'latitude.test_deployment_id',
|
|
953
|
+
previousTraceId: 'latitude.previous_trace_id',
|
|
954
|
+
// Custom additions to the GenAI semantic conventions (deprecated)
|
|
955
|
+
request: {
|
|
956
|
+
_root: 'gen_ai.request',
|
|
957
|
+
configuration: 'gen_ai.request.configuration',
|
|
958
|
+
template: 'gen_ai.request.template',
|
|
959
|
+
parameters: 'gen_ai.request.parameters'},
|
|
960
|
+
response: {
|
|
961
|
+
_root: 'gen_ai.response'},
|
|
962
|
+
usage: {
|
|
963
|
+
promptTokens: 'gen_ai.usage.prompt_tokens',
|
|
964
|
+
cachedTokens: 'gen_ai.usage.cached_tokens',
|
|
965
|
+
reasoningTokens: 'gen_ai.usage.reasoning_tokens',
|
|
966
|
+
completionTokens: 'gen_ai.usage.completion_tokens',
|
|
967
|
+
},
|
|
968
|
+
},
|
|
969
|
+
// Official OpenTelemetry semantic conventions
|
|
970
|
+
OPENTELEMETRY: {
|
|
971
|
+
HTTP: {
|
|
972
|
+
request: {
|
|
973
|
+
url: 'http.request.url',
|
|
974
|
+
body: 'http.request.body',
|
|
975
|
+
header: 'http.request.header',
|
|
976
|
+
method: semanticConventions.ATTR_HTTP_REQUEST_METHOD,
|
|
977
|
+
},
|
|
978
|
+
response: {
|
|
979
|
+
body: 'http.response.body',
|
|
980
|
+
header: 'http.response.header',
|
|
981
|
+
statusCode: semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
982
|
+
},
|
|
983
|
+
},
|
|
984
|
+
// GenAI semantic conventions
|
|
985
|
+
// https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
|
|
986
|
+
GEN_AI: {
|
|
987
|
+
operation: incubating.ATTR_GEN_AI_OPERATION_NAME,
|
|
988
|
+
response: {
|
|
989
|
+
model: incubating.ATTR_GEN_AI_RESPONSE_MODEL,
|
|
990
|
+
finishReasons: incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
|
|
991
|
+
},
|
|
992
|
+
usage: {
|
|
993
|
+
inputTokens: incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS,
|
|
994
|
+
outputTokens: incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
995
|
+
},
|
|
996
|
+
systemInstructions: 'gen_ai.system.instructions', // Contains the PARTS of the "system message"
|
|
997
|
+
tool: {
|
|
998
|
+
call: {
|
|
999
|
+
id: incubating.ATTR_GEN_AI_TOOL_CALL_ID,
|
|
1000
|
+
arguments: 'gen_ai.tool.call.arguments'}},
|
|
1001
|
+
input: {
|
|
1002
|
+
messages: 'gen_ai.input.messages',
|
|
1003
|
+
},
|
|
1004
|
+
output: {
|
|
1005
|
+
messages: 'gen_ai.output.messages',
|
|
1006
|
+
},
|
|
1007
|
+
_deprecated: {
|
|
1008
|
+
system: incubating.ATTR_GEN_AI_SYSTEM,
|
|
1009
|
+
tool: {
|
|
1010
|
+
name: incubating.ATTR_GEN_AI_TOOL_NAME,
|
|
1011
|
+
type: incubating.ATTR_GEN_AI_TOOL_TYPE,
|
|
1012
|
+
result: {
|
|
1013
|
+
value: 'gen_ai.tool.result.value',
|
|
1014
|
+
isError: 'gen_ai.tool.result.is_error',
|
|
1015
|
+
},
|
|
1016
|
+
}},
|
|
1017
|
+
},
|
|
1018
|
+
}};
|
|
1019
|
+
const VALUES = {
|
|
1020
|
+
OPENTELEMETRY: {
|
|
1021
|
+
GEN_AI: {
|
|
1022
|
+
response: {
|
|
1023
|
+
finishReasons: {
|
|
1024
|
+
stop: 'stop',
|
|
1025
|
+
toolCalls: 'tool_calls'},
|
|
1026
|
+
},
|
|
1027
|
+
tool: {
|
|
1028
|
+
type: {
|
|
1029
|
+
function: 'function',
|
|
1030
|
+
},
|
|
1031
|
+
}},
|
|
1032
|
+
}};
|
|
1033
|
+
|
|
902
1034
|
/* Note: Instrumentation scopes from all language SDKs */
|
|
903
1035
|
const SCOPE_LATITUDE = 'so.latitude.instrumentation';
|
|
904
1036
|
var InstrumentationScope;
|
|
@@ -927,52 +1059,6 @@ var InstrumentationScope;
|
|
|
927
1059
|
InstrumentationScope["Transformers"] = "transformers";
|
|
928
1060
|
InstrumentationScope["AlephAlpha"] = "alephalpha";
|
|
929
1061
|
})(InstrumentationScope || (InstrumentationScope = {}));
|
|
930
|
-
/* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
|
|
931
|
-
const ATTR_LATITUDE = 'latitude';
|
|
932
|
-
const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
|
|
933
|
-
const ATTR_LATITUDE_DOCUMENT_UUID = `${ATTR_LATITUDE}.document_uuid`;
|
|
934
|
-
const ATTR_LATITUDE_PROMPT_PATH = `${ATTR_LATITUDE}.prompt_path`;
|
|
935
|
-
const ATTR_LATITUDE_COMMIT_UUID = `${ATTR_LATITUDE}.commit_uuid`;
|
|
936
|
-
const ATTR_LATITUDE_DOCUMENT_LOG_UUID = `${ATTR_LATITUDE}.document_log_uuid`;
|
|
937
|
-
const ATTR_LATITUDE_PROJECT_ID = `${ATTR_LATITUDE}.project_id`;
|
|
938
|
-
const ATTR_LATITUDE_EXPERIMENT_UUID = `${ATTR_LATITUDE}.experiment_uuid`;
|
|
939
|
-
const ATTR_LATITUDE_SOURCE = `${ATTR_LATITUDE}.source`;
|
|
940
|
-
const ATTR_LATITUDE_EXTERNAL_ID = `${ATTR_LATITUDE}.external_id`;
|
|
941
|
-
const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
|
|
942
|
-
const ATTR_LATITUDE_PREVIOUS_TRACE_ID = `${ATTR_LATITUDE}.previous_trace_id`;
|
|
943
|
-
const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
|
|
944
|
-
const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
|
|
945
|
-
const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
|
|
946
|
-
const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
|
|
947
|
-
const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
|
|
948
|
-
const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
|
|
949
|
-
const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
|
|
950
|
-
const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
|
|
951
|
-
const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
|
|
952
|
-
const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
|
|
953
|
-
const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
|
|
954
|
-
const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
|
|
955
|
-
const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
|
|
956
|
-
const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
|
|
957
|
-
const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
|
|
958
|
-
const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
|
|
959
|
-
const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
|
|
960
|
-
const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
|
|
961
|
-
const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
|
|
962
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
|
|
963
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
|
|
964
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
|
|
965
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
|
|
966
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
|
|
967
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
|
|
968
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
|
|
969
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
|
|
970
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
|
|
971
|
-
const ATTR_HTTP_REQUEST_URL = 'http.request.url';
|
|
972
|
-
const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
|
|
973
|
-
const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
|
|
974
|
-
const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
|
|
975
|
-
const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
|
|
976
1062
|
/* Note: Schemas for span ingestion following OpenTelemetry service request specification */
|
|
977
1063
|
var Otlp;
|
|
978
1064
|
(function (Otlp) {
|
|
@@ -1053,6 +1139,54 @@ var Otlp;
|
|
|
1053
1139
|
});
|
|
1054
1140
|
})(Otlp || (Otlp = {}));
|
|
1055
1141
|
|
|
1142
|
+
const MAX_SIMULATION_TURNS = 10;
|
|
1143
|
+
const globalGoalSourceSchema = zod.z.object({
|
|
1144
|
+
type: zod.z.literal('global'),
|
|
1145
|
+
value: zod.z.string(),
|
|
1146
|
+
});
|
|
1147
|
+
const columnGoalSourceSchema = zod.z.object({
|
|
1148
|
+
type: zod.z.literal('column'),
|
|
1149
|
+
columnIndex: zod.z.number(),
|
|
1150
|
+
});
|
|
1151
|
+
const simulatedUserGoalSourceSchema = zod.z.discriminatedUnion('type', [
|
|
1152
|
+
globalGoalSourceSchema,
|
|
1153
|
+
columnGoalSourceSchema,
|
|
1154
|
+
]);
|
|
1155
|
+
const SimulationSettingsSchema = zod.z.object({
|
|
1156
|
+
simulateToolResponses: zod.z.boolean().optional(),
|
|
1157
|
+
simulatedTools: zod.z.array(zod.z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
|
|
1158
|
+
toolSimulationInstructions: zod.z.string().optional(), // A prompt used to guide and generate the simulation result
|
|
1159
|
+
maxTurns: zod.z.number().min(1).max(MAX_SIMULATION_TURNS).optional(), // The maximum number of turns to simulate. Default is 1, and any greater value will add a new user message to the simulated conversation.
|
|
1160
|
+
simulatedUserGoal: zod.z.string().optional(), // Deprecated: Use simulatedUserGoalSource instead. Kept for backward compatibility.
|
|
1161
|
+
simulatedUserGoalSource: simulatedUserGoalSourceSchema.optional(), // The source for the simulated user goal (global text or dataset column).
|
|
1162
|
+
});
|
|
1163
|
+
|
|
1164
|
+
var OptimizationEngine;
|
|
1165
|
+
(function (OptimizationEngine) {
|
|
1166
|
+
OptimizationEngine["Identity"] = "identity";
|
|
1167
|
+
OptimizationEngine["Gepa"] = "gepa";
|
|
1168
|
+
})(OptimizationEngine || (OptimizationEngine = {}));
|
|
1169
|
+
const OptimizationBudgetSchema = zod.z.object({
|
|
1170
|
+
time: zod.z.number().min(0).optional(),
|
|
1171
|
+
tokens: zod.z.number().min(0).optional(),
|
|
1172
|
+
});
|
|
1173
|
+
zod.z.object({
|
|
1174
|
+
parameters: zod.z
|
|
1175
|
+
.record(zod.z.string(), zod.z.object({
|
|
1176
|
+
column: zod.z.string().optional(), // Note: corresponding column in the user-provided trainset and testset
|
|
1177
|
+
isPii: zod.z.boolean().optional(),
|
|
1178
|
+
}))
|
|
1179
|
+
.optional(),
|
|
1180
|
+
simulation: SimulationSettingsSchema.optional(),
|
|
1181
|
+
scope: zod.z
|
|
1182
|
+
.object({
|
|
1183
|
+
configuration: zod.z.boolean().optional(),
|
|
1184
|
+
instructions: zod.z.boolean().optional(),
|
|
1185
|
+
})
|
|
1186
|
+
.optional(),
|
|
1187
|
+
budget: OptimizationBudgetSchema.optional(),
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1056
1190
|
// TODO(tracing): deprecated
|
|
1057
1191
|
const HEAD_COMMIT = 'live';
|
|
1058
1192
|
var Providers;
|
|
@@ -1098,12 +1232,18 @@ var DocumentTriggerParameters;
|
|
|
1098
1232
|
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
1099
1233
|
const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
|
|
1100
1234
|
|
|
1235
|
+
const translator = new rosettaAi.Translator({
|
|
1236
|
+
filterEmptyMessages: true,
|
|
1237
|
+
providerMetadata: 'preserve',
|
|
1238
|
+
});
|
|
1101
1239
|
class ManualInstrumentation {
|
|
1102
1240
|
enabled;
|
|
1103
1241
|
tracer;
|
|
1104
|
-
|
|
1242
|
+
options;
|
|
1243
|
+
constructor(tracer, options) {
|
|
1105
1244
|
this.enabled = false;
|
|
1106
1245
|
this.tracer = tracer;
|
|
1246
|
+
this.options = options ?? {};
|
|
1107
1247
|
}
|
|
1108
1248
|
isEnabled() {
|
|
1109
1249
|
return this.enabled;
|
|
@@ -1143,36 +1283,6 @@ class ManualInstrumentation {
|
|
|
1143
1283
|
}
|
|
1144
1284
|
return context;
|
|
1145
1285
|
}
|
|
1146
|
-
capitalize(str) {
|
|
1147
|
-
if (str.length === 0)
|
|
1148
|
-
return str;
|
|
1149
|
-
return str.charAt(0).toUpperCase() + str.toLowerCase().slice(1);
|
|
1150
|
-
}
|
|
1151
|
-
toCamelCase(str) {
|
|
1152
|
-
return str
|
|
1153
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
1154
|
-
.replace(/[^A-Za-z0-9]+/g, ' ')
|
|
1155
|
-
.trim()
|
|
1156
|
-
.split(' ')
|
|
1157
|
-
.map((w, i) => (i ? this.capitalize(w) : w.toLowerCase()))
|
|
1158
|
-
.join('');
|
|
1159
|
-
}
|
|
1160
|
-
toSnakeCase(str) {
|
|
1161
|
-
return str
|
|
1162
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
1163
|
-
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
1164
|
-
.replace(/_+/g, '_')
|
|
1165
|
-
.replace(/^_+|_+$/g, '')
|
|
1166
|
-
.toLowerCase();
|
|
1167
|
-
}
|
|
1168
|
-
toKebabCase(input) {
|
|
1169
|
-
return input
|
|
1170
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
1171
|
-
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
1172
|
-
.replace(/-+/g, '-')
|
|
1173
|
-
.replace(/^-+|-+$/g, '')
|
|
1174
|
-
.toLowerCase();
|
|
1175
|
-
}
|
|
1176
1286
|
error(span, error, options) {
|
|
1177
1287
|
options = options || {};
|
|
1178
1288
|
span.recordException(error);
|
|
@@ -1198,9 +1308,9 @@ class ManualInstrumentation {
|
|
|
1198
1308
|
}
|
|
1199
1309
|
const span = this.tracer.startSpan(name, {
|
|
1200
1310
|
attributes: {
|
|
1201
|
-
[
|
|
1311
|
+
[ATTRIBUTES.LATITUDE.type]: type,
|
|
1202
1312
|
...(operation && {
|
|
1203
|
-
[
|
|
1313
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
|
|
1204
1314
|
}),
|
|
1205
1315
|
...(start.attributes || {}),
|
|
1206
1316
|
},
|
|
@@ -1220,26 +1330,29 @@ class ManualInstrumentation {
|
|
|
1220
1330
|
},
|
|
1221
1331
|
};
|
|
1222
1332
|
}
|
|
1333
|
+
unknown(ctx, options) {
|
|
1334
|
+
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Unknown].name, SpanType.Unknown, options);
|
|
1335
|
+
}
|
|
1223
1336
|
tool(ctx, options) {
|
|
1224
1337
|
const start = options;
|
|
1225
1338
|
let jsonArguments = '';
|
|
1226
1339
|
try {
|
|
1227
1340
|
jsonArguments = JSON.stringify(start.call.arguments);
|
|
1228
1341
|
}
|
|
1229
|
-
catch (
|
|
1342
|
+
catch (_error) {
|
|
1230
1343
|
jsonArguments = '{}';
|
|
1231
1344
|
}
|
|
1232
1345
|
const span = this.span(ctx, start.name, SpanType.Tool, {
|
|
1233
1346
|
attributes: {
|
|
1234
|
-
[
|
|
1235
|
-
[
|
|
1236
|
-
[
|
|
1237
|
-
[
|
|
1347
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
|
|
1348
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
|
|
1349
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
|
|
1350
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
|
|
1238
1351
|
...(start.attributes || {}),
|
|
1239
1352
|
},
|
|
1240
1353
|
});
|
|
1241
1354
|
return {
|
|
1242
|
-
|
|
1355
|
+
...span,
|
|
1243
1356
|
end: (options) => {
|
|
1244
1357
|
const end = options;
|
|
1245
1358
|
let stringResult = '';
|
|
@@ -1247,7 +1360,7 @@ class ManualInstrumentation {
|
|
|
1247
1360
|
try {
|
|
1248
1361
|
stringResult = JSON.stringify(end.result.value);
|
|
1249
1362
|
}
|
|
1250
|
-
catch (
|
|
1363
|
+
catch (_error) {
|
|
1251
1364
|
stringResult = '{}';
|
|
1252
1365
|
}
|
|
1253
1366
|
}
|
|
@@ -1256,180 +1369,21 @@ class ManualInstrumentation {
|
|
|
1256
1369
|
}
|
|
1257
1370
|
span.end({
|
|
1258
1371
|
attributes: {
|
|
1259
|
-
[
|
|
1260
|
-
[
|
|
1372
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
|
|
1373
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
|
|
1261
1374
|
...(end.attributes || {}),
|
|
1262
1375
|
},
|
|
1263
1376
|
});
|
|
1264
1377
|
},
|
|
1265
|
-
fail: span.fail,
|
|
1266
1378
|
};
|
|
1267
1379
|
}
|
|
1268
|
-
attribifyMessageToolCalls(prefix, toolCalls) {
|
|
1269
|
-
const attributes = {};
|
|
1270
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
1271
|
-
for (const key in toolCalls[i]) {
|
|
1272
|
-
const field = this.toCamelCase(key);
|
|
1273
|
-
let value = toolCalls[i][key];
|
|
1274
|
-
if (value === null || value === undefined)
|
|
1275
|
-
continue;
|
|
1276
|
-
switch (field) {
|
|
1277
|
-
case 'id':
|
|
1278
|
-
case 'toolCallId':
|
|
1279
|
-
case 'toolUseId': {
|
|
1280
|
-
if (typeof value !== 'string')
|
|
1281
|
-
continue;
|
|
1282
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID}`] = value;
|
|
1283
|
-
break;
|
|
1284
|
-
}
|
|
1285
|
-
case 'name':
|
|
1286
|
-
case 'toolName': {
|
|
1287
|
-
if (typeof value !== 'string')
|
|
1288
|
-
continue;
|
|
1289
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value;
|
|
1290
|
-
break;
|
|
1291
|
-
}
|
|
1292
|
-
case 'arguments':
|
|
1293
|
-
case 'toolArguments':
|
|
1294
|
-
case 'input': {
|
|
1295
|
-
if (typeof value === 'string') {
|
|
1296
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value;
|
|
1297
|
-
}
|
|
1298
|
-
else {
|
|
1299
|
-
try {
|
|
1300
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = JSON.stringify(value);
|
|
1301
|
-
}
|
|
1302
|
-
catch (error) {
|
|
1303
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = '{}';
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
break;
|
|
1307
|
-
}
|
|
1308
|
-
/* OpenAI function calls */
|
|
1309
|
-
case 'function': {
|
|
1310
|
-
if (typeof value !== 'object')
|
|
1311
|
-
continue;
|
|
1312
|
-
if (!('name' in value))
|
|
1313
|
-
continue;
|
|
1314
|
-
if (typeof value.name !== 'string')
|
|
1315
|
-
continue;
|
|
1316
|
-
if (!('arguments' in value))
|
|
1317
|
-
continue;
|
|
1318
|
-
if (typeof value.arguments !== 'string')
|
|
1319
|
-
continue;
|
|
1320
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value.name;
|
|
1321
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value.arguments;
|
|
1322
|
-
break;
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
return attributes;
|
|
1328
|
-
}
|
|
1329
|
-
attribifyMessageContent(prefix, content) {
|
|
1330
|
-
let attributes = {};
|
|
1331
|
-
if (typeof content === 'string') {
|
|
1332
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
|
|
1333
|
-
return attributes;
|
|
1334
|
-
}
|
|
1335
|
-
try {
|
|
1336
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] =
|
|
1337
|
-
JSON.stringify(content);
|
|
1338
|
-
}
|
|
1339
|
-
catch (error) {
|
|
1340
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = '[]';
|
|
1341
|
-
}
|
|
1342
|
-
if (!Array.isArray(content))
|
|
1343
|
-
return attributes;
|
|
1344
|
-
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1345
|
-
const toolCalls = [];
|
|
1346
|
-
for (const item of content) {
|
|
1347
|
-
for (const key in item) {
|
|
1348
|
-
if (this.toCamelCase(key) !== 'type')
|
|
1349
|
-
continue;
|
|
1350
|
-
if (typeof item[key] !== 'string')
|
|
1351
|
-
continue;
|
|
1352
|
-
if (item[key] !== 'tool-call' && item[key] !== 'tool_use')
|
|
1353
|
-
continue;
|
|
1354
|
-
toolCalls.push(item);
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
if (toolCalls.length > 0) {
|
|
1358
|
-
attributes = {
|
|
1359
|
-
...attributes,
|
|
1360
|
-
...this.attribifyMessageToolCalls(prefix, toolCalls),
|
|
1361
|
-
};
|
|
1362
|
-
}
|
|
1363
|
-
return attributes;
|
|
1364
|
-
}
|
|
1365
|
-
attribifyMessages(direction, messages) {
|
|
1366
|
-
const prefix = direction === 'input' ? ATTR_GEN_AI_PROMPTS : ATTR_GEN_AI_COMPLETIONS;
|
|
1367
|
-
let attributes = {};
|
|
1368
|
-
for (let i = 0; i < messages.length; i++) {
|
|
1369
|
-
for (const key in messages[i]) {
|
|
1370
|
-
const field = this.toCamelCase(key);
|
|
1371
|
-
let value = messages[i][key];
|
|
1372
|
-
if (value === null || value === undefined)
|
|
1373
|
-
continue;
|
|
1374
|
-
switch (field) {
|
|
1375
|
-
case 'role': {
|
|
1376
|
-
if (typeof value !== 'string')
|
|
1377
|
-
continue;
|
|
1378
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_ROLE}`] = value;
|
|
1379
|
-
break;
|
|
1380
|
-
}
|
|
1381
|
-
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1382
|
-
case 'content': {
|
|
1383
|
-
attributes = {
|
|
1384
|
-
...attributes,
|
|
1385
|
-
...this.attribifyMessageContent(`${prefix}.${i}`, value),
|
|
1386
|
-
};
|
|
1387
|
-
break;
|
|
1388
|
-
}
|
|
1389
|
-
/* Tool calls for OpenAI */
|
|
1390
|
-
case 'toolCalls': {
|
|
1391
|
-
if (!Array.isArray(value))
|
|
1392
|
-
continue;
|
|
1393
|
-
attributes = {
|
|
1394
|
-
...attributes,
|
|
1395
|
-
...this.attribifyMessageToolCalls(`${prefix}.${i}`, value),
|
|
1396
|
-
};
|
|
1397
|
-
break;
|
|
1398
|
-
}
|
|
1399
|
-
/* Tool result for OpenAI / Anthropic / PromptL */
|
|
1400
|
-
case 'toolCallId':
|
|
1401
|
-
case 'toolId':
|
|
1402
|
-
case 'toolUseId': {
|
|
1403
|
-
if (typeof value !== 'string')
|
|
1404
|
-
continue;
|
|
1405
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID}`] =
|
|
1406
|
-
value;
|
|
1407
|
-
break;
|
|
1408
|
-
}
|
|
1409
|
-
case 'toolName': {
|
|
1410
|
-
if (typeof value !== 'string')
|
|
1411
|
-
continue;
|
|
1412
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_NAME}`] =
|
|
1413
|
-
value;
|
|
1414
|
-
break;
|
|
1415
|
-
}
|
|
1416
|
-
// Note: 'toolResult' is 'content' itself
|
|
1417
|
-
case 'isError': {
|
|
1418
|
-
if (typeof value !== 'boolean')
|
|
1419
|
-
continue;
|
|
1420
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR}`] = value;
|
|
1421
|
-
break;
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
return attributes;
|
|
1427
|
-
}
|
|
1428
1380
|
attribifyConfiguration(direction, configuration) {
|
|
1429
|
-
const prefix = direction === 'input'
|
|
1381
|
+
const prefix = direction === 'input'
|
|
1382
|
+
? ATTRIBUTES.LATITUDE.request._root
|
|
1383
|
+
: ATTRIBUTES.LATITUDE.response._root;
|
|
1430
1384
|
const attributes = {};
|
|
1431
1385
|
for (const key in configuration) {
|
|
1432
|
-
const field =
|
|
1386
|
+
const field = toSnakeCase(key);
|
|
1433
1387
|
let value = configuration[key];
|
|
1434
1388
|
if (value === null || value === undefined)
|
|
1435
1389
|
continue;
|
|
@@ -1437,7 +1391,7 @@ class ManualInstrumentation {
|
|
|
1437
1391
|
try {
|
|
1438
1392
|
value = JSON.stringify(value);
|
|
1439
1393
|
}
|
|
1440
|
-
catch (
|
|
1394
|
+
catch (_error) {
|
|
1441
1395
|
value = '{}';
|
|
1442
1396
|
}
|
|
1443
1397
|
}
|
|
@@ -1455,45 +1409,56 @@ class ManualInstrumentation {
|
|
|
1455
1409
|
try {
|
|
1456
1410
|
jsonConfiguration = JSON.stringify(configuration);
|
|
1457
1411
|
}
|
|
1458
|
-
catch (
|
|
1412
|
+
catch (_error) {
|
|
1459
1413
|
jsonConfiguration = '{}';
|
|
1460
1414
|
}
|
|
1461
1415
|
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1462
1416
|
const input = start.input ?? [];
|
|
1417
|
+
let jsonSystem = '';
|
|
1463
1418
|
let jsonInput = '';
|
|
1464
1419
|
try {
|
|
1465
|
-
|
|
1420
|
+
const translated = translator.translate(input, {
|
|
1421
|
+
from: this.options.provider,
|
|
1422
|
+
to: rosettaAi.Provider.GenAI,
|
|
1423
|
+
direction: 'input',
|
|
1424
|
+
});
|
|
1425
|
+
jsonSystem = JSON.stringify(translated.system ?? []);
|
|
1426
|
+
jsonInput = JSON.stringify(translated.messages ?? []);
|
|
1466
1427
|
}
|
|
1467
|
-
catch (
|
|
1428
|
+
catch (_error) {
|
|
1429
|
+
jsonSystem = '[]';
|
|
1468
1430
|
jsonInput = '[]';
|
|
1469
1431
|
}
|
|
1470
|
-
const attrInput = this.attribifyMessages('input', input);
|
|
1471
1432
|
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1472
1433
|
attributes: {
|
|
1473
|
-
[
|
|
1474
|
-
[
|
|
1434
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
|
|
1435
|
+
[ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
|
|
1475
1436
|
...attrConfiguration,
|
|
1476
|
-
[
|
|
1477
|
-
|
|
1437
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.systemInstructions]: jsonSystem,
|
|
1438
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.input.messages]: jsonInput,
|
|
1478
1439
|
...(start.attributes || {}),
|
|
1479
|
-
[
|
|
1480
|
-
[
|
|
1481
|
-
[
|
|
1440
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
|
|
1441
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
|
|
1442
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
|
|
1482
1443
|
},
|
|
1483
1444
|
});
|
|
1484
1445
|
return {
|
|
1485
|
-
|
|
1446
|
+
...span,
|
|
1486
1447
|
end: (options) => {
|
|
1487
1448
|
const end = options ?? {};
|
|
1488
1449
|
const output = end.output ?? [];
|
|
1489
1450
|
let jsonOutput = '';
|
|
1490
1451
|
try {
|
|
1491
|
-
|
|
1452
|
+
const translated = translator.translate(output, {
|
|
1453
|
+
from: this.options.provider,
|
|
1454
|
+
to: rosettaAi.Provider.GenAI,
|
|
1455
|
+
direction: 'output',
|
|
1456
|
+
});
|
|
1457
|
+
jsonOutput = JSON.stringify(translated.messages ?? []);
|
|
1492
1458
|
}
|
|
1493
|
-
catch (
|
|
1459
|
+
catch (_error) {
|
|
1494
1460
|
jsonOutput = '[]';
|
|
1495
1461
|
}
|
|
1496
|
-
const attrOutput = this.attribifyMessages('output', output);
|
|
1497
1462
|
const tokens = {
|
|
1498
1463
|
prompt: end.tokens?.prompt ?? 0,
|
|
1499
1464
|
cached: end.tokens?.cached ?? 0,
|
|
@@ -1505,39 +1470,33 @@ class ManualInstrumentation {
|
|
|
1505
1470
|
const finishReason = end.finishReason ?? '';
|
|
1506
1471
|
span.end({
|
|
1507
1472
|
attributes: {
|
|
1508
|
-
[
|
|
1509
|
-
|
|
1510
|
-
[
|
|
1511
|
-
[
|
|
1512
|
-
[
|
|
1513
|
-
[
|
|
1514
|
-
[
|
|
1515
|
-
[
|
|
1516
|
-
[
|
|
1517
|
-
|
|
1473
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.output.messages]: jsonOutput,
|
|
1474
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
|
|
1475
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
|
|
1476
|
+
[ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
|
|
1477
|
+
[ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
|
|
1478
|
+
[ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
|
|
1479
|
+
[ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
|
|
1480
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
|
|
1481
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
|
|
1482
|
+
finishReason,
|
|
1483
|
+
],
|
|
1518
1484
|
...(end.attributes || {}),
|
|
1519
1485
|
},
|
|
1520
1486
|
});
|
|
1521
1487
|
},
|
|
1522
|
-
fail: span.fail,
|
|
1523
1488
|
};
|
|
1524
1489
|
}
|
|
1525
1490
|
embedding(ctx, options) {
|
|
1526
1491
|
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
|
|
1527
1492
|
}
|
|
1528
|
-
retrieval(ctx, options) {
|
|
1529
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Retrieval].name, SpanType.Retrieval, options);
|
|
1530
|
-
}
|
|
1531
|
-
reranking(ctx, options) {
|
|
1532
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Reranking].name, SpanType.Reranking, options);
|
|
1533
|
-
}
|
|
1534
1493
|
attribifyHeaders(direction, headers) {
|
|
1535
1494
|
const prefix = direction === 'request'
|
|
1536
|
-
?
|
|
1537
|
-
:
|
|
1495
|
+
? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
|
|
1496
|
+
: ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
|
|
1538
1497
|
const attributes = {};
|
|
1539
1498
|
for (const key in headers) {
|
|
1540
|
-
const field =
|
|
1499
|
+
const field = toKebabCase(key);
|
|
1541
1500
|
const value = headers[key];
|
|
1542
1501
|
if (value === null || value === undefined)
|
|
1543
1502
|
continue;
|
|
@@ -1558,21 +1517,21 @@ class ManualInstrumentation {
|
|
|
1558
1517
|
try {
|
|
1559
1518
|
finalBody = JSON.stringify(start.request.body);
|
|
1560
1519
|
}
|
|
1561
|
-
catch (
|
|
1520
|
+
catch (_error) {
|
|
1562
1521
|
finalBody = '{}';
|
|
1563
1522
|
}
|
|
1564
1523
|
}
|
|
1565
1524
|
const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
|
|
1566
1525
|
attributes: {
|
|
1567
|
-
[
|
|
1568
|
-
[
|
|
1526
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
|
|
1527
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
|
|
1569
1528
|
...attrHeaders,
|
|
1570
|
-
[
|
|
1529
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
|
|
1571
1530
|
...(start.attributes || {}),
|
|
1572
1531
|
},
|
|
1573
1532
|
});
|
|
1574
1533
|
return {
|
|
1575
|
-
|
|
1534
|
+
...span,
|
|
1576
1535
|
end: (options) => {
|
|
1577
1536
|
const end = options;
|
|
1578
1537
|
// Note: do not serialize headers as a single attribute because fields won't be redacted
|
|
@@ -1585,20 +1544,19 @@ class ManualInstrumentation {
|
|
|
1585
1544
|
try {
|
|
1586
1545
|
finalBody = JSON.stringify(end.response.body);
|
|
1587
1546
|
}
|
|
1588
|
-
catch (
|
|
1547
|
+
catch (_error) {
|
|
1589
1548
|
finalBody = '{}';
|
|
1590
1549
|
}
|
|
1591
1550
|
}
|
|
1592
1551
|
span.end({
|
|
1593
1552
|
attributes: {
|
|
1594
|
-
[
|
|
1553
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
|
|
1595
1554
|
...attrHeaders,
|
|
1596
|
-
[
|
|
1555
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
|
|
1597
1556
|
...(end.attributes || {}),
|
|
1598
1557
|
},
|
|
1599
1558
|
});
|
|
1600
1559
|
},
|
|
1601
|
-
fail: span.fail,
|
|
1602
1560
|
};
|
|
1603
1561
|
}
|
|
1604
1562
|
prompt(ctx, { documentLogUuid, versionUuid, promptUuid, projectId, experimentUuid, testDeploymentId, externalId, template, parameters, name, source, ...rest }) {
|
|
@@ -1606,49 +1564,50 @@ class ManualInstrumentation {
|
|
|
1606
1564
|
try {
|
|
1607
1565
|
jsonParameters = JSON.stringify(parameters || {});
|
|
1608
1566
|
}
|
|
1609
|
-
catch (
|
|
1567
|
+
catch (_error) {
|
|
1610
1568
|
jsonParameters = '{}';
|
|
1611
1569
|
}
|
|
1612
1570
|
const attributes = {
|
|
1613
|
-
[
|
|
1614
|
-
[
|
|
1615
|
-
[
|
|
1616
|
-
[
|
|
1617
|
-
[
|
|
1618
|
-
[
|
|
1571
|
+
[ATTRIBUTES.LATITUDE.request.template]: template,
|
|
1572
|
+
[ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
|
|
1573
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
|
|
1574
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1575
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1576
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1619
1577
|
...(experimentUuid && {
|
|
1620
|
-
[
|
|
1578
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
|
|
1621
1579
|
}),
|
|
1622
1580
|
...(testDeploymentId && {
|
|
1623
|
-
[
|
|
1581
|
+
[ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
|
|
1624
1582
|
}),
|
|
1625
|
-
...(externalId && { [
|
|
1626
|
-
...(source && { [
|
|
1583
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1584
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1627
1585
|
...(rest.attributes || {}),
|
|
1628
1586
|
};
|
|
1629
1587
|
return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
|
|
1630
1588
|
attributes,
|
|
1631
1589
|
});
|
|
1632
1590
|
}
|
|
1633
|
-
|
|
1634
|
-
return this.span(ctx, 'step', SpanType.Step, options);
|
|
1635
|
-
}
|
|
1636
|
-
chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
|
|
1591
|
+
chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
|
|
1637
1592
|
const attributes = {
|
|
1638
|
-
[
|
|
1639
|
-
[
|
|
1640
|
-
...(
|
|
1593
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1594
|
+
[ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
|
|
1595
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1596
|
+
...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
|
|
1597
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1641
1598
|
...(rest.attributes || {}),
|
|
1642
1599
|
};
|
|
1643
|
-
return this.span(ctx, name ||
|
|
1600
|
+
return this.span(ctx, name || `chat-${documentLogUuid}`, SpanType.Chat, {
|
|
1601
|
+
attributes,
|
|
1602
|
+
});
|
|
1644
1603
|
}
|
|
1645
1604
|
external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
|
|
1646
1605
|
const attributes = {
|
|
1647
|
-
[
|
|
1648
|
-
[
|
|
1649
|
-
[
|
|
1650
|
-
...(versionUuid && { [
|
|
1651
|
-
...(externalId && { [
|
|
1606
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1607
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1608
|
+
[ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
|
|
1609
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1610
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1652
1611
|
...(rest.attributes || {}),
|
|
1653
1612
|
};
|
|
1654
1613
|
return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
|
|
@@ -1657,11 +1616,11 @@ class ManualInstrumentation {
|
|
|
1657
1616
|
}
|
|
1658
1617
|
unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
|
|
1659
1618
|
const attributes = {
|
|
1660
|
-
[
|
|
1661
|
-
[
|
|
1662
|
-
...(versionUuid && { [
|
|
1619
|
+
[ATTRIBUTES.LATITUDE.promptPath]: path,
|
|
1620
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1621
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1663
1622
|
...(conversationUuid && {
|
|
1664
|
-
[
|
|
1623
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
|
|
1665
1624
|
}),
|
|
1666
1625
|
...(rest.attributes || {}),
|
|
1667
1626
|
};
|
|
@@ -1680,8 +1639,8 @@ class LatitudeInstrumentation {
|
|
|
1680
1639
|
return this.manualTelemetry.isEnabled();
|
|
1681
1640
|
}
|
|
1682
1641
|
enable() {
|
|
1683
|
-
this.options.module.instrument(this);
|
|
1684
1642
|
this.manualTelemetry.enable();
|
|
1643
|
+
this.options.module.instrument(this);
|
|
1685
1644
|
}
|
|
1686
1645
|
disable() {
|
|
1687
1646
|
this.manualTelemetry.disable();
|
|
@@ -1726,19 +1685,6 @@ class LatitudeInstrumentation {
|
|
|
1726
1685
|
$prompt.end();
|
|
1727
1686
|
return result;
|
|
1728
1687
|
}
|
|
1729
|
-
async wrapRenderStep(fn, ...args) {
|
|
1730
|
-
const $step = this.manualTelemetry.step(otel.context.active());
|
|
1731
|
-
let result;
|
|
1732
|
-
try {
|
|
1733
|
-
result = await otel.context.with($step.context, async () => await fn(...args));
|
|
1734
|
-
}
|
|
1735
|
-
catch (error) {
|
|
1736
|
-
$step.fail(error);
|
|
1737
|
-
throw error;
|
|
1738
|
-
}
|
|
1739
|
-
$step.end();
|
|
1740
|
-
return result;
|
|
1741
|
-
}
|
|
1742
1688
|
async wrapRenderCompletion(fn, ...args) {
|
|
1743
1689
|
if (!this.options.completions) {
|
|
1744
1690
|
return await fn(...args);
|
|
@@ -1772,8 +1718,8 @@ class LatitudeInstrumentation {
|
|
|
1772
1718
|
completion: completionTokens,
|
|
1773
1719
|
},
|
|
1774
1720
|
finishReason: result.toolRequests.length > 0
|
|
1775
|
-
?
|
|
1776
|
-
:
|
|
1721
|
+
? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
|
|
1722
|
+
: VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
|
|
1777
1723
|
});
|
|
1778
1724
|
return result;
|
|
1779
1725
|
}
|
|
@@ -1818,6 +1764,7 @@ var LatitudeErrorCodes;
|
|
|
1818
1764
|
LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
|
|
1819
1765
|
LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
|
|
1820
1766
|
LatitudeErrorCodes["AbortedError"] = "AbortedError";
|
|
1767
|
+
LatitudeErrorCodes["BillingError"] = "BillingError";
|
|
1821
1768
|
})(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
|
|
1822
1769
|
// NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
|
|
1823
1770
|
var RunErrorCodes;
|
|
@@ -1888,6 +1835,9 @@ class SpanFactory {
|
|
|
1888
1835
|
constructor(telemetry) {
|
|
1889
1836
|
this.telemetry = telemetry;
|
|
1890
1837
|
}
|
|
1838
|
+
span(options, ctx) {
|
|
1839
|
+
return this.telemetry.unknown(ctx ?? otel.context.active(), options);
|
|
1840
|
+
}
|
|
1891
1841
|
tool(options, ctx) {
|
|
1892
1842
|
return this.telemetry.tool(ctx ?? otel.context.active(), options);
|
|
1893
1843
|
}
|
|
@@ -1897,21 +1847,12 @@ class SpanFactory {
|
|
|
1897
1847
|
embedding(options, ctx) {
|
|
1898
1848
|
return this.telemetry.embedding(ctx ?? otel.context.active(), options);
|
|
1899
1849
|
}
|
|
1900
|
-
retrieval(options, ctx) {
|
|
1901
|
-
return this.telemetry.retrieval(ctx ?? otel.context.active(), options);
|
|
1902
|
-
}
|
|
1903
|
-
reranking(options, ctx) {
|
|
1904
|
-
return this.telemetry.reranking(ctx ?? otel.context.active(), options);
|
|
1905
|
-
}
|
|
1906
1850
|
http(options, ctx) {
|
|
1907
1851
|
return this.telemetry.http(ctx ?? otel.context.active(), options);
|
|
1908
1852
|
}
|
|
1909
1853
|
prompt(options, ctx) {
|
|
1910
1854
|
return this.telemetry.prompt(ctx ?? otel.context.active(), options);
|
|
1911
1855
|
}
|
|
1912
|
-
step(options, ctx) {
|
|
1913
|
-
return this.telemetry.step(ctx ?? otel.context.active(), options);
|
|
1914
|
-
}
|
|
1915
1856
|
chat(options, ctx) {
|
|
1916
1857
|
return this.telemetry.chat(ctx ?? otel.context.active(), options);
|
|
1917
1858
|
}
|
|
@@ -1930,6 +1871,9 @@ class ContextManager {
|
|
|
1930
1871
|
active() {
|
|
1931
1872
|
return otel.context.active();
|
|
1932
1873
|
}
|
|
1874
|
+
with(ctx, fn, thisArg, ...args) {
|
|
1875
|
+
return otel.context.with(ctx, fn, thisArg, ...args);
|
|
1876
|
+
}
|
|
1933
1877
|
}
|
|
1934
1878
|
class InstrumentationManager {
|
|
1935
1879
|
instrumentations;
|
|
@@ -1976,6 +1920,23 @@ class ScopedTracerProvider {
|
|
|
1976
1920
|
return this.provider.getTracer(this.scope, this.version, options);
|
|
1977
1921
|
}
|
|
1978
1922
|
}
|
|
1923
|
+
class LifecycleManager {
|
|
1924
|
+
nodeProvider;
|
|
1925
|
+
exporter;
|
|
1926
|
+
constructor(nodeProvider, exporter) {
|
|
1927
|
+
this.nodeProvider = nodeProvider;
|
|
1928
|
+
this.exporter = exporter;
|
|
1929
|
+
}
|
|
1930
|
+
async flush() {
|
|
1931
|
+
await this.nodeProvider.forceFlush();
|
|
1932
|
+
await this.exporter.forceFlush?.();
|
|
1933
|
+
}
|
|
1934
|
+
async shutdown() {
|
|
1935
|
+
await this.flush();
|
|
1936
|
+
await this.nodeProvider.shutdown();
|
|
1937
|
+
await this.exporter.shutdown?.();
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1979
1940
|
const DEFAULT_SPAN_EXPORTER = (apiKey) => new exporterTraceOtlpHttp.OTLPTraceExporter({
|
|
1980
1941
|
url: TRACES_URL,
|
|
1981
1942
|
headers: {
|
|
@@ -1994,6 +1955,7 @@ exports.Instrumentation = void 0;
|
|
|
1994
1955
|
Instrumentation["Langchain"] = "langchain";
|
|
1995
1956
|
Instrumentation["Latitude"] = "latitude";
|
|
1996
1957
|
Instrumentation["LlamaIndex"] = "llamaindex";
|
|
1958
|
+
Instrumentation["Manual"] = "manual";
|
|
1997
1959
|
Instrumentation["OpenAI"] = "openai";
|
|
1998
1960
|
Instrumentation["TogetherAI"] = "togetherai";
|
|
1999
1961
|
Instrumentation["VertexAI"] = "vertexai";
|
|
@@ -2007,6 +1969,7 @@ class LatitudeTelemetry {
|
|
|
2007
1969
|
context;
|
|
2008
1970
|
instrumentation;
|
|
2009
1971
|
tracer;
|
|
1972
|
+
lifecycle;
|
|
2010
1973
|
constructor(apiKey, options) {
|
|
2011
1974
|
this.options = options || {};
|
|
2012
1975
|
if (!this.options.exporter) {
|
|
@@ -2023,6 +1986,7 @@ class LatitudeTelemetry {
|
|
|
2023
1986
|
this.nodeProvider = new sdkTraceNode.NodeTracerProvider({
|
|
2024
1987
|
resource: new resources.Resource({ [semanticConventions.ATTR_SERVICE_NAME]: SERVICE_NAME }),
|
|
2025
1988
|
});
|
|
1989
|
+
this.lifecycle = new LifecycleManager(this.nodeProvider, this.options.exporter);
|
|
2026
1990
|
// Note: important, must run before the exporter span processors
|
|
2027
1991
|
this.nodeProvider.addSpanProcessor(new baggageSpanProcessor.BaggageSpanProcessor(baggageSpanProcessor.ALLOW_ALL_BAGGAGE_KEYS));
|
|
2028
1992
|
if (this.options.processors) {
|
|
@@ -2052,19 +2016,16 @@ class LatitudeTelemetry {
|
|
|
2052
2016
|
this.context = new ContextManager(this.manualInstrumentation);
|
|
2053
2017
|
}
|
|
2054
2018
|
async flush() {
|
|
2055
|
-
await this.
|
|
2056
|
-
await this.options.exporter.forceFlush?.();
|
|
2019
|
+
await this.lifecycle.flush();
|
|
2057
2020
|
}
|
|
2058
2021
|
async shutdown() {
|
|
2059
|
-
await this.
|
|
2060
|
-
await this.nodeProvider.shutdown();
|
|
2061
|
-
await this.options.exporter.shutdown?.();
|
|
2022
|
+
await this.lifecycle.shutdown();
|
|
2062
2023
|
}
|
|
2063
2024
|
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
2064
2025
|
initInstrumentations() {
|
|
2065
2026
|
this.instrumentationsList = [];
|
|
2066
|
-
const tracer = this.tracer.get(
|
|
2067
|
-
this.manualInstrumentation = new ManualInstrumentation(tracer);
|
|
2027
|
+
const tracer = this.tracer.get(exports.Instrumentation.Manual);
|
|
2028
|
+
this.manualInstrumentation = new ManualInstrumentation(tracer, this.options.instrumentations?.manual);
|
|
2068
2029
|
this.instrumentationsList.push(this.manualInstrumentation);
|
|
2069
2030
|
const latitude = this.options.instrumentations?.latitude;
|
|
2070
2031
|
if (latitude) {
|
|
@@ -2074,12 +2035,12 @@ class LatitudeTelemetry {
|
|
|
2074
2035
|
}
|
|
2075
2036
|
const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
|
|
2076
2037
|
const providerPkg = this.options.instrumentations?.[instrumentationType];
|
|
2038
|
+
if (!providerPkg)
|
|
2039
|
+
return;
|
|
2077
2040
|
const provider = this.tracer.provider(instrumentationType);
|
|
2078
2041
|
const instrumentation$1 = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
|
|
2079
2042
|
instrumentation$1.setTracerProvider(provider);
|
|
2080
|
-
|
|
2081
|
-
instrumentation$1.manuallyInstrument(providerPkg);
|
|
2082
|
-
}
|
|
2043
|
+
instrumentation$1.manuallyInstrument(providerPkg);
|
|
2083
2044
|
instrumentation.registerInstrumentations({
|
|
2084
2045
|
instrumentations: [instrumentation$1],
|
|
2085
2046
|
tracerProvider: provider,
|
|
@@ -2092,27 +2053,26 @@ class LatitudeTelemetry {
|
|
|
2092
2053
|
configureInstrumentation(exports.Instrumentation.Cohere, instrumentationCohere.CohereInstrumentation); // prettier-ignore
|
|
2093
2054
|
configureInstrumentation(exports.Instrumentation.Langchain, instrumentationLangchain.LangChainInstrumentation); // prettier-ignore
|
|
2094
2055
|
configureInstrumentation(exports.Instrumentation.LlamaIndex, instrumentationLlamaindex.LlamaIndexInstrumentation); // prettier-ignore
|
|
2095
|
-
|
|
2096
|
-
configureInstrumentation(exports.Instrumentation.
|
|
2056
|
+
// NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
|
|
2057
|
+
configureInstrumentation(exports.Instrumentation.OpenAI, instrumentationOpenai.OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2058
|
+
configureInstrumentation(exports.Instrumentation.TogetherAI, instrumentationTogether.TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2097
2059
|
configureInstrumentation(exports.Instrumentation.VertexAI, instrumentationVertexai.VertexAIInstrumentation); // prettier-ignore
|
|
2098
2060
|
}
|
|
2099
2061
|
async capture(options, fn) {
|
|
2100
2062
|
if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
|
|
2101
2063
|
throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
|
|
2102
2064
|
}
|
|
2103
|
-
const span = this.manualInstrumentation.unresolvedExternal(
|
|
2065
|
+
const span = this.manualInstrumentation.unresolvedExternal(BACKGROUND(), options);
|
|
2066
|
+
let result;
|
|
2104
2067
|
try {
|
|
2105
|
-
|
|
2106
|
-
span.end();
|
|
2107
|
-
return result;
|
|
2068
|
+
result = await otel.context.with(span.context, async () => await fn(span.context));
|
|
2108
2069
|
}
|
|
2109
2070
|
catch (error) {
|
|
2110
2071
|
span.fail(error);
|
|
2111
2072
|
throw error;
|
|
2112
2073
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
}
|
|
2074
|
+
span.end();
|
|
2075
|
+
return result;
|
|
2116
2076
|
}
|
|
2117
2077
|
}
|
|
2118
2078
|
|