@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.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
|
|
3
|
+
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
2
4
|
import * as otel from '@opentelemetry/api';
|
|
3
5
|
import { trace, propagation, context } from '@opentelemetry/api';
|
|
4
|
-
import {
|
|
5
|
-
import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
|
|
6
|
+
import { Translator, Provider } from 'rosetta-ai';
|
|
6
7
|
import { v4 } from 'uuid';
|
|
7
8
|
import { BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS } from '@opentelemetry/baggage-span-processor';
|
|
8
9
|
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
|
|
@@ -118,6 +119,23 @@ function GET_GATEWAY_BASE_URL() {
|
|
|
118
119
|
}
|
|
119
120
|
const env = { GATEWAY_BASE_URL: GET_GATEWAY_BASE_URL() };
|
|
120
121
|
|
|
122
|
+
function toSnakeCase(str) {
|
|
123
|
+
return str
|
|
124
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
125
|
+
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
126
|
+
.replace(/_+/g, '_')
|
|
127
|
+
.replace(/^_+|_+$/g, '')
|
|
128
|
+
.toLowerCase();
|
|
129
|
+
}
|
|
130
|
+
function toKebabCase(input) {
|
|
131
|
+
return input
|
|
132
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
133
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
134
|
+
.replace(/-+/g, '-')
|
|
135
|
+
.replace(/^-+|-+$/g, '')
|
|
136
|
+
.toLowerCase();
|
|
137
|
+
}
|
|
138
|
+
|
|
121
139
|
var StreamEventTypes;
|
|
122
140
|
(function (StreamEventTypes) {
|
|
123
141
|
StreamEventTypes["Latitude"] = "latitude-event";
|
|
@@ -130,6 +148,15 @@ z.object({
|
|
|
130
148
|
isError: z.boolean().optional(),
|
|
131
149
|
text: z.string().optional(),
|
|
132
150
|
});
|
|
151
|
+
z.object({
|
|
152
|
+
inputTokens: z.number(),
|
|
153
|
+
outputTokens: z.number(),
|
|
154
|
+
promptTokens: z.number(),
|
|
155
|
+
completionTokens: z.number(),
|
|
156
|
+
totalTokens: z.number(),
|
|
157
|
+
reasoningTokens: z.number(),
|
|
158
|
+
cachedInputTokens: z.number(),
|
|
159
|
+
});
|
|
133
160
|
|
|
134
161
|
var ParameterType;
|
|
135
162
|
(function (ParameterType) {
|
|
@@ -170,10 +197,24 @@ const expectedOutputConfiguration = z.object({
|
|
|
170
197
|
parsingFormat: z.enum(['string', 'json']),
|
|
171
198
|
fieldAccessor: z.string().optional(), // Field accessor to get the output from if it's a key-value format
|
|
172
199
|
});
|
|
200
|
+
const EVALUATION_TRIGGER_TARGETS = ['first', 'every', 'last'];
|
|
201
|
+
const DEFAULT_LAST_INTERACTION_DEBOUNCE_SECONDS = 120;
|
|
202
|
+
const LAST_INTERACTION_DEBOUNCE_MIN_SECONDS = 30;
|
|
203
|
+
const LAST_INTERACTION_DEBOUNCE_MAX_SECONDS = 60 * 60 * 24; // 1 day
|
|
204
|
+
const triggerConfiguration = z.object({
|
|
205
|
+
target: z.enum(EVALUATION_TRIGGER_TARGETS),
|
|
206
|
+
lastInteractionDebounce: z
|
|
207
|
+
.number()
|
|
208
|
+
.min(LAST_INTERACTION_DEBOUNCE_MIN_SECONDS)
|
|
209
|
+
.max(LAST_INTERACTION_DEBOUNCE_MAX_SECONDS)
|
|
210
|
+
.optional()
|
|
211
|
+
.default(DEFAULT_LAST_INTERACTION_DEBOUNCE_SECONDS),
|
|
212
|
+
});
|
|
173
213
|
const baseEvaluationConfiguration = z.object({
|
|
174
214
|
reverseScale: z.boolean(), // If true, lower is better, otherwise, higher is better
|
|
175
215
|
actualOutput: actualOutputConfiguration,
|
|
176
216
|
expectedOutput: expectedOutputConfiguration.optional(),
|
|
217
|
+
trigger: triggerConfiguration.optional(),
|
|
177
218
|
});
|
|
178
219
|
const baseEvaluationResultMetadata = z.object({
|
|
179
220
|
// configuration: Configuration snapshot is defined in every metric specification
|
|
@@ -189,7 +230,6 @@ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
|
189
230
|
evaluationUuids: z.array(z.string()),
|
|
190
231
|
minThreshold: z.number().optional(), // Threshold percentage
|
|
191
232
|
maxThreshold: z.number().optional(), // Threshold percentage
|
|
192
|
-
defaultTarget: z.boolean().optional(), // Default for optimizations and distillations
|
|
193
233
|
});
|
|
194
234
|
const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
195
235
|
results: z.record(z.string(), // Evaluation uuid
|
|
@@ -256,12 +296,34 @@ const CompositeEvaluationSpecification = {
|
|
|
256
296
|
},
|
|
257
297
|
};
|
|
258
298
|
|
|
299
|
+
const selectedContextSchema = z.object({
|
|
300
|
+
messageIndex: z.number().int().nonnegative(),
|
|
301
|
+
contentBlockIndex: z.number().int().nonnegative(),
|
|
302
|
+
contentType: z.enum([
|
|
303
|
+
'text',
|
|
304
|
+
'reasoning',
|
|
305
|
+
'image',
|
|
306
|
+
'file',
|
|
307
|
+
'tool-call',
|
|
308
|
+
'tool-result',
|
|
309
|
+
]),
|
|
310
|
+
textRange: z
|
|
311
|
+
.object({
|
|
312
|
+
start: z.number().int().nonnegative(),
|
|
313
|
+
end: z.number().int().nonnegative(),
|
|
314
|
+
})
|
|
315
|
+
.optional(),
|
|
316
|
+
selectedText: z.string().optional(),
|
|
317
|
+
toolCallId: z.string().optional(),
|
|
318
|
+
});
|
|
259
319
|
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
260
320
|
enableControls: z.boolean().optional(), // UI annotation controls
|
|
261
321
|
criteria: z.string().optional(),
|
|
262
322
|
});
|
|
263
323
|
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
264
324
|
reason: z.string().optional(),
|
|
325
|
+
enrichedReason: z.string().optional(),
|
|
326
|
+
selectedContexts: z.array(selectedContextSchema).optional(),
|
|
265
327
|
});
|
|
266
328
|
const humanEvaluationResultError = baseEvaluationResultError.extend({});
|
|
267
329
|
// BINARY
|
|
@@ -539,18 +601,8 @@ z.object({
|
|
|
539
601
|
});
|
|
540
602
|
z.object({
|
|
541
603
|
evaluateLiveLogs: z.boolean().nullable().optional(),
|
|
542
|
-
enableSuggestions: z.boolean().nullable().optional(),
|
|
543
|
-
autoApplySuggestions: z.boolean().nullable().optional(),
|
|
544
604
|
});
|
|
545
605
|
|
|
546
|
-
var LegacyChainEventTypes;
|
|
547
|
-
(function (LegacyChainEventTypes) {
|
|
548
|
-
LegacyChainEventTypes["Error"] = "chain-error";
|
|
549
|
-
LegacyChainEventTypes["Step"] = "chain-step";
|
|
550
|
-
LegacyChainEventTypes["Complete"] = "chain-complete";
|
|
551
|
-
LegacyChainEventTypes["StepComplete"] = "chain-step-complete";
|
|
552
|
-
})(LegacyChainEventTypes || (LegacyChainEventTypes = {}));
|
|
553
|
-
|
|
554
606
|
var ChainEventTypes;
|
|
555
607
|
(function (ChainEventTypes) {
|
|
556
608
|
ChainEventTypes["ChainCompleted"] = "chain-completed";
|
|
@@ -738,6 +790,7 @@ var LogSources;
|
|
|
738
790
|
LogSources["ShadowTest"] = "shadow_test";
|
|
739
791
|
LogSources["ABTestChallenger"] = "ab_test_challenger";
|
|
740
792
|
LogSources["User"] = "user";
|
|
793
|
+
LogSources["Optimization"] = "optimization";
|
|
741
794
|
})(LogSources || (LogSources = {}));
|
|
742
795
|
|
|
743
796
|
var RunSourceGroup;
|
|
@@ -748,7 +801,8 @@ var RunSourceGroup;
|
|
|
748
801
|
({
|
|
749
802
|
[RunSourceGroup.Production]: [
|
|
750
803
|
LogSources.API,
|
|
751
|
-
LogSources.
|
|
804
|
+
LogSources.ShadowTest,
|
|
805
|
+
LogSources.ABTestChallenger,
|
|
752
806
|
LogSources.EmailTrigger,
|
|
753
807
|
LogSources.IntegrationTrigger,
|
|
754
808
|
LogSources.ScheduledTrigger,
|
|
@@ -758,14 +812,6 @@ var RunSourceGroup;
|
|
|
758
812
|
[RunSourceGroup.Playground]: [LogSources.Playground, LogSources.Experiment],
|
|
759
813
|
});
|
|
760
814
|
|
|
761
|
-
var MessageRole;
|
|
762
|
-
(function (MessageRole) {
|
|
763
|
-
MessageRole["system"] = "system";
|
|
764
|
-
MessageRole["user"] = "user";
|
|
765
|
-
MessageRole["assistant"] = "assistant";
|
|
766
|
-
MessageRole["tool"] = "tool";
|
|
767
|
-
})(MessageRole || (MessageRole = {}));
|
|
768
|
-
|
|
769
815
|
var SpanKind;
|
|
770
816
|
(function (SpanKind) {
|
|
771
817
|
SpanKind["Internal"] = "internal";
|
|
@@ -777,26 +823,49 @@ var SpanKind;
|
|
|
777
823
|
// Note: loosely based on OpenTelemetry GenAI semantic conventions
|
|
778
824
|
var SpanType;
|
|
779
825
|
(function (SpanType) {
|
|
780
|
-
|
|
781
|
-
SpanType["Completion"] = "completion";
|
|
782
|
-
SpanType["Embedding"] = "embedding";
|
|
783
|
-
SpanType["Retrieval"] = "retrieval";
|
|
784
|
-
SpanType["Reranking"] = "reranking";
|
|
785
|
-
SpanType["Http"] = "http";
|
|
786
|
-
SpanType["Unknown"] = "unknown";
|
|
826
|
+
// Latitude wrappers
|
|
787
827
|
SpanType["Prompt"] = "prompt";
|
|
788
828
|
SpanType["Chat"] = "chat";
|
|
789
829
|
SpanType["External"] = "external";
|
|
790
830
|
SpanType["UnresolvedExternal"] = "unresolved_external";
|
|
791
|
-
|
|
831
|
+
// Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
|
|
832
|
+
SpanType["Http"] = "http";
|
|
833
|
+
// Any known span from supported specifications will be grouped into one of these types
|
|
834
|
+
SpanType["Completion"] = "completion";
|
|
835
|
+
SpanType["Tool"] = "tool";
|
|
836
|
+
SpanType["Embedding"] = "embedding";
|
|
837
|
+
SpanType["Unknown"] = "unknown";
|
|
792
838
|
})(SpanType || (SpanType = {}));
|
|
839
|
+
[
|
|
840
|
+
SpanType.Prompt,
|
|
841
|
+
SpanType.External,
|
|
842
|
+
SpanType.Chat,
|
|
843
|
+
];
|
|
793
844
|
const SPAN_SPECIFICATIONS = {
|
|
794
|
-
[SpanType.
|
|
795
|
-
name: '
|
|
796
|
-
description: 'A
|
|
797
|
-
isGenAI:
|
|
845
|
+
[SpanType.Prompt]: {
|
|
846
|
+
name: 'Prompt',
|
|
847
|
+
description: 'A prompt span',
|
|
848
|
+
isGenAI: false,
|
|
849
|
+
isHidden: false,
|
|
850
|
+
},
|
|
851
|
+
[SpanType.Chat]: {
|
|
852
|
+
name: 'Chat',
|
|
853
|
+
description: 'A chat continuation span',
|
|
854
|
+
isGenAI: false,
|
|
855
|
+
isHidden: false,
|
|
856
|
+
},
|
|
857
|
+
[SpanType.External]: {
|
|
858
|
+
name: 'External',
|
|
859
|
+
description: 'An external capture span',
|
|
860
|
+
isGenAI: false,
|
|
798
861
|
isHidden: false,
|
|
799
862
|
},
|
|
863
|
+
[SpanType.UnresolvedExternal]: {
|
|
864
|
+
name: 'Unresolved External',
|
|
865
|
+
description: 'An external span that needs path resolution before storage',
|
|
866
|
+
isGenAI: false,
|
|
867
|
+
isHidden: true,
|
|
868
|
+
},
|
|
800
869
|
[SpanType.Completion]: {
|
|
801
870
|
name: 'Completion',
|
|
802
871
|
description: 'A completion call',
|
|
@@ -809,15 +878,9 @@ const SPAN_SPECIFICATIONS = {
|
|
|
809
878
|
isGenAI: true,
|
|
810
879
|
isHidden: false,
|
|
811
880
|
},
|
|
812
|
-
[SpanType.
|
|
813
|
-
name: '
|
|
814
|
-
description: 'A
|
|
815
|
-
isGenAI: true,
|
|
816
|
-
isHidden: false,
|
|
817
|
-
},
|
|
818
|
-
[SpanType.Reranking]: {
|
|
819
|
-
name: 'Reranking',
|
|
820
|
-
description: 'A reranking call',
|
|
881
|
+
[SpanType.Tool]: {
|
|
882
|
+
name: 'Tool',
|
|
883
|
+
description: 'A tool call',
|
|
821
884
|
isGenAI: true,
|
|
822
885
|
isHidden: false,
|
|
823
886
|
},
|
|
@@ -833,36 +896,6 @@ const SPAN_SPECIFICATIONS = {
|
|
|
833
896
|
isGenAI: false,
|
|
834
897
|
isHidden: true,
|
|
835
898
|
},
|
|
836
|
-
[SpanType.Prompt]: {
|
|
837
|
-
name: 'Prompt',
|
|
838
|
-
description: 'A prompt span',
|
|
839
|
-
isGenAI: false,
|
|
840
|
-
isHidden: false,
|
|
841
|
-
},
|
|
842
|
-
[SpanType.Chat]: {
|
|
843
|
-
name: 'Chat',
|
|
844
|
-
description: 'A chat continuation span',
|
|
845
|
-
isGenAI: false,
|
|
846
|
-
isHidden: false,
|
|
847
|
-
},
|
|
848
|
-
[SpanType.External]: {
|
|
849
|
-
name: 'External',
|
|
850
|
-
description: 'An external capture span',
|
|
851
|
-
isGenAI: false,
|
|
852
|
-
isHidden: false,
|
|
853
|
-
},
|
|
854
|
-
[SpanType.UnresolvedExternal]: {
|
|
855
|
-
name: 'Unresolved External',
|
|
856
|
-
description: 'An external span that needs path resolution before storage',
|
|
857
|
-
isGenAI: false,
|
|
858
|
-
isHidden: true,
|
|
859
|
-
},
|
|
860
|
-
[SpanType.Step]: {
|
|
861
|
-
name: 'Step',
|
|
862
|
-
description: 'A step span',
|
|
863
|
-
isGenAI: false,
|
|
864
|
-
isHidden: false,
|
|
865
|
-
},
|
|
866
899
|
};
|
|
867
900
|
var SpanStatus;
|
|
868
901
|
(function (SpanStatus) {
|
|
@@ -870,6 +903,11 @@ var SpanStatus;
|
|
|
870
903
|
SpanStatus["Ok"] = "ok";
|
|
871
904
|
SpanStatus["Error"] = "error";
|
|
872
905
|
})(SpanStatus || (SpanStatus = {}));
|
|
906
|
+
new Set([
|
|
907
|
+
SpanType.Prompt,
|
|
908
|
+
SpanType.Chat,
|
|
909
|
+
SpanType.External,
|
|
910
|
+
]);
|
|
873
911
|
|
|
874
912
|
// Note: Traces are unmaterialized but this context is used to propagate the trace
|
|
875
913
|
// See www.w3.org/TR/trace-context and w3c.github.io/baggage
|
|
@@ -879,6 +917,100 @@ z.object({
|
|
|
879
917
|
baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
880
918
|
});
|
|
881
919
|
|
|
920
|
+
const ATTRIBUTES = {
|
|
921
|
+
// Custom attributes added and used by Latitude spans (Prompt / External / Chat)
|
|
922
|
+
LATITUDE: {
|
|
923
|
+
type: 'latitude.type',
|
|
924
|
+
documentUuid: 'latitude.document_uuid',
|
|
925
|
+
promptPath: 'latitude.prompt_path',
|
|
926
|
+
commitUuid: 'latitude.commit_uuid',
|
|
927
|
+
documentLogUuid: 'latitude.document_log_uuid',
|
|
928
|
+
projectId: 'latitude.project_id',
|
|
929
|
+
experimentUuid: 'latitude.experiment_uuid',
|
|
930
|
+
source: 'latitude.source',
|
|
931
|
+
externalId: 'latitude.external_id',
|
|
932
|
+
testDeploymentId: 'latitude.test_deployment_id',
|
|
933
|
+
previousTraceId: 'latitude.previous_trace_id',
|
|
934
|
+
// Custom additions to the GenAI semantic conventions (deprecated)
|
|
935
|
+
request: {
|
|
936
|
+
_root: 'gen_ai.request',
|
|
937
|
+
configuration: 'gen_ai.request.configuration',
|
|
938
|
+
template: 'gen_ai.request.template',
|
|
939
|
+
parameters: 'gen_ai.request.parameters'},
|
|
940
|
+
response: {
|
|
941
|
+
_root: 'gen_ai.response'},
|
|
942
|
+
usage: {
|
|
943
|
+
promptTokens: 'gen_ai.usage.prompt_tokens',
|
|
944
|
+
cachedTokens: 'gen_ai.usage.cached_tokens',
|
|
945
|
+
reasoningTokens: 'gen_ai.usage.reasoning_tokens',
|
|
946
|
+
completionTokens: 'gen_ai.usage.completion_tokens',
|
|
947
|
+
},
|
|
948
|
+
},
|
|
949
|
+
// Official OpenTelemetry semantic conventions
|
|
950
|
+
OPENTELEMETRY: {
|
|
951
|
+
HTTP: {
|
|
952
|
+
request: {
|
|
953
|
+
url: 'http.request.url',
|
|
954
|
+
body: 'http.request.body',
|
|
955
|
+
header: 'http.request.header',
|
|
956
|
+
method: ATTR_HTTP_REQUEST_METHOD,
|
|
957
|
+
},
|
|
958
|
+
response: {
|
|
959
|
+
body: 'http.response.body',
|
|
960
|
+
header: 'http.response.header',
|
|
961
|
+
statusCode: ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
962
|
+
},
|
|
963
|
+
},
|
|
964
|
+
// GenAI semantic conventions
|
|
965
|
+
// https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
|
|
966
|
+
GEN_AI: {
|
|
967
|
+
operation: ATTR_GEN_AI_OPERATION_NAME,
|
|
968
|
+
response: {
|
|
969
|
+
model: ATTR_GEN_AI_RESPONSE_MODEL,
|
|
970
|
+
finishReasons: ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
|
|
971
|
+
},
|
|
972
|
+
usage: {
|
|
973
|
+
inputTokens: ATTR_GEN_AI_USAGE_INPUT_TOKENS,
|
|
974
|
+
outputTokens: ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
975
|
+
},
|
|
976
|
+
systemInstructions: 'gen_ai.system.instructions', // Contains the PARTS of the "system message"
|
|
977
|
+
tool: {
|
|
978
|
+
call: {
|
|
979
|
+
id: ATTR_GEN_AI_TOOL_CALL_ID,
|
|
980
|
+
arguments: 'gen_ai.tool.call.arguments'}},
|
|
981
|
+
input: {
|
|
982
|
+
messages: 'gen_ai.input.messages',
|
|
983
|
+
},
|
|
984
|
+
output: {
|
|
985
|
+
messages: 'gen_ai.output.messages',
|
|
986
|
+
},
|
|
987
|
+
_deprecated: {
|
|
988
|
+
system: ATTR_GEN_AI_SYSTEM,
|
|
989
|
+
tool: {
|
|
990
|
+
name: ATTR_GEN_AI_TOOL_NAME,
|
|
991
|
+
type: ATTR_GEN_AI_TOOL_TYPE,
|
|
992
|
+
result: {
|
|
993
|
+
value: 'gen_ai.tool.result.value',
|
|
994
|
+
isError: 'gen_ai.tool.result.is_error',
|
|
995
|
+
},
|
|
996
|
+
}},
|
|
997
|
+
},
|
|
998
|
+
}};
|
|
999
|
+
const VALUES = {
|
|
1000
|
+
OPENTELEMETRY: {
|
|
1001
|
+
GEN_AI: {
|
|
1002
|
+
response: {
|
|
1003
|
+
finishReasons: {
|
|
1004
|
+
stop: 'stop',
|
|
1005
|
+
toolCalls: 'tool_calls'},
|
|
1006
|
+
},
|
|
1007
|
+
tool: {
|
|
1008
|
+
type: {
|
|
1009
|
+
function: 'function',
|
|
1010
|
+
},
|
|
1011
|
+
}},
|
|
1012
|
+
}};
|
|
1013
|
+
|
|
882
1014
|
/* Note: Instrumentation scopes from all language SDKs */
|
|
883
1015
|
const SCOPE_LATITUDE = 'so.latitude.instrumentation';
|
|
884
1016
|
var InstrumentationScope;
|
|
@@ -907,52 +1039,6 @@ var InstrumentationScope;
|
|
|
907
1039
|
InstrumentationScope["Transformers"] = "transformers";
|
|
908
1040
|
InstrumentationScope["AlephAlpha"] = "alephalpha";
|
|
909
1041
|
})(InstrumentationScope || (InstrumentationScope = {}));
|
|
910
|
-
/* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
|
|
911
|
-
const ATTR_LATITUDE = 'latitude';
|
|
912
|
-
const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
|
|
913
|
-
const ATTR_LATITUDE_DOCUMENT_UUID = `${ATTR_LATITUDE}.document_uuid`;
|
|
914
|
-
const ATTR_LATITUDE_PROMPT_PATH = `${ATTR_LATITUDE}.prompt_path`;
|
|
915
|
-
const ATTR_LATITUDE_COMMIT_UUID = `${ATTR_LATITUDE}.commit_uuid`;
|
|
916
|
-
const ATTR_LATITUDE_DOCUMENT_LOG_UUID = `${ATTR_LATITUDE}.document_log_uuid`;
|
|
917
|
-
const ATTR_LATITUDE_PROJECT_ID = `${ATTR_LATITUDE}.project_id`;
|
|
918
|
-
const ATTR_LATITUDE_EXPERIMENT_UUID = `${ATTR_LATITUDE}.experiment_uuid`;
|
|
919
|
-
const ATTR_LATITUDE_SOURCE = `${ATTR_LATITUDE}.source`;
|
|
920
|
-
const ATTR_LATITUDE_EXTERNAL_ID = `${ATTR_LATITUDE}.external_id`;
|
|
921
|
-
const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
|
|
922
|
-
const ATTR_LATITUDE_PREVIOUS_TRACE_ID = `${ATTR_LATITUDE}.previous_trace_id`;
|
|
923
|
-
const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
|
|
924
|
-
const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
|
|
925
|
-
const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
|
|
926
|
-
const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
|
|
927
|
-
const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
|
|
928
|
-
const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
|
|
929
|
-
const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
|
|
930
|
-
const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
|
|
931
|
-
const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
|
|
932
|
-
const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
|
|
933
|
-
const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
|
|
934
|
-
const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
|
|
935
|
-
const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
|
|
936
|
-
const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
|
|
937
|
-
const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
|
|
938
|
-
const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
|
|
939
|
-
const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
|
|
940
|
-
const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
|
|
941
|
-
const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
|
|
942
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
|
|
943
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
|
|
944
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
|
|
945
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
|
|
946
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
|
|
947
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
|
|
948
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
|
|
949
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
|
|
950
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
|
|
951
|
-
const ATTR_HTTP_REQUEST_URL = 'http.request.url';
|
|
952
|
-
const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
|
|
953
|
-
const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
|
|
954
|
-
const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
|
|
955
|
-
const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
|
|
956
1042
|
/* Note: Schemas for span ingestion following OpenTelemetry service request specification */
|
|
957
1043
|
var Otlp;
|
|
958
1044
|
(function (Otlp) {
|
|
@@ -1033,6 +1119,54 @@ var Otlp;
|
|
|
1033
1119
|
});
|
|
1034
1120
|
})(Otlp || (Otlp = {}));
|
|
1035
1121
|
|
|
1122
|
+
const MAX_SIMULATION_TURNS = 10;
|
|
1123
|
+
const globalGoalSourceSchema = z.object({
|
|
1124
|
+
type: z.literal('global'),
|
|
1125
|
+
value: z.string(),
|
|
1126
|
+
});
|
|
1127
|
+
const columnGoalSourceSchema = z.object({
|
|
1128
|
+
type: z.literal('column'),
|
|
1129
|
+
columnIndex: z.number(),
|
|
1130
|
+
});
|
|
1131
|
+
const simulatedUserGoalSourceSchema = z.discriminatedUnion('type', [
|
|
1132
|
+
globalGoalSourceSchema,
|
|
1133
|
+
columnGoalSourceSchema,
|
|
1134
|
+
]);
|
|
1135
|
+
const SimulationSettingsSchema = z.object({
|
|
1136
|
+
simulateToolResponses: z.boolean().optional(),
|
|
1137
|
+
simulatedTools: z.array(z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
|
|
1138
|
+
toolSimulationInstructions: z.string().optional(), // A prompt used to guide and generate the simulation result
|
|
1139
|
+
maxTurns: z.number().min(1).max(MAX_SIMULATION_TURNS).optional(), // The maximum number of turns to simulate. Default is 1, and any greater value will add a new user message to the simulated conversation.
|
|
1140
|
+
simulatedUserGoal: z.string().optional(), // Deprecated: Use simulatedUserGoalSource instead. Kept for backward compatibility.
|
|
1141
|
+
simulatedUserGoalSource: simulatedUserGoalSourceSchema.optional(), // The source for the simulated user goal (global text or dataset column).
|
|
1142
|
+
});
|
|
1143
|
+
|
|
1144
|
+
var OptimizationEngine;
|
|
1145
|
+
(function (OptimizationEngine) {
|
|
1146
|
+
OptimizationEngine["Identity"] = "identity";
|
|
1147
|
+
OptimizationEngine["Gepa"] = "gepa";
|
|
1148
|
+
})(OptimizationEngine || (OptimizationEngine = {}));
|
|
1149
|
+
const OptimizationBudgetSchema = z.object({
|
|
1150
|
+
time: z.number().min(0).optional(),
|
|
1151
|
+
tokens: z.number().min(0).optional(),
|
|
1152
|
+
});
|
|
1153
|
+
z.object({
|
|
1154
|
+
parameters: z
|
|
1155
|
+
.record(z.string(), z.object({
|
|
1156
|
+
column: z.string().optional(), // Note: corresponding column in the user-provided trainset and testset
|
|
1157
|
+
isPii: z.boolean().optional(),
|
|
1158
|
+
}))
|
|
1159
|
+
.optional(),
|
|
1160
|
+
simulation: SimulationSettingsSchema.optional(),
|
|
1161
|
+
scope: z
|
|
1162
|
+
.object({
|
|
1163
|
+
configuration: z.boolean().optional(),
|
|
1164
|
+
instructions: z.boolean().optional(),
|
|
1165
|
+
})
|
|
1166
|
+
.optional(),
|
|
1167
|
+
budget: OptimizationBudgetSchema.optional(),
|
|
1168
|
+
});
|
|
1169
|
+
|
|
1036
1170
|
// TODO(tracing): deprecated
|
|
1037
1171
|
const HEAD_COMMIT = 'live';
|
|
1038
1172
|
var Providers;
|
|
@@ -1078,12 +1212,18 @@ var DocumentTriggerParameters;
|
|
|
1078
1212
|
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
1079
1213
|
const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
|
|
1080
1214
|
|
|
1215
|
+
const translator = new Translator({
|
|
1216
|
+
filterEmptyMessages: true,
|
|
1217
|
+
providerMetadata: 'preserve',
|
|
1218
|
+
});
|
|
1081
1219
|
class ManualInstrumentation {
|
|
1082
1220
|
enabled;
|
|
1083
1221
|
tracer;
|
|
1084
|
-
|
|
1222
|
+
options;
|
|
1223
|
+
constructor(tracer, options) {
|
|
1085
1224
|
this.enabled = false;
|
|
1086
1225
|
this.tracer = tracer;
|
|
1226
|
+
this.options = options ?? {};
|
|
1087
1227
|
}
|
|
1088
1228
|
isEnabled() {
|
|
1089
1229
|
return this.enabled;
|
|
@@ -1123,36 +1263,6 @@ class ManualInstrumentation {
|
|
|
1123
1263
|
}
|
|
1124
1264
|
return context;
|
|
1125
1265
|
}
|
|
1126
|
-
capitalize(str) {
|
|
1127
|
-
if (str.length === 0)
|
|
1128
|
-
return str;
|
|
1129
|
-
return str.charAt(0).toUpperCase() + str.toLowerCase().slice(1);
|
|
1130
|
-
}
|
|
1131
|
-
toCamelCase(str) {
|
|
1132
|
-
return str
|
|
1133
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
1134
|
-
.replace(/[^A-Za-z0-9]+/g, ' ')
|
|
1135
|
-
.trim()
|
|
1136
|
-
.split(' ')
|
|
1137
|
-
.map((w, i) => (i ? this.capitalize(w) : w.toLowerCase()))
|
|
1138
|
-
.join('');
|
|
1139
|
-
}
|
|
1140
|
-
toSnakeCase(str) {
|
|
1141
|
-
return str
|
|
1142
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
1143
|
-
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
1144
|
-
.replace(/_+/g, '_')
|
|
1145
|
-
.replace(/^_+|_+$/g, '')
|
|
1146
|
-
.toLowerCase();
|
|
1147
|
-
}
|
|
1148
|
-
toKebabCase(input) {
|
|
1149
|
-
return input
|
|
1150
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
1151
|
-
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
1152
|
-
.replace(/-+/g, '-')
|
|
1153
|
-
.replace(/^-+|-+$/g, '')
|
|
1154
|
-
.toLowerCase();
|
|
1155
|
-
}
|
|
1156
1266
|
error(span, error, options) {
|
|
1157
1267
|
options = options || {};
|
|
1158
1268
|
span.recordException(error);
|
|
@@ -1178,9 +1288,9 @@ class ManualInstrumentation {
|
|
|
1178
1288
|
}
|
|
1179
1289
|
const span = this.tracer.startSpan(name, {
|
|
1180
1290
|
attributes: {
|
|
1181
|
-
[
|
|
1291
|
+
[ATTRIBUTES.LATITUDE.type]: type,
|
|
1182
1292
|
...(operation && {
|
|
1183
|
-
[
|
|
1293
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
|
|
1184
1294
|
}),
|
|
1185
1295
|
...(start.attributes || {}),
|
|
1186
1296
|
},
|
|
@@ -1200,26 +1310,29 @@ class ManualInstrumentation {
|
|
|
1200
1310
|
},
|
|
1201
1311
|
};
|
|
1202
1312
|
}
|
|
1313
|
+
unknown(ctx, options) {
|
|
1314
|
+
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Unknown].name, SpanType.Unknown, options);
|
|
1315
|
+
}
|
|
1203
1316
|
tool(ctx, options) {
|
|
1204
1317
|
const start = options;
|
|
1205
1318
|
let jsonArguments = '';
|
|
1206
1319
|
try {
|
|
1207
1320
|
jsonArguments = JSON.stringify(start.call.arguments);
|
|
1208
1321
|
}
|
|
1209
|
-
catch (
|
|
1322
|
+
catch (_error) {
|
|
1210
1323
|
jsonArguments = '{}';
|
|
1211
1324
|
}
|
|
1212
1325
|
const span = this.span(ctx, start.name, SpanType.Tool, {
|
|
1213
1326
|
attributes: {
|
|
1214
|
-
[
|
|
1215
|
-
[
|
|
1216
|
-
[
|
|
1217
|
-
[
|
|
1327
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
|
|
1328
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
|
|
1329
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
|
|
1330
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
|
|
1218
1331
|
...(start.attributes || {}),
|
|
1219
1332
|
},
|
|
1220
1333
|
});
|
|
1221
1334
|
return {
|
|
1222
|
-
|
|
1335
|
+
...span,
|
|
1223
1336
|
end: (options) => {
|
|
1224
1337
|
const end = options;
|
|
1225
1338
|
let stringResult = '';
|
|
@@ -1227,7 +1340,7 @@ class ManualInstrumentation {
|
|
|
1227
1340
|
try {
|
|
1228
1341
|
stringResult = JSON.stringify(end.result.value);
|
|
1229
1342
|
}
|
|
1230
|
-
catch (
|
|
1343
|
+
catch (_error) {
|
|
1231
1344
|
stringResult = '{}';
|
|
1232
1345
|
}
|
|
1233
1346
|
}
|
|
@@ -1236,180 +1349,21 @@ class ManualInstrumentation {
|
|
|
1236
1349
|
}
|
|
1237
1350
|
span.end({
|
|
1238
1351
|
attributes: {
|
|
1239
|
-
[
|
|
1240
|
-
[
|
|
1352
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
|
|
1353
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
|
|
1241
1354
|
...(end.attributes || {}),
|
|
1242
1355
|
},
|
|
1243
1356
|
});
|
|
1244
1357
|
},
|
|
1245
|
-
fail: span.fail,
|
|
1246
1358
|
};
|
|
1247
1359
|
}
|
|
1248
|
-
attribifyMessageToolCalls(prefix, toolCalls) {
|
|
1249
|
-
const attributes = {};
|
|
1250
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
1251
|
-
for (const key in toolCalls[i]) {
|
|
1252
|
-
const field = this.toCamelCase(key);
|
|
1253
|
-
let value = toolCalls[i][key];
|
|
1254
|
-
if (value === null || value === undefined)
|
|
1255
|
-
continue;
|
|
1256
|
-
switch (field) {
|
|
1257
|
-
case 'id':
|
|
1258
|
-
case 'toolCallId':
|
|
1259
|
-
case 'toolUseId': {
|
|
1260
|
-
if (typeof value !== 'string')
|
|
1261
|
-
continue;
|
|
1262
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID}`] = value;
|
|
1263
|
-
break;
|
|
1264
|
-
}
|
|
1265
|
-
case 'name':
|
|
1266
|
-
case 'toolName': {
|
|
1267
|
-
if (typeof value !== 'string')
|
|
1268
|
-
continue;
|
|
1269
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value;
|
|
1270
|
-
break;
|
|
1271
|
-
}
|
|
1272
|
-
case 'arguments':
|
|
1273
|
-
case 'toolArguments':
|
|
1274
|
-
case 'input': {
|
|
1275
|
-
if (typeof value === 'string') {
|
|
1276
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value;
|
|
1277
|
-
}
|
|
1278
|
-
else {
|
|
1279
|
-
try {
|
|
1280
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = JSON.stringify(value);
|
|
1281
|
-
}
|
|
1282
|
-
catch (error) {
|
|
1283
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = '{}';
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
break;
|
|
1287
|
-
}
|
|
1288
|
-
/* OpenAI function calls */
|
|
1289
|
-
case 'function': {
|
|
1290
|
-
if (typeof value !== 'object')
|
|
1291
|
-
continue;
|
|
1292
|
-
if (!('name' in value))
|
|
1293
|
-
continue;
|
|
1294
|
-
if (typeof value.name !== 'string')
|
|
1295
|
-
continue;
|
|
1296
|
-
if (!('arguments' in value))
|
|
1297
|
-
continue;
|
|
1298
|
-
if (typeof value.arguments !== 'string')
|
|
1299
|
-
continue;
|
|
1300
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value.name;
|
|
1301
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value.arguments;
|
|
1302
|
-
break;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
return attributes;
|
|
1308
|
-
}
|
|
1309
|
-
attribifyMessageContent(prefix, content) {
|
|
1310
|
-
let attributes = {};
|
|
1311
|
-
if (typeof content === 'string') {
|
|
1312
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
|
|
1313
|
-
return attributes;
|
|
1314
|
-
}
|
|
1315
|
-
try {
|
|
1316
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] =
|
|
1317
|
-
JSON.stringify(content);
|
|
1318
|
-
}
|
|
1319
|
-
catch (error) {
|
|
1320
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = '[]';
|
|
1321
|
-
}
|
|
1322
|
-
if (!Array.isArray(content))
|
|
1323
|
-
return attributes;
|
|
1324
|
-
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1325
|
-
const toolCalls = [];
|
|
1326
|
-
for (const item of content) {
|
|
1327
|
-
for (const key in item) {
|
|
1328
|
-
if (this.toCamelCase(key) !== 'type')
|
|
1329
|
-
continue;
|
|
1330
|
-
if (typeof item[key] !== 'string')
|
|
1331
|
-
continue;
|
|
1332
|
-
if (item[key] !== 'tool-call' && item[key] !== 'tool_use')
|
|
1333
|
-
continue;
|
|
1334
|
-
toolCalls.push(item);
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
if (toolCalls.length > 0) {
|
|
1338
|
-
attributes = {
|
|
1339
|
-
...attributes,
|
|
1340
|
-
...this.attribifyMessageToolCalls(prefix, toolCalls),
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
return attributes;
|
|
1344
|
-
}
|
|
1345
|
-
attribifyMessages(direction, messages) {
|
|
1346
|
-
const prefix = direction === 'input' ? ATTR_GEN_AI_PROMPTS : ATTR_GEN_AI_COMPLETIONS;
|
|
1347
|
-
let attributes = {};
|
|
1348
|
-
for (let i = 0; i < messages.length; i++) {
|
|
1349
|
-
for (const key in messages[i]) {
|
|
1350
|
-
const field = this.toCamelCase(key);
|
|
1351
|
-
let value = messages[i][key];
|
|
1352
|
-
if (value === null || value === undefined)
|
|
1353
|
-
continue;
|
|
1354
|
-
switch (field) {
|
|
1355
|
-
case 'role': {
|
|
1356
|
-
if (typeof value !== 'string')
|
|
1357
|
-
continue;
|
|
1358
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_ROLE}`] = value;
|
|
1359
|
-
break;
|
|
1360
|
-
}
|
|
1361
|
-
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1362
|
-
case 'content': {
|
|
1363
|
-
attributes = {
|
|
1364
|
-
...attributes,
|
|
1365
|
-
...this.attribifyMessageContent(`${prefix}.${i}`, value),
|
|
1366
|
-
};
|
|
1367
|
-
break;
|
|
1368
|
-
}
|
|
1369
|
-
/* Tool calls for OpenAI */
|
|
1370
|
-
case 'toolCalls': {
|
|
1371
|
-
if (!Array.isArray(value))
|
|
1372
|
-
continue;
|
|
1373
|
-
attributes = {
|
|
1374
|
-
...attributes,
|
|
1375
|
-
...this.attribifyMessageToolCalls(`${prefix}.${i}`, value),
|
|
1376
|
-
};
|
|
1377
|
-
break;
|
|
1378
|
-
}
|
|
1379
|
-
/* Tool result for OpenAI / Anthropic / PromptL */
|
|
1380
|
-
case 'toolCallId':
|
|
1381
|
-
case 'toolId':
|
|
1382
|
-
case 'toolUseId': {
|
|
1383
|
-
if (typeof value !== 'string')
|
|
1384
|
-
continue;
|
|
1385
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID}`] =
|
|
1386
|
-
value;
|
|
1387
|
-
break;
|
|
1388
|
-
}
|
|
1389
|
-
case 'toolName': {
|
|
1390
|
-
if (typeof value !== 'string')
|
|
1391
|
-
continue;
|
|
1392
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_NAME}`] =
|
|
1393
|
-
value;
|
|
1394
|
-
break;
|
|
1395
|
-
}
|
|
1396
|
-
// Note: 'toolResult' is 'content' itself
|
|
1397
|
-
case 'isError': {
|
|
1398
|
-
if (typeof value !== 'boolean')
|
|
1399
|
-
continue;
|
|
1400
|
-
attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR}`] = value;
|
|
1401
|
-
break;
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
return attributes;
|
|
1407
|
-
}
|
|
1408
1360
|
attribifyConfiguration(direction, configuration) {
|
|
1409
|
-
const prefix = direction === 'input'
|
|
1361
|
+
const prefix = direction === 'input'
|
|
1362
|
+
? ATTRIBUTES.LATITUDE.request._root
|
|
1363
|
+
: ATTRIBUTES.LATITUDE.response._root;
|
|
1410
1364
|
const attributes = {};
|
|
1411
1365
|
for (const key in configuration) {
|
|
1412
|
-
const field =
|
|
1366
|
+
const field = toSnakeCase(key);
|
|
1413
1367
|
let value = configuration[key];
|
|
1414
1368
|
if (value === null || value === undefined)
|
|
1415
1369
|
continue;
|
|
@@ -1417,7 +1371,7 @@ class ManualInstrumentation {
|
|
|
1417
1371
|
try {
|
|
1418
1372
|
value = JSON.stringify(value);
|
|
1419
1373
|
}
|
|
1420
|
-
catch (
|
|
1374
|
+
catch (_error) {
|
|
1421
1375
|
value = '{}';
|
|
1422
1376
|
}
|
|
1423
1377
|
}
|
|
@@ -1435,45 +1389,56 @@ class ManualInstrumentation {
|
|
|
1435
1389
|
try {
|
|
1436
1390
|
jsonConfiguration = JSON.stringify(configuration);
|
|
1437
1391
|
}
|
|
1438
|
-
catch (
|
|
1392
|
+
catch (_error) {
|
|
1439
1393
|
jsonConfiguration = '{}';
|
|
1440
1394
|
}
|
|
1441
1395
|
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1442
1396
|
const input = start.input ?? [];
|
|
1397
|
+
let jsonSystem = '';
|
|
1443
1398
|
let jsonInput = '';
|
|
1444
1399
|
try {
|
|
1445
|
-
|
|
1400
|
+
const translated = translator.translate(input, {
|
|
1401
|
+
from: this.options.provider,
|
|
1402
|
+
to: Provider.GenAI,
|
|
1403
|
+
direction: 'input',
|
|
1404
|
+
});
|
|
1405
|
+
jsonSystem = JSON.stringify(translated.system ?? []);
|
|
1406
|
+
jsonInput = JSON.stringify(translated.messages ?? []);
|
|
1446
1407
|
}
|
|
1447
|
-
catch (
|
|
1408
|
+
catch (_error) {
|
|
1409
|
+
jsonSystem = '[]';
|
|
1448
1410
|
jsonInput = '[]';
|
|
1449
1411
|
}
|
|
1450
|
-
const attrInput = this.attribifyMessages('input', input);
|
|
1451
1412
|
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1452
1413
|
attributes: {
|
|
1453
|
-
[
|
|
1454
|
-
[
|
|
1414
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
|
|
1415
|
+
[ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
|
|
1455
1416
|
...attrConfiguration,
|
|
1456
|
-
[
|
|
1457
|
-
|
|
1417
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.systemInstructions]: jsonSystem,
|
|
1418
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.input.messages]: jsonInput,
|
|
1458
1419
|
...(start.attributes || {}),
|
|
1459
|
-
[
|
|
1460
|
-
[
|
|
1461
|
-
[
|
|
1420
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
|
|
1421
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
|
|
1422
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
|
|
1462
1423
|
},
|
|
1463
1424
|
});
|
|
1464
1425
|
return {
|
|
1465
|
-
|
|
1426
|
+
...span,
|
|
1466
1427
|
end: (options) => {
|
|
1467
1428
|
const end = options ?? {};
|
|
1468
1429
|
const output = end.output ?? [];
|
|
1469
1430
|
let jsonOutput = '';
|
|
1470
1431
|
try {
|
|
1471
|
-
|
|
1432
|
+
const translated = translator.translate(output, {
|
|
1433
|
+
from: this.options.provider,
|
|
1434
|
+
to: Provider.GenAI,
|
|
1435
|
+
direction: 'output',
|
|
1436
|
+
});
|
|
1437
|
+
jsonOutput = JSON.stringify(translated.messages ?? []);
|
|
1472
1438
|
}
|
|
1473
|
-
catch (
|
|
1439
|
+
catch (_error) {
|
|
1474
1440
|
jsonOutput = '[]';
|
|
1475
1441
|
}
|
|
1476
|
-
const attrOutput = this.attribifyMessages('output', output);
|
|
1477
1442
|
const tokens = {
|
|
1478
1443
|
prompt: end.tokens?.prompt ?? 0,
|
|
1479
1444
|
cached: end.tokens?.cached ?? 0,
|
|
@@ -1485,39 +1450,33 @@ class ManualInstrumentation {
|
|
|
1485
1450
|
const finishReason = end.finishReason ?? '';
|
|
1486
1451
|
span.end({
|
|
1487
1452
|
attributes: {
|
|
1488
|
-
[
|
|
1489
|
-
|
|
1490
|
-
[
|
|
1491
|
-
[
|
|
1492
|
-
[
|
|
1493
|
-
[
|
|
1494
|
-
[
|
|
1495
|
-
[
|
|
1496
|
-
[
|
|
1497
|
-
|
|
1453
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.output.messages]: jsonOutput,
|
|
1454
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
|
|
1455
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
|
|
1456
|
+
[ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
|
|
1457
|
+
[ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
|
|
1458
|
+
[ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
|
|
1459
|
+
[ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
|
|
1460
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
|
|
1461
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
|
|
1462
|
+
finishReason,
|
|
1463
|
+
],
|
|
1498
1464
|
...(end.attributes || {}),
|
|
1499
1465
|
},
|
|
1500
1466
|
});
|
|
1501
1467
|
},
|
|
1502
|
-
fail: span.fail,
|
|
1503
1468
|
};
|
|
1504
1469
|
}
|
|
1505
1470
|
embedding(ctx, options) {
|
|
1506
1471
|
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
|
|
1507
1472
|
}
|
|
1508
|
-
retrieval(ctx, options) {
|
|
1509
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Retrieval].name, SpanType.Retrieval, options);
|
|
1510
|
-
}
|
|
1511
|
-
reranking(ctx, options) {
|
|
1512
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Reranking].name, SpanType.Reranking, options);
|
|
1513
|
-
}
|
|
1514
1473
|
attribifyHeaders(direction, headers) {
|
|
1515
1474
|
const prefix = direction === 'request'
|
|
1516
|
-
?
|
|
1517
|
-
:
|
|
1475
|
+
? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
|
|
1476
|
+
: ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
|
|
1518
1477
|
const attributes = {};
|
|
1519
1478
|
for (const key in headers) {
|
|
1520
|
-
const field =
|
|
1479
|
+
const field = toKebabCase(key);
|
|
1521
1480
|
const value = headers[key];
|
|
1522
1481
|
if (value === null || value === undefined)
|
|
1523
1482
|
continue;
|
|
@@ -1538,21 +1497,21 @@ class ManualInstrumentation {
|
|
|
1538
1497
|
try {
|
|
1539
1498
|
finalBody = JSON.stringify(start.request.body);
|
|
1540
1499
|
}
|
|
1541
|
-
catch (
|
|
1500
|
+
catch (_error) {
|
|
1542
1501
|
finalBody = '{}';
|
|
1543
1502
|
}
|
|
1544
1503
|
}
|
|
1545
1504
|
const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
|
|
1546
1505
|
attributes: {
|
|
1547
|
-
[
|
|
1548
|
-
[
|
|
1506
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
|
|
1507
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
|
|
1549
1508
|
...attrHeaders,
|
|
1550
|
-
[
|
|
1509
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
|
|
1551
1510
|
...(start.attributes || {}),
|
|
1552
1511
|
},
|
|
1553
1512
|
});
|
|
1554
1513
|
return {
|
|
1555
|
-
|
|
1514
|
+
...span,
|
|
1556
1515
|
end: (options) => {
|
|
1557
1516
|
const end = options;
|
|
1558
1517
|
// Note: do not serialize headers as a single attribute because fields won't be redacted
|
|
@@ -1565,20 +1524,19 @@ class ManualInstrumentation {
|
|
|
1565
1524
|
try {
|
|
1566
1525
|
finalBody = JSON.stringify(end.response.body);
|
|
1567
1526
|
}
|
|
1568
|
-
catch (
|
|
1527
|
+
catch (_error) {
|
|
1569
1528
|
finalBody = '{}';
|
|
1570
1529
|
}
|
|
1571
1530
|
}
|
|
1572
1531
|
span.end({
|
|
1573
1532
|
attributes: {
|
|
1574
|
-
[
|
|
1533
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
|
|
1575
1534
|
...attrHeaders,
|
|
1576
|
-
[
|
|
1535
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
|
|
1577
1536
|
...(end.attributes || {}),
|
|
1578
1537
|
},
|
|
1579
1538
|
});
|
|
1580
1539
|
},
|
|
1581
|
-
fail: span.fail,
|
|
1582
1540
|
};
|
|
1583
1541
|
}
|
|
1584
1542
|
prompt(ctx, { documentLogUuid, versionUuid, promptUuid, projectId, experimentUuid, testDeploymentId, externalId, template, parameters, name, source, ...rest }) {
|
|
@@ -1586,49 +1544,50 @@ class ManualInstrumentation {
|
|
|
1586
1544
|
try {
|
|
1587
1545
|
jsonParameters = JSON.stringify(parameters || {});
|
|
1588
1546
|
}
|
|
1589
|
-
catch (
|
|
1547
|
+
catch (_error) {
|
|
1590
1548
|
jsonParameters = '{}';
|
|
1591
1549
|
}
|
|
1592
1550
|
const attributes = {
|
|
1593
|
-
[
|
|
1594
|
-
[
|
|
1595
|
-
[
|
|
1596
|
-
[
|
|
1597
|
-
[
|
|
1598
|
-
[
|
|
1551
|
+
[ATTRIBUTES.LATITUDE.request.template]: template,
|
|
1552
|
+
[ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
|
|
1553
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
|
|
1554
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1555
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1556
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1599
1557
|
...(experimentUuid && {
|
|
1600
|
-
[
|
|
1558
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
|
|
1601
1559
|
}),
|
|
1602
1560
|
...(testDeploymentId && {
|
|
1603
|
-
[
|
|
1561
|
+
[ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
|
|
1604
1562
|
}),
|
|
1605
|
-
...(externalId && { [
|
|
1606
|
-
...(source && { [
|
|
1563
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1564
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1607
1565
|
...(rest.attributes || {}),
|
|
1608
1566
|
};
|
|
1609
1567
|
return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
|
|
1610
1568
|
attributes,
|
|
1611
1569
|
});
|
|
1612
1570
|
}
|
|
1613
|
-
|
|
1614
|
-
return this.span(ctx, 'step', SpanType.Step, options);
|
|
1615
|
-
}
|
|
1616
|
-
chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
|
|
1571
|
+
chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
|
|
1617
1572
|
const attributes = {
|
|
1618
|
-
[
|
|
1619
|
-
[
|
|
1620
|
-
...(
|
|
1573
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1574
|
+
[ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
|
|
1575
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1576
|
+
...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
|
|
1577
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1621
1578
|
...(rest.attributes || {}),
|
|
1622
1579
|
};
|
|
1623
|
-
return this.span(ctx, name ||
|
|
1580
|
+
return this.span(ctx, name || `chat-${documentLogUuid}`, SpanType.Chat, {
|
|
1581
|
+
attributes,
|
|
1582
|
+
});
|
|
1624
1583
|
}
|
|
1625
1584
|
external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
|
|
1626
1585
|
const attributes = {
|
|
1627
|
-
[
|
|
1628
|
-
[
|
|
1629
|
-
[
|
|
1630
|
-
...(versionUuid && { [
|
|
1631
|
-
...(externalId && { [
|
|
1586
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1587
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1588
|
+
[ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
|
|
1589
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1590
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1632
1591
|
...(rest.attributes || {}),
|
|
1633
1592
|
};
|
|
1634
1593
|
return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
|
|
@@ -1637,11 +1596,11 @@ class ManualInstrumentation {
|
|
|
1637
1596
|
}
|
|
1638
1597
|
unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
|
|
1639
1598
|
const attributes = {
|
|
1640
|
-
[
|
|
1641
|
-
[
|
|
1642
|
-
...(versionUuid && { [
|
|
1599
|
+
[ATTRIBUTES.LATITUDE.promptPath]: path,
|
|
1600
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1601
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1643
1602
|
...(conversationUuid && {
|
|
1644
|
-
[
|
|
1603
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
|
|
1645
1604
|
}),
|
|
1646
1605
|
...(rest.attributes || {}),
|
|
1647
1606
|
};
|
|
@@ -1660,8 +1619,8 @@ class LatitudeInstrumentation {
|
|
|
1660
1619
|
return this.manualTelemetry.isEnabled();
|
|
1661
1620
|
}
|
|
1662
1621
|
enable() {
|
|
1663
|
-
this.options.module.instrument(this);
|
|
1664
1622
|
this.manualTelemetry.enable();
|
|
1623
|
+
this.options.module.instrument(this);
|
|
1665
1624
|
}
|
|
1666
1625
|
disable() {
|
|
1667
1626
|
this.manualTelemetry.disable();
|
|
@@ -1706,19 +1665,6 @@ class LatitudeInstrumentation {
|
|
|
1706
1665
|
$prompt.end();
|
|
1707
1666
|
return result;
|
|
1708
1667
|
}
|
|
1709
|
-
async wrapRenderStep(fn, ...args) {
|
|
1710
|
-
const $step = this.manualTelemetry.step(context.active());
|
|
1711
|
-
let result;
|
|
1712
|
-
try {
|
|
1713
|
-
result = await context.with($step.context, async () => await fn(...args));
|
|
1714
|
-
}
|
|
1715
|
-
catch (error) {
|
|
1716
|
-
$step.fail(error);
|
|
1717
|
-
throw error;
|
|
1718
|
-
}
|
|
1719
|
-
$step.end();
|
|
1720
|
-
return result;
|
|
1721
|
-
}
|
|
1722
1668
|
async wrapRenderCompletion(fn, ...args) {
|
|
1723
1669
|
if (!this.options.completions) {
|
|
1724
1670
|
return await fn(...args);
|
|
@@ -1752,8 +1698,8 @@ class LatitudeInstrumentation {
|
|
|
1752
1698
|
completion: completionTokens,
|
|
1753
1699
|
},
|
|
1754
1700
|
finishReason: result.toolRequests.length > 0
|
|
1755
|
-
?
|
|
1756
|
-
:
|
|
1701
|
+
? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
|
|
1702
|
+
: VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
|
|
1757
1703
|
});
|
|
1758
1704
|
return result;
|
|
1759
1705
|
}
|
|
@@ -1798,6 +1744,7 @@ var LatitudeErrorCodes;
|
|
|
1798
1744
|
LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
|
|
1799
1745
|
LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
|
|
1800
1746
|
LatitudeErrorCodes["AbortedError"] = "AbortedError";
|
|
1747
|
+
LatitudeErrorCodes["BillingError"] = "BillingError";
|
|
1801
1748
|
})(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
|
|
1802
1749
|
// NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
|
|
1803
1750
|
var RunErrorCodes;
|
|
@@ -1868,6 +1815,9 @@ class SpanFactory {
|
|
|
1868
1815
|
constructor(telemetry) {
|
|
1869
1816
|
this.telemetry = telemetry;
|
|
1870
1817
|
}
|
|
1818
|
+
span(options, ctx) {
|
|
1819
|
+
return this.telemetry.unknown(ctx ?? context.active(), options);
|
|
1820
|
+
}
|
|
1871
1821
|
tool(options, ctx) {
|
|
1872
1822
|
return this.telemetry.tool(ctx ?? context.active(), options);
|
|
1873
1823
|
}
|
|
@@ -1877,21 +1827,12 @@ class SpanFactory {
|
|
|
1877
1827
|
embedding(options, ctx) {
|
|
1878
1828
|
return this.telemetry.embedding(ctx ?? context.active(), options);
|
|
1879
1829
|
}
|
|
1880
|
-
retrieval(options, ctx) {
|
|
1881
|
-
return this.telemetry.retrieval(ctx ?? context.active(), options);
|
|
1882
|
-
}
|
|
1883
|
-
reranking(options, ctx) {
|
|
1884
|
-
return this.telemetry.reranking(ctx ?? context.active(), options);
|
|
1885
|
-
}
|
|
1886
1830
|
http(options, ctx) {
|
|
1887
1831
|
return this.telemetry.http(ctx ?? context.active(), options);
|
|
1888
1832
|
}
|
|
1889
1833
|
prompt(options, ctx) {
|
|
1890
1834
|
return this.telemetry.prompt(ctx ?? context.active(), options);
|
|
1891
1835
|
}
|
|
1892
|
-
step(options, ctx) {
|
|
1893
|
-
return this.telemetry.step(ctx ?? context.active(), options);
|
|
1894
|
-
}
|
|
1895
1836
|
chat(options, ctx) {
|
|
1896
1837
|
return this.telemetry.chat(ctx ?? context.active(), options);
|
|
1897
1838
|
}
|
|
@@ -1910,6 +1851,9 @@ class ContextManager {
|
|
|
1910
1851
|
active() {
|
|
1911
1852
|
return context.active();
|
|
1912
1853
|
}
|
|
1854
|
+
with(ctx, fn, thisArg, ...args) {
|
|
1855
|
+
return context.with(ctx, fn, thisArg, ...args);
|
|
1856
|
+
}
|
|
1913
1857
|
}
|
|
1914
1858
|
class InstrumentationManager {
|
|
1915
1859
|
instrumentations;
|
|
@@ -1956,6 +1900,23 @@ class ScopedTracerProvider {
|
|
|
1956
1900
|
return this.provider.getTracer(this.scope, this.version, options);
|
|
1957
1901
|
}
|
|
1958
1902
|
}
|
|
1903
|
+
class LifecycleManager {
|
|
1904
|
+
nodeProvider;
|
|
1905
|
+
exporter;
|
|
1906
|
+
constructor(nodeProvider, exporter) {
|
|
1907
|
+
this.nodeProvider = nodeProvider;
|
|
1908
|
+
this.exporter = exporter;
|
|
1909
|
+
}
|
|
1910
|
+
async flush() {
|
|
1911
|
+
await this.nodeProvider.forceFlush();
|
|
1912
|
+
await this.exporter.forceFlush?.();
|
|
1913
|
+
}
|
|
1914
|
+
async shutdown() {
|
|
1915
|
+
await this.flush();
|
|
1916
|
+
await this.nodeProvider.shutdown();
|
|
1917
|
+
await this.exporter.shutdown?.();
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1959
1920
|
const DEFAULT_SPAN_EXPORTER = (apiKey) => new OTLPTraceExporter({
|
|
1960
1921
|
url: TRACES_URL,
|
|
1961
1922
|
headers: {
|
|
@@ -1974,6 +1935,7 @@ var Instrumentation;
|
|
|
1974
1935
|
Instrumentation["Langchain"] = "langchain";
|
|
1975
1936
|
Instrumentation["Latitude"] = "latitude";
|
|
1976
1937
|
Instrumentation["LlamaIndex"] = "llamaindex";
|
|
1938
|
+
Instrumentation["Manual"] = "manual";
|
|
1977
1939
|
Instrumentation["OpenAI"] = "openai";
|
|
1978
1940
|
Instrumentation["TogetherAI"] = "togetherai";
|
|
1979
1941
|
Instrumentation["VertexAI"] = "vertexai";
|
|
@@ -1987,6 +1949,7 @@ class LatitudeTelemetry {
|
|
|
1987
1949
|
context;
|
|
1988
1950
|
instrumentation;
|
|
1989
1951
|
tracer;
|
|
1952
|
+
lifecycle;
|
|
1990
1953
|
constructor(apiKey, options) {
|
|
1991
1954
|
this.options = options || {};
|
|
1992
1955
|
if (!this.options.exporter) {
|
|
@@ -2003,6 +1966,7 @@ class LatitudeTelemetry {
|
|
|
2003
1966
|
this.nodeProvider = new NodeTracerProvider({
|
|
2004
1967
|
resource: new Resource({ [ATTR_SERVICE_NAME]: SERVICE_NAME }),
|
|
2005
1968
|
});
|
|
1969
|
+
this.lifecycle = new LifecycleManager(this.nodeProvider, this.options.exporter);
|
|
2006
1970
|
// Note: important, must run before the exporter span processors
|
|
2007
1971
|
this.nodeProvider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
|
|
2008
1972
|
if (this.options.processors) {
|
|
@@ -2032,19 +1996,16 @@ class LatitudeTelemetry {
|
|
|
2032
1996
|
this.context = new ContextManager(this.manualInstrumentation);
|
|
2033
1997
|
}
|
|
2034
1998
|
async flush() {
|
|
2035
|
-
await this.
|
|
2036
|
-
await this.options.exporter.forceFlush?.();
|
|
1999
|
+
await this.lifecycle.flush();
|
|
2037
2000
|
}
|
|
2038
2001
|
async shutdown() {
|
|
2039
|
-
await this.
|
|
2040
|
-
await this.nodeProvider.shutdown();
|
|
2041
|
-
await this.options.exporter.shutdown?.();
|
|
2002
|
+
await this.lifecycle.shutdown();
|
|
2042
2003
|
}
|
|
2043
2004
|
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
2044
2005
|
initInstrumentations() {
|
|
2045
2006
|
this.instrumentationsList = [];
|
|
2046
|
-
const tracer = this.tracer.get(
|
|
2047
|
-
this.manualInstrumentation = new ManualInstrumentation(tracer);
|
|
2007
|
+
const tracer = this.tracer.get(Instrumentation.Manual);
|
|
2008
|
+
this.manualInstrumentation = new ManualInstrumentation(tracer, this.options.instrumentations?.manual);
|
|
2048
2009
|
this.instrumentationsList.push(this.manualInstrumentation);
|
|
2049
2010
|
const latitude = this.options.instrumentations?.latitude;
|
|
2050
2011
|
if (latitude) {
|
|
@@ -2054,12 +2015,12 @@ class LatitudeTelemetry {
|
|
|
2054
2015
|
}
|
|
2055
2016
|
const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
|
|
2056
2017
|
const providerPkg = this.options.instrumentations?.[instrumentationType];
|
|
2018
|
+
if (!providerPkg)
|
|
2019
|
+
return;
|
|
2057
2020
|
const provider = this.tracer.provider(instrumentationType);
|
|
2058
2021
|
const instrumentation = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
|
|
2059
2022
|
instrumentation.setTracerProvider(provider);
|
|
2060
|
-
|
|
2061
|
-
instrumentation.manuallyInstrument(providerPkg);
|
|
2062
|
-
}
|
|
2023
|
+
instrumentation.manuallyInstrument(providerPkg);
|
|
2063
2024
|
registerInstrumentations({
|
|
2064
2025
|
instrumentations: [instrumentation],
|
|
2065
2026
|
tracerProvider: provider,
|
|
@@ -2072,27 +2033,26 @@ class LatitudeTelemetry {
|
|
|
2072
2033
|
configureInstrumentation(Instrumentation.Cohere, CohereInstrumentation); // prettier-ignore
|
|
2073
2034
|
configureInstrumentation(Instrumentation.Langchain, LangChainInstrumentation); // prettier-ignore
|
|
2074
2035
|
configureInstrumentation(Instrumentation.LlamaIndex, LlamaIndexInstrumentation); // prettier-ignore
|
|
2075
|
-
|
|
2076
|
-
configureInstrumentation(Instrumentation.
|
|
2036
|
+
// NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
|
|
2037
|
+
configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2038
|
+
configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2077
2039
|
configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
|
|
2078
2040
|
}
|
|
2079
2041
|
async capture(options, fn) {
|
|
2080
2042
|
if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
|
|
2081
2043
|
throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
|
|
2082
2044
|
}
|
|
2083
|
-
const span = this.manualInstrumentation.unresolvedExternal(
|
|
2045
|
+
const span = this.manualInstrumentation.unresolvedExternal(BACKGROUND(), options);
|
|
2046
|
+
let result;
|
|
2084
2047
|
try {
|
|
2085
|
-
|
|
2086
|
-
span.end();
|
|
2087
|
-
return result;
|
|
2048
|
+
result = await context.with(span.context, async () => await fn(span.context));
|
|
2088
2049
|
}
|
|
2089
2050
|
catch (error) {
|
|
2090
2051
|
span.fail(error);
|
|
2091
2052
|
throw error;
|
|
2092
2053
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
}
|
|
2054
|
+
span.end();
|
|
2055
|
+
return result;
|
|
2096
2056
|
}
|
|
2097
2057
|
}
|
|
2098
2058
|
|