@latitude-data/telemetry 1.0.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +613 -261
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +170 -64
- package/dist/index.js +614 -262
- package/dist/index.js.map +1 -1
- package/package.json +11 -8
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import * as otel from '@opentelemetry/api';
|
|
3
|
-
import { propagation, trace, context } from '@opentelemetry/api';
|
|
4
|
-
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
5
2
|
import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
|
|
3
|
+
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
4
|
+
import * as otel from '@opentelemetry/api';
|
|
5
|
+
import { trace, propagation, context } from '@opentelemetry/api';
|
|
6
|
+
import { v4 } from 'uuid';
|
|
6
7
|
import { BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS } from '@opentelemetry/baggage-span-processor';
|
|
7
8
|
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
|
|
8
9
|
import { CompositePropagator, W3CTraceContextPropagator, W3CBaggagePropagator } from '@opentelemetry/core';
|
|
@@ -74,7 +75,7 @@ const DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
|
|
|
74
75
|
attributes: [
|
|
75
76
|
/^.*auth.*$/i,
|
|
76
77
|
/^.*authorization.*$/i,
|
|
77
|
-
/^(?!
|
|
78
|
+
/^(?!gen_ai\.).*usage.*$/i,
|
|
78
79
|
/^(?!gen_ai\.).*token.*$/i,
|
|
79
80
|
/^.*secret.*$/i,
|
|
80
81
|
/^.*key.*$/i,
|
|
@@ -129,6 +130,15 @@ z.object({
|
|
|
129
130
|
isError: z.boolean().optional(),
|
|
130
131
|
text: z.string().optional(),
|
|
131
132
|
});
|
|
133
|
+
z.object({
|
|
134
|
+
inputTokens: z.number(),
|
|
135
|
+
outputTokens: z.number(),
|
|
136
|
+
promptTokens: z.number(),
|
|
137
|
+
completionTokens: z.number(),
|
|
138
|
+
totalTokens: z.number(),
|
|
139
|
+
reasoningTokens: z.number(),
|
|
140
|
+
cachedInputTokens: z.number(),
|
|
141
|
+
});
|
|
132
142
|
|
|
133
143
|
var ParameterType;
|
|
134
144
|
(function (ParameterType) {
|
|
@@ -254,12 +264,34 @@ const CompositeEvaluationSpecification = {
|
|
|
254
264
|
},
|
|
255
265
|
};
|
|
256
266
|
|
|
267
|
+
const selectedContextSchema = z.object({
|
|
268
|
+
messageIndex: z.number().int().nonnegative(),
|
|
269
|
+
contentBlockIndex: z.number().int().nonnegative(),
|
|
270
|
+
contentType: z.enum([
|
|
271
|
+
'text',
|
|
272
|
+
'reasoning',
|
|
273
|
+
'image',
|
|
274
|
+
'file',
|
|
275
|
+
'tool-call',
|
|
276
|
+
'tool-result',
|
|
277
|
+
]),
|
|
278
|
+
textRange: z
|
|
279
|
+
.object({
|
|
280
|
+
start: z.number().int().nonnegative(),
|
|
281
|
+
end: z.number().int().nonnegative(),
|
|
282
|
+
})
|
|
283
|
+
.optional(),
|
|
284
|
+
selectedText: z.string().optional(),
|
|
285
|
+
toolCallId: z.string().optional(),
|
|
286
|
+
});
|
|
257
287
|
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
258
|
-
enableControls: z.boolean().optional(),
|
|
288
|
+
enableControls: z.boolean().optional(), // UI annotation controls
|
|
259
289
|
criteria: z.string().optional(),
|
|
260
290
|
});
|
|
261
291
|
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
262
292
|
reason: z.string().optional(),
|
|
293
|
+
enrichedReason: z.string().optional(),
|
|
294
|
+
selectedContexts: z.array(selectedContextSchema).optional(),
|
|
263
295
|
});
|
|
264
296
|
const humanEvaluationResultError = baseEvaluationResultError.extend({});
|
|
265
297
|
// BINARY
|
|
@@ -537,8 +569,6 @@ z.object({
|
|
|
537
569
|
});
|
|
538
570
|
z.object({
|
|
539
571
|
evaluateLiveLogs: z.boolean().nullable().optional(),
|
|
540
|
-
enableSuggestions: z.boolean().nullable().optional(),
|
|
541
|
-
autoApplySuggestions: z.boolean().nullable().optional(),
|
|
542
572
|
});
|
|
543
573
|
|
|
544
574
|
var LegacyChainEventTypes;
|
|
@@ -736,6 +766,7 @@ var LogSources;
|
|
|
736
766
|
LogSources["ShadowTest"] = "shadow_test";
|
|
737
767
|
LogSources["ABTestChallenger"] = "ab_test_challenger";
|
|
738
768
|
LogSources["User"] = "user";
|
|
769
|
+
LogSources["Optimization"] = "optimization";
|
|
739
770
|
})(LogSources || (LogSources = {}));
|
|
740
771
|
|
|
741
772
|
var RunSourceGroup;
|
|
@@ -746,7 +777,8 @@ var RunSourceGroup;
|
|
|
746
777
|
({
|
|
747
778
|
[RunSourceGroup.Production]: [
|
|
748
779
|
LogSources.API,
|
|
749
|
-
LogSources.
|
|
780
|
+
LogSources.ShadowTest,
|
|
781
|
+
LogSources.ABTestChallenger,
|
|
750
782
|
LogSources.EmailTrigger,
|
|
751
783
|
LogSources.IntegrationTrigger,
|
|
752
784
|
LogSources.ScheduledTrigger,
|
|
@@ -775,23 +807,49 @@ var SpanKind;
|
|
|
775
807
|
// Note: loosely based on OpenTelemetry GenAI semantic conventions
|
|
776
808
|
var SpanType;
|
|
777
809
|
(function (SpanType) {
|
|
778
|
-
|
|
810
|
+
// Latitude wrappers
|
|
811
|
+
SpanType["Prompt"] = "prompt";
|
|
812
|
+
SpanType["Chat"] = "chat";
|
|
813
|
+
SpanType["External"] = "external";
|
|
814
|
+
SpanType["UnresolvedExternal"] = "unresolved_external";
|
|
815
|
+
// Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
|
|
816
|
+
SpanType["Http"] = "http";
|
|
817
|
+
// Any known span from supported specifications will be grouped into one of these types
|
|
779
818
|
SpanType["Completion"] = "completion";
|
|
819
|
+
SpanType["Tool"] = "tool";
|
|
780
820
|
SpanType["Embedding"] = "embedding";
|
|
781
|
-
SpanType["Retrieval"] = "retrieval";
|
|
782
|
-
SpanType["Reranking"] = "reranking";
|
|
783
|
-
SpanType["Http"] = "http";
|
|
784
821
|
SpanType["Unknown"] = "unknown";
|
|
785
|
-
SpanType["Prompt"] = "prompt";
|
|
786
|
-
SpanType["Step"] = "step";
|
|
787
822
|
})(SpanType || (SpanType = {}));
|
|
823
|
+
[
|
|
824
|
+
SpanType.Prompt,
|
|
825
|
+
SpanType.External,
|
|
826
|
+
SpanType.Chat,
|
|
827
|
+
];
|
|
788
828
|
const SPAN_SPECIFICATIONS = {
|
|
789
|
-
[SpanType.
|
|
790
|
-
name: '
|
|
791
|
-
description: 'A
|
|
792
|
-
isGenAI:
|
|
829
|
+
[SpanType.Prompt]: {
|
|
830
|
+
name: 'Prompt',
|
|
831
|
+
description: 'A prompt span',
|
|
832
|
+
isGenAI: false,
|
|
793
833
|
isHidden: false,
|
|
794
834
|
},
|
|
835
|
+
[SpanType.Chat]: {
|
|
836
|
+
name: 'Chat',
|
|
837
|
+
description: 'A chat continuation span',
|
|
838
|
+
isGenAI: false,
|
|
839
|
+
isHidden: false,
|
|
840
|
+
},
|
|
841
|
+
[SpanType.External]: {
|
|
842
|
+
name: 'External',
|
|
843
|
+
description: 'An external capture span',
|
|
844
|
+
isGenAI: false,
|
|
845
|
+
isHidden: false,
|
|
846
|
+
},
|
|
847
|
+
[SpanType.UnresolvedExternal]: {
|
|
848
|
+
name: 'Unresolved External',
|
|
849
|
+
description: 'An external span that needs path resolution before storage',
|
|
850
|
+
isGenAI: false,
|
|
851
|
+
isHidden: true,
|
|
852
|
+
},
|
|
795
853
|
[SpanType.Completion]: {
|
|
796
854
|
name: 'Completion',
|
|
797
855
|
description: 'A completion call',
|
|
@@ -804,15 +862,9 @@ const SPAN_SPECIFICATIONS = {
|
|
|
804
862
|
isGenAI: true,
|
|
805
863
|
isHidden: false,
|
|
806
864
|
},
|
|
807
|
-
[SpanType.
|
|
808
|
-
name: '
|
|
809
|
-
description: 'A
|
|
810
|
-
isGenAI: true,
|
|
811
|
-
isHidden: false,
|
|
812
|
-
},
|
|
813
|
-
[SpanType.Reranking]: {
|
|
814
|
-
name: 'Reranking',
|
|
815
|
-
description: 'A reranking call',
|
|
865
|
+
[SpanType.Tool]: {
|
|
866
|
+
name: 'Tool',
|
|
867
|
+
description: 'A tool call',
|
|
816
868
|
isGenAI: true,
|
|
817
869
|
isHidden: false,
|
|
818
870
|
},
|
|
@@ -828,18 +880,6 @@ const SPAN_SPECIFICATIONS = {
|
|
|
828
880
|
isGenAI: false,
|
|
829
881
|
isHidden: true,
|
|
830
882
|
},
|
|
831
|
-
[SpanType.Prompt]: {
|
|
832
|
-
name: 'Prompt',
|
|
833
|
-
description: 'A prompt span',
|
|
834
|
-
isGenAI: false,
|
|
835
|
-
isHidden: false,
|
|
836
|
-
},
|
|
837
|
-
[SpanType.Step]: {
|
|
838
|
-
name: 'Step',
|
|
839
|
-
description: 'A step span',
|
|
840
|
-
isGenAI: false,
|
|
841
|
-
isHidden: false,
|
|
842
|
-
},
|
|
843
883
|
};
|
|
844
884
|
var SpanStatus;
|
|
845
885
|
(function (SpanStatus) {
|
|
@@ -847,6 +887,11 @@ var SpanStatus;
|
|
|
847
887
|
SpanStatus["Ok"] = "ok";
|
|
848
888
|
SpanStatus["Error"] = "error";
|
|
849
889
|
})(SpanStatus || (SpanStatus = {}));
|
|
890
|
+
new Set([
|
|
891
|
+
SpanType.Prompt,
|
|
892
|
+
SpanType.Chat,
|
|
893
|
+
SpanType.External,
|
|
894
|
+
]);
|
|
850
895
|
|
|
851
896
|
// Note: Traces are unmaterialized but this context is used to propagate the trace
|
|
852
897
|
// See www.w3.org/TR/trace-context and w3c.github.io/baggage
|
|
@@ -856,6 +901,130 @@ z.object({
|
|
|
856
901
|
baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
|
|
857
902
|
});
|
|
858
903
|
|
|
904
|
+
const ATTRIBUTES = {
|
|
905
|
+
// Custom attributes added and used by Latitude spans (Prompt / External / Chat)
|
|
906
|
+
LATITUDE: {
|
|
907
|
+
type: 'latitude.type',
|
|
908
|
+
documentUuid: 'latitude.document_uuid',
|
|
909
|
+
promptPath: 'latitude.prompt_path',
|
|
910
|
+
commitUuid: 'latitude.commit_uuid',
|
|
911
|
+
documentLogUuid: 'latitude.document_log_uuid',
|
|
912
|
+
projectId: 'latitude.project_id',
|
|
913
|
+
experimentUuid: 'latitude.experiment_uuid',
|
|
914
|
+
source: 'latitude.source',
|
|
915
|
+
externalId: 'latitude.external_id',
|
|
916
|
+
testDeploymentId: 'latitude.test_deployment_id',
|
|
917
|
+
previousTraceId: 'latitude.previous_trace_id',
|
|
918
|
+
// Custom additions to the GenAI semantic conventions (deprecated)
|
|
919
|
+
request: {
|
|
920
|
+
_root: 'gen_ai.request',
|
|
921
|
+
configuration: 'gen_ai.request.configuration',
|
|
922
|
+
template: 'gen_ai.request.template',
|
|
923
|
+
parameters: 'gen_ai.request.parameters',
|
|
924
|
+
messages: 'gen_ai.request.messages'},
|
|
925
|
+
response: {
|
|
926
|
+
_root: 'gen_ai.response',
|
|
927
|
+
messages: 'gen_ai.response.messages',
|
|
928
|
+
},
|
|
929
|
+
usage: {
|
|
930
|
+
promptTokens: 'gen_ai.usage.prompt_tokens',
|
|
931
|
+
cachedTokens: 'gen_ai.usage.cached_tokens',
|
|
932
|
+
reasoningTokens: 'gen_ai.usage.reasoning_tokens',
|
|
933
|
+
completionTokens: 'gen_ai.usage.completion_tokens',
|
|
934
|
+
},
|
|
935
|
+
},
|
|
936
|
+
// Official OpenTelemetry semantic conventions
|
|
937
|
+
OPENTELEMETRY: {
|
|
938
|
+
HTTP: {
|
|
939
|
+
request: {
|
|
940
|
+
url: 'http.request.url',
|
|
941
|
+
body: 'http.request.body',
|
|
942
|
+
header: 'http.request.header',
|
|
943
|
+
method: ATTR_HTTP_REQUEST_METHOD,
|
|
944
|
+
},
|
|
945
|
+
response: {
|
|
946
|
+
body: 'http.response.body',
|
|
947
|
+
header: 'http.response.header',
|
|
948
|
+
statusCode: ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
949
|
+
},
|
|
950
|
+
},
|
|
951
|
+
// GenAI semantic conventions
|
|
952
|
+
// https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
|
|
953
|
+
GEN_AI: {
|
|
954
|
+
operation: ATTR_GEN_AI_OPERATION_NAME,
|
|
955
|
+
response: {
|
|
956
|
+
model: ATTR_GEN_AI_RESPONSE_MODEL,
|
|
957
|
+
finishReasons: ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
|
|
958
|
+
},
|
|
959
|
+
usage: {
|
|
960
|
+
inputTokens: ATTR_GEN_AI_USAGE_INPUT_TOKENS,
|
|
961
|
+
outputTokens: ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
|
|
962
|
+
},
|
|
963
|
+
tool: {
|
|
964
|
+
call: {
|
|
965
|
+
id: ATTR_GEN_AI_TOOL_CALL_ID,
|
|
966
|
+
arguments: 'gen_ai.tool.call.arguments'}},
|
|
967
|
+
_deprecated: {
|
|
968
|
+
system: ATTR_GEN_AI_SYSTEM,
|
|
969
|
+
tool: {
|
|
970
|
+
name: ATTR_GEN_AI_TOOL_NAME,
|
|
971
|
+
type: ATTR_GEN_AI_TOOL_TYPE,
|
|
972
|
+
result: {
|
|
973
|
+
value: 'gen_ai.tool.result.value',
|
|
974
|
+
isError: 'gen_ai.tool.result.is_error',
|
|
975
|
+
},
|
|
976
|
+
},
|
|
977
|
+
prompt: {
|
|
978
|
+
_root: 'gen_ai.prompt',
|
|
979
|
+
index: (promptIndex) => ({
|
|
980
|
+
role: `gen_ai.prompt.${promptIndex}.role`,
|
|
981
|
+
content: `gen_ai.prompt.${promptIndex}.content`, // string or object
|
|
982
|
+
toolCalls: (toolCallIndex) => ({
|
|
983
|
+
id: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.id`,
|
|
984
|
+
name: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.name`,
|
|
985
|
+
arguments: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.arguments`,
|
|
986
|
+
}),
|
|
987
|
+
tool: {
|
|
988
|
+
callId: `gen_ai.prompt.${promptIndex}.tool_call_id`,
|
|
989
|
+
toolName: `gen_ai.prompt.${promptIndex}.tool_name`,
|
|
990
|
+
isError: `gen_ai.prompt.${promptIndex}.is_error`,
|
|
991
|
+
},
|
|
992
|
+
}),
|
|
993
|
+
},
|
|
994
|
+
completion: {
|
|
995
|
+
_root: 'gen_ai.completion',
|
|
996
|
+
index: (completionIndex) => ({
|
|
997
|
+
role: `gen_ai.completion.${completionIndex}.role`,
|
|
998
|
+
content: `gen_ai.completion.${completionIndex}.content`, // string or object
|
|
999
|
+
toolCalls: (toolCallIndex) => ({
|
|
1000
|
+
id: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.id`,
|
|
1001
|
+
name: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.name`,
|
|
1002
|
+
arguments: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.arguments`,
|
|
1003
|
+
}),
|
|
1004
|
+
tool: {
|
|
1005
|
+
callId: `gen_ai.prompt.${completionIndex}.tool_call_id`,
|
|
1006
|
+
toolName: `gen_ai.prompt.${completionIndex}.tool_name`,
|
|
1007
|
+
isError: `gen_ai.prompt.${completionIndex}.is_error`,
|
|
1008
|
+
},
|
|
1009
|
+
}),
|
|
1010
|
+
}},
|
|
1011
|
+
},
|
|
1012
|
+
}};
|
|
1013
|
+
const VALUES = {
|
|
1014
|
+
OPENTELEMETRY: {
|
|
1015
|
+
GEN_AI: {
|
|
1016
|
+
response: {
|
|
1017
|
+
finishReasons: {
|
|
1018
|
+
stop: 'stop',
|
|
1019
|
+
toolCalls: 'tool_calls'},
|
|
1020
|
+
},
|
|
1021
|
+
tool: {
|
|
1022
|
+
type: {
|
|
1023
|
+
function: 'function',
|
|
1024
|
+
},
|
|
1025
|
+
}},
|
|
1026
|
+
}};
|
|
1027
|
+
|
|
859
1028
|
/* Note: Instrumentation scopes from all language SDKs */
|
|
860
1029
|
const SCOPE_LATITUDE = 'so.latitude.instrumentation';
|
|
861
1030
|
var InstrumentationScope;
|
|
@@ -884,43 +1053,6 @@ var InstrumentationScope;
|
|
|
884
1053
|
InstrumentationScope["Transformers"] = "transformers";
|
|
885
1054
|
InstrumentationScope["AlephAlpha"] = "alephalpha";
|
|
886
1055
|
})(InstrumentationScope || (InstrumentationScope = {}));
|
|
887
|
-
/* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
|
|
888
|
-
const ATTR_LATITUDE = 'latitude';
|
|
889
|
-
const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
|
|
890
|
-
const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
|
|
891
|
-
const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
|
|
892
|
-
const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
|
|
893
|
-
const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
|
|
894
|
-
const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
|
|
895
|
-
const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
|
|
896
|
-
const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
|
|
897
|
-
const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
|
|
898
|
-
const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
|
|
899
|
-
const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
|
|
900
|
-
const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
|
|
901
|
-
const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
|
|
902
|
-
const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
|
|
903
|
-
const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
|
|
904
|
-
const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
|
|
905
|
-
const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
|
|
906
|
-
const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
|
|
907
|
-
const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
|
|
908
|
-
const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
|
|
909
|
-
const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
|
|
910
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
|
|
911
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
|
|
912
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
|
|
913
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
|
|
914
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
|
|
915
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
|
|
916
|
-
const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
|
|
917
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
|
|
918
|
-
const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
|
|
919
|
-
const ATTR_HTTP_REQUEST_URL = 'http.request.url';
|
|
920
|
-
const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
|
|
921
|
-
const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
|
|
922
|
-
const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
|
|
923
|
-
const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
|
|
924
1056
|
/* Note: Schemas for span ingestion following OpenTelemetry service request specification */
|
|
925
1057
|
var Otlp;
|
|
926
1058
|
(function (Otlp) {
|
|
@@ -1001,6 +1133,40 @@ var Otlp;
|
|
|
1001
1133
|
});
|
|
1002
1134
|
})(Otlp || (Otlp = {}));
|
|
1003
1135
|
|
|
1136
|
+
const MAX_SIMULATION_TURNS = 10;
|
|
1137
|
+
const SimulationSettingsSchema = z.object({
|
|
1138
|
+
simulateToolResponses: z.boolean().optional(),
|
|
1139
|
+
simulatedTools: z.array(z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
|
|
1140
|
+
toolSimulationInstructions: z.string().optional(), // A prompt used to guide and generate the simulation result
|
|
1141
|
+
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.
|
|
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
|
+
|
|
1004
1170
|
// TODO(tracing): deprecated
|
|
1005
1171
|
const HEAD_COMMIT = 'live';
|
|
1006
1172
|
var Providers;
|
|
@@ -1044,6 +1210,7 @@ var DocumentTriggerParameters;
|
|
|
1044
1210
|
DocumentTriggerParameters["Body"] = "body";
|
|
1045
1211
|
DocumentTriggerParameters["Attachments"] = "attachments";
|
|
1046
1212
|
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
1213
|
+
const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
|
|
1047
1214
|
|
|
1048
1215
|
class ManualInstrumentation {
|
|
1049
1216
|
enabled;
|
|
@@ -1062,7 +1229,33 @@ class ManualInstrumentation {
|
|
|
1062
1229
|
this.enabled = false;
|
|
1063
1230
|
}
|
|
1064
1231
|
resume(ctx) {
|
|
1065
|
-
|
|
1232
|
+
const parts = ctx.traceparent.split('-');
|
|
1233
|
+
if (parts.length !== 4) {
|
|
1234
|
+
return otel.ROOT_CONTEXT;
|
|
1235
|
+
}
|
|
1236
|
+
const [, traceId, spanId, flags] = parts;
|
|
1237
|
+
if (!traceId || !spanId) {
|
|
1238
|
+
return otel.ROOT_CONTEXT;
|
|
1239
|
+
}
|
|
1240
|
+
const spanContext = {
|
|
1241
|
+
traceId,
|
|
1242
|
+
spanId,
|
|
1243
|
+
traceFlags: parseInt(flags ?? '01', 16),
|
|
1244
|
+
isRemote: true,
|
|
1245
|
+
};
|
|
1246
|
+
let context = trace.setSpanContext(otel.ROOT_CONTEXT, spanContext);
|
|
1247
|
+
if (ctx.baggage) {
|
|
1248
|
+
const baggageEntries = {};
|
|
1249
|
+
for (const pair of ctx.baggage.split(',')) {
|
|
1250
|
+
const [key, value] = pair.split('=');
|
|
1251
|
+
if (key && value) {
|
|
1252
|
+
baggageEntries[key] = { value: decodeURIComponent(value) };
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
const baggage = propagation.createBaggage(baggageEntries);
|
|
1256
|
+
context = propagation.setBaggage(context, baggage);
|
|
1257
|
+
}
|
|
1258
|
+
return context;
|
|
1066
1259
|
}
|
|
1067
1260
|
capitalize(str) {
|
|
1068
1261
|
if (str.length === 0)
|
|
@@ -1119,9 +1312,9 @@ class ManualInstrumentation {
|
|
|
1119
1312
|
}
|
|
1120
1313
|
const span = this.tracer.startSpan(name, {
|
|
1121
1314
|
attributes: {
|
|
1122
|
-
[
|
|
1315
|
+
[ATTRIBUTES.LATITUDE.type]: type,
|
|
1123
1316
|
...(operation && {
|
|
1124
|
-
[
|
|
1317
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
|
|
1125
1318
|
}),
|
|
1126
1319
|
...(start.attributes || {}),
|
|
1127
1320
|
},
|
|
@@ -1147,15 +1340,15 @@ class ManualInstrumentation {
|
|
|
1147
1340
|
try {
|
|
1148
1341
|
jsonArguments = JSON.stringify(start.call.arguments);
|
|
1149
1342
|
}
|
|
1150
|
-
catch (
|
|
1343
|
+
catch (_error) {
|
|
1151
1344
|
jsonArguments = '{}';
|
|
1152
1345
|
}
|
|
1153
1346
|
const span = this.span(ctx, start.name, SpanType.Tool, {
|
|
1154
1347
|
attributes: {
|
|
1155
|
-
[
|
|
1156
|
-
[
|
|
1157
|
-
[
|
|
1158
|
-
[
|
|
1348
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
|
|
1349
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
|
|
1350
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
|
|
1351
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
|
|
1159
1352
|
...(start.attributes || {}),
|
|
1160
1353
|
},
|
|
1161
1354
|
});
|
|
@@ -1168,7 +1361,7 @@ class ManualInstrumentation {
|
|
|
1168
1361
|
try {
|
|
1169
1362
|
stringResult = JSON.stringify(end.result.value);
|
|
1170
1363
|
}
|
|
1171
|
-
catch (
|
|
1364
|
+
catch (_error) {
|
|
1172
1365
|
stringResult = '{}';
|
|
1173
1366
|
}
|
|
1174
1367
|
}
|
|
@@ -1177,8 +1370,8 @@ class ManualInstrumentation {
|
|
|
1177
1370
|
}
|
|
1178
1371
|
span.end({
|
|
1179
1372
|
attributes: {
|
|
1180
|
-
[
|
|
1181
|
-
[
|
|
1373
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
|
|
1374
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
|
|
1182
1375
|
...(end.attributes || {}),
|
|
1183
1376
|
},
|
|
1184
1377
|
});
|
|
@@ -1186,12 +1379,12 @@ class ManualInstrumentation {
|
|
|
1186
1379
|
fail: span.fail,
|
|
1187
1380
|
};
|
|
1188
1381
|
}
|
|
1189
|
-
attribifyMessageToolCalls(
|
|
1382
|
+
attribifyMessageToolCalls(otelMessageField, toolCalls) {
|
|
1190
1383
|
const attributes = {};
|
|
1191
1384
|
for (let i = 0; i < toolCalls.length; i++) {
|
|
1192
1385
|
for (const key in toolCalls[i]) {
|
|
1193
1386
|
const field = this.toCamelCase(key);
|
|
1194
|
-
|
|
1387
|
+
const value = toolCalls[i][key];
|
|
1195
1388
|
if (value === null || value === undefined)
|
|
1196
1389
|
continue;
|
|
1197
1390
|
switch (field) {
|
|
@@ -1200,28 +1393,29 @@ class ManualInstrumentation {
|
|
|
1200
1393
|
case 'toolUseId': {
|
|
1201
1394
|
if (typeof value !== 'string')
|
|
1202
1395
|
continue;
|
|
1203
|
-
attributes[
|
|
1396
|
+
attributes[otelMessageField.toolCalls(i).id] = value;
|
|
1204
1397
|
break;
|
|
1205
1398
|
}
|
|
1206
1399
|
case 'name':
|
|
1207
1400
|
case 'toolName': {
|
|
1208
1401
|
if (typeof value !== 'string')
|
|
1209
1402
|
continue;
|
|
1210
|
-
attributes[
|
|
1403
|
+
attributes[otelMessageField.toolCalls(i).name] = value;
|
|
1211
1404
|
break;
|
|
1212
1405
|
}
|
|
1213
1406
|
case 'arguments':
|
|
1214
1407
|
case 'toolArguments':
|
|
1215
1408
|
case 'input': {
|
|
1216
1409
|
if (typeof value === 'string') {
|
|
1217
|
-
attributes[
|
|
1410
|
+
attributes[otelMessageField.toolCalls(i).arguments] = value;
|
|
1218
1411
|
}
|
|
1219
1412
|
else {
|
|
1220
1413
|
try {
|
|
1221
|
-
attributes[
|
|
1414
|
+
attributes[otelMessageField.toolCalls(i).arguments] =
|
|
1415
|
+
JSON.stringify(value);
|
|
1222
1416
|
}
|
|
1223
|
-
catch (
|
|
1224
|
-
attributes[
|
|
1417
|
+
catch (_error) {
|
|
1418
|
+
attributes[otelMessageField.toolCalls(i).arguments] = '{}';
|
|
1225
1419
|
}
|
|
1226
1420
|
}
|
|
1227
1421
|
break;
|
|
@@ -1238,8 +1432,9 @@ class ManualInstrumentation {
|
|
|
1238
1432
|
continue;
|
|
1239
1433
|
if (typeof value.arguments !== 'string')
|
|
1240
1434
|
continue;
|
|
1241
|
-
attributes[
|
|
1242
|
-
attributes[
|
|
1435
|
+
attributes[otelMessageField.toolCalls(i).name] = value.name;
|
|
1436
|
+
attributes[otelMessageField.toolCalls(i).arguments] =
|
|
1437
|
+
value.arguments;
|
|
1243
1438
|
break;
|
|
1244
1439
|
}
|
|
1245
1440
|
}
|
|
@@ -1247,18 +1442,16 @@ class ManualInstrumentation {
|
|
|
1247
1442
|
}
|
|
1248
1443
|
return attributes;
|
|
1249
1444
|
}
|
|
1250
|
-
attribifyMessageContent(
|
|
1445
|
+
attribifyMessageContent(otelMessageField, content) {
|
|
1251
1446
|
let attributes = {};
|
|
1252
1447
|
if (typeof content === 'string') {
|
|
1253
|
-
attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
|
|
1254
1448
|
return attributes;
|
|
1255
1449
|
}
|
|
1256
1450
|
try {
|
|
1257
|
-
attributes[
|
|
1258
|
-
JSON.stringify(content);
|
|
1451
|
+
attributes[otelMessageField.content] = JSON.stringify(content);
|
|
1259
1452
|
}
|
|
1260
|
-
catch (
|
|
1261
|
-
attributes[
|
|
1453
|
+
catch (_error) {
|
|
1454
|
+
attributes[otelMessageField.content] = '[]';
|
|
1262
1455
|
}
|
|
1263
1456
|
if (!Array.isArray(content))
|
|
1264
1457
|
return attributes;
|
|
@@ -1278,32 +1471,34 @@ class ManualInstrumentation {
|
|
|
1278
1471
|
if (toolCalls.length > 0) {
|
|
1279
1472
|
attributes = {
|
|
1280
1473
|
...attributes,
|
|
1281
|
-
...this.attribifyMessageToolCalls(
|
|
1474
|
+
...this.attribifyMessageToolCalls(otelMessageField, toolCalls),
|
|
1282
1475
|
};
|
|
1283
1476
|
}
|
|
1284
1477
|
return attributes;
|
|
1285
1478
|
}
|
|
1286
1479
|
attribifyMessages(direction, messages) {
|
|
1287
|
-
const
|
|
1480
|
+
const otelField = direction === 'input'
|
|
1481
|
+
? ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.prompt
|
|
1482
|
+
: ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.completion;
|
|
1288
1483
|
let attributes = {};
|
|
1289
1484
|
for (let i = 0; i < messages.length; i++) {
|
|
1290
1485
|
for (const key in messages[i]) {
|
|
1291
1486
|
const field = this.toCamelCase(key);
|
|
1292
|
-
|
|
1487
|
+
const value = messages[i][key];
|
|
1293
1488
|
if (value === null || value === undefined)
|
|
1294
1489
|
continue;
|
|
1295
1490
|
switch (field) {
|
|
1296
1491
|
case 'role': {
|
|
1297
1492
|
if (typeof value !== 'string')
|
|
1298
1493
|
continue;
|
|
1299
|
-
attributes[
|
|
1494
|
+
attributes[otelField.index(i).role] = value;
|
|
1300
1495
|
break;
|
|
1301
1496
|
}
|
|
1302
1497
|
/* Tool calls for Anthropic and PromptL are in the content */
|
|
1303
1498
|
case 'content': {
|
|
1304
1499
|
attributes = {
|
|
1305
1500
|
...attributes,
|
|
1306
|
-
...this.attribifyMessageContent(
|
|
1501
|
+
...this.attribifyMessageContent(otelField.index(i), value),
|
|
1307
1502
|
};
|
|
1308
1503
|
break;
|
|
1309
1504
|
}
|
|
@@ -1313,7 +1508,7 @@ class ManualInstrumentation {
|
|
|
1313
1508
|
continue;
|
|
1314
1509
|
attributes = {
|
|
1315
1510
|
...attributes,
|
|
1316
|
-
...this.attribifyMessageToolCalls(
|
|
1511
|
+
...this.attribifyMessageToolCalls(otelField.index(i), value),
|
|
1317
1512
|
};
|
|
1318
1513
|
break;
|
|
1319
1514
|
}
|
|
@@ -1323,22 +1518,20 @@ class ManualInstrumentation {
|
|
|
1323
1518
|
case 'toolUseId': {
|
|
1324
1519
|
if (typeof value !== 'string')
|
|
1325
1520
|
continue;
|
|
1326
|
-
attributes[
|
|
1327
|
-
value;
|
|
1521
|
+
attributes[otelField.index(i).tool.callId] = value;
|
|
1328
1522
|
break;
|
|
1329
1523
|
}
|
|
1330
1524
|
case 'toolName': {
|
|
1331
1525
|
if (typeof value !== 'string')
|
|
1332
1526
|
continue;
|
|
1333
|
-
attributes[
|
|
1334
|
-
value;
|
|
1527
|
+
attributes[otelField.index(i).tool.toolName] = value;
|
|
1335
1528
|
break;
|
|
1336
1529
|
}
|
|
1337
1530
|
// Note: 'toolResult' is 'content' itself
|
|
1338
1531
|
case 'isError': {
|
|
1339
1532
|
if (typeof value !== 'boolean')
|
|
1340
1533
|
continue;
|
|
1341
|
-
attributes[
|
|
1534
|
+
attributes[otelField.index(i).tool.isError] = value;
|
|
1342
1535
|
break;
|
|
1343
1536
|
}
|
|
1344
1537
|
}
|
|
@@ -1347,7 +1540,9 @@ class ManualInstrumentation {
|
|
|
1347
1540
|
return attributes;
|
|
1348
1541
|
}
|
|
1349
1542
|
attribifyConfiguration(direction, configuration) {
|
|
1350
|
-
const prefix = direction === 'input'
|
|
1543
|
+
const prefix = direction === 'input'
|
|
1544
|
+
? ATTRIBUTES.LATITUDE.request._root
|
|
1545
|
+
: ATTRIBUTES.LATITUDE.response._root;
|
|
1351
1546
|
const attributes = {};
|
|
1352
1547
|
for (const key in configuration) {
|
|
1353
1548
|
const field = this.toSnakeCase(key);
|
|
@@ -1358,7 +1553,7 @@ class ManualInstrumentation {
|
|
|
1358
1553
|
try {
|
|
1359
1554
|
value = JSON.stringify(value);
|
|
1360
1555
|
}
|
|
1361
|
-
catch (
|
|
1556
|
+
catch (_error) {
|
|
1362
1557
|
value = '{}';
|
|
1363
1558
|
}
|
|
1364
1559
|
}
|
|
@@ -1369,64 +1564,75 @@ class ManualInstrumentation {
|
|
|
1369
1564
|
completion(ctx, options) {
|
|
1370
1565
|
const start = options;
|
|
1371
1566
|
const configuration = {
|
|
1372
|
-
...start.configuration,
|
|
1567
|
+
...(start.configuration ?? {}),
|
|
1373
1568
|
model: start.model,
|
|
1374
1569
|
};
|
|
1375
1570
|
let jsonConfiguration = '';
|
|
1376
1571
|
try {
|
|
1377
1572
|
jsonConfiguration = JSON.stringify(configuration);
|
|
1378
1573
|
}
|
|
1379
|
-
catch (
|
|
1574
|
+
catch (_error) {
|
|
1380
1575
|
jsonConfiguration = '{}';
|
|
1381
1576
|
}
|
|
1382
1577
|
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1578
|
+
const input = start.input ?? [];
|
|
1383
1579
|
let jsonInput = '';
|
|
1384
1580
|
try {
|
|
1385
|
-
jsonInput = JSON.stringify(
|
|
1581
|
+
jsonInput = JSON.stringify(input);
|
|
1386
1582
|
}
|
|
1387
|
-
catch (
|
|
1583
|
+
catch (_error) {
|
|
1388
1584
|
jsonInput = '[]';
|
|
1389
1585
|
}
|
|
1390
|
-
const attrInput = this.attribifyMessages('input',
|
|
1586
|
+
const attrInput = this.attribifyMessages('input', input);
|
|
1391
1587
|
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1392
1588
|
attributes: {
|
|
1393
|
-
[
|
|
1394
|
-
[
|
|
1589
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
|
|
1590
|
+
[ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
|
|
1395
1591
|
...attrConfiguration,
|
|
1396
|
-
[
|
|
1592
|
+
[ATTRIBUTES.LATITUDE.request.messages]: jsonInput,
|
|
1397
1593
|
...attrInput,
|
|
1398
1594
|
...(start.attributes || {}),
|
|
1399
|
-
[
|
|
1400
|
-
[
|
|
1401
|
-
[
|
|
1595
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
|
|
1596
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
|
|
1597
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
|
|
1402
1598
|
},
|
|
1403
1599
|
});
|
|
1404
1600
|
return {
|
|
1405
1601
|
context: span.context,
|
|
1406
1602
|
end: (options) => {
|
|
1407
|
-
const end = options;
|
|
1603
|
+
const end = options ?? {};
|
|
1604
|
+
const output = end.output ?? [];
|
|
1408
1605
|
let jsonOutput = '';
|
|
1409
1606
|
try {
|
|
1410
|
-
jsonOutput = JSON.stringify(
|
|
1607
|
+
jsonOutput = JSON.stringify(output);
|
|
1411
1608
|
}
|
|
1412
|
-
catch (
|
|
1609
|
+
catch (_error) {
|
|
1413
1610
|
jsonOutput = '[]';
|
|
1414
1611
|
}
|
|
1415
|
-
const attrOutput = this.attribifyMessages('output',
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1612
|
+
const attrOutput = this.attribifyMessages('output', output);
|
|
1613
|
+
const tokens = {
|
|
1614
|
+
prompt: end.tokens?.prompt ?? 0,
|
|
1615
|
+
cached: end.tokens?.cached ?? 0,
|
|
1616
|
+
reasoning: end.tokens?.reasoning ?? 0,
|
|
1617
|
+
completion: end.tokens?.completion ?? 0,
|
|
1618
|
+
};
|
|
1619
|
+
const inputTokens = tokens.prompt + tokens.cached;
|
|
1620
|
+
const outputTokens = tokens.reasoning + tokens.completion;
|
|
1621
|
+
const finishReason = end.finishReason ?? '';
|
|
1418
1622
|
span.end({
|
|
1419
1623
|
attributes: {
|
|
1420
|
-
[
|
|
1624
|
+
[ATTRIBUTES.LATITUDE.response.messages]: jsonOutput,
|
|
1421
1625
|
...attrOutput,
|
|
1422
|
-
[
|
|
1423
|
-
[
|
|
1424
|
-
[
|
|
1425
|
-
[
|
|
1426
|
-
[
|
|
1427
|
-
[
|
|
1428
|
-
[
|
|
1429
|
-
[
|
|
1626
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
|
|
1627
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
|
|
1628
|
+
[ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
|
|
1629
|
+
[ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
|
|
1630
|
+
[ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
|
|
1631
|
+
[ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
|
|
1632
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
|
|
1633
|
+
[ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
|
|
1634
|
+
finishReason,
|
|
1635
|
+
],
|
|
1430
1636
|
...(end.attributes || {}),
|
|
1431
1637
|
},
|
|
1432
1638
|
});
|
|
@@ -1437,16 +1643,10 @@ class ManualInstrumentation {
|
|
|
1437
1643
|
embedding(ctx, options) {
|
|
1438
1644
|
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
|
|
1439
1645
|
}
|
|
1440
|
-
retrieval(ctx, options) {
|
|
1441
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Retrieval].name, SpanType.Retrieval, options);
|
|
1442
|
-
}
|
|
1443
|
-
reranking(ctx, options) {
|
|
1444
|
-
return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Reranking].name, SpanType.Reranking, options);
|
|
1445
|
-
}
|
|
1446
1646
|
attribifyHeaders(direction, headers) {
|
|
1447
1647
|
const prefix = direction === 'request'
|
|
1448
|
-
?
|
|
1449
|
-
:
|
|
1648
|
+
? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
|
|
1649
|
+
: ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
|
|
1450
1650
|
const attributes = {};
|
|
1451
1651
|
for (const key in headers) {
|
|
1452
1652
|
const field = this.toKebabCase(key);
|
|
@@ -1470,16 +1670,16 @@ class ManualInstrumentation {
|
|
|
1470
1670
|
try {
|
|
1471
1671
|
finalBody = JSON.stringify(start.request.body);
|
|
1472
1672
|
}
|
|
1473
|
-
catch (
|
|
1673
|
+
catch (_error) {
|
|
1474
1674
|
finalBody = '{}';
|
|
1475
1675
|
}
|
|
1476
1676
|
}
|
|
1477
1677
|
const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
|
|
1478
1678
|
attributes: {
|
|
1479
|
-
[
|
|
1480
|
-
[
|
|
1679
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
|
|
1680
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
|
|
1481
1681
|
...attrHeaders,
|
|
1482
|
-
[
|
|
1682
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
|
|
1483
1683
|
...(start.attributes || {}),
|
|
1484
1684
|
},
|
|
1485
1685
|
});
|
|
@@ -1497,15 +1697,15 @@ class ManualInstrumentation {
|
|
|
1497
1697
|
try {
|
|
1498
1698
|
finalBody = JSON.stringify(end.response.body);
|
|
1499
1699
|
}
|
|
1500
|
-
catch (
|
|
1700
|
+
catch (_error) {
|
|
1501
1701
|
finalBody = '{}';
|
|
1502
1702
|
}
|
|
1503
1703
|
}
|
|
1504
1704
|
span.end({
|
|
1505
1705
|
attributes: {
|
|
1506
|
-
[
|
|
1706
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
|
|
1507
1707
|
...attrHeaders,
|
|
1508
|
-
[
|
|
1708
|
+
[ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
|
|
1509
1709
|
...(end.attributes || {}),
|
|
1510
1710
|
},
|
|
1511
1711
|
});
|
|
@@ -1518,49 +1718,84 @@ class ManualInstrumentation {
|
|
|
1518
1718
|
try {
|
|
1519
1719
|
jsonParameters = JSON.stringify(parameters || {});
|
|
1520
1720
|
}
|
|
1521
|
-
catch (
|
|
1721
|
+
catch (_error) {
|
|
1522
1722
|
jsonParameters = '{}';
|
|
1523
1723
|
}
|
|
1524
1724
|
const attributes = {
|
|
1525
|
-
[
|
|
1526
|
-
[
|
|
1527
|
-
[
|
|
1528
|
-
[
|
|
1529
|
-
[
|
|
1530
|
-
|
|
1531
|
-
...(experimentUuid && {
|
|
1725
|
+
[ATTRIBUTES.LATITUDE.request.template]: template,
|
|
1726
|
+
[ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
|
|
1727
|
+
[ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
|
|
1728
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1729
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1730
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1731
|
+
...(experimentUuid && {
|
|
1732
|
+
[ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
|
|
1733
|
+
}),
|
|
1532
1734
|
...(testDeploymentId && {
|
|
1533
|
-
[
|
|
1735
|
+
[ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
|
|
1534
1736
|
}),
|
|
1535
|
-
...(externalId && { [
|
|
1536
|
-
...(source && { [
|
|
1737
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1738
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1537
1739
|
...(rest.attributes || {}),
|
|
1538
1740
|
};
|
|
1539
1741
|
return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
|
|
1540
1742
|
attributes,
|
|
1541
1743
|
});
|
|
1542
1744
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1745
|
+
chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
|
|
1746
|
+
const attributes = {
|
|
1747
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1748
|
+
[ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
|
|
1749
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1750
|
+
...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
|
|
1751
|
+
...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
|
|
1752
|
+
...(rest.attributes || {}),
|
|
1753
|
+
};
|
|
1754
|
+
return this.span(ctx, name || 'chat', SpanType.Chat, { attributes });
|
|
1755
|
+
}
|
|
1756
|
+
external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
|
|
1757
|
+
const attributes = {
|
|
1758
|
+
[ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
|
|
1759
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
|
|
1760
|
+
[ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
|
|
1761
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1762
|
+
...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
|
|
1763
|
+
...(rest.attributes || {}),
|
|
1764
|
+
};
|
|
1765
|
+
return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
|
|
1766
|
+
attributes,
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
|
|
1770
|
+
const attributes = {
|
|
1771
|
+
[ATTRIBUTES.LATITUDE.promptPath]: path,
|
|
1772
|
+
[ATTRIBUTES.LATITUDE.projectId]: projectId,
|
|
1773
|
+
...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
|
|
1774
|
+
...(conversationUuid && {
|
|
1775
|
+
[ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
|
|
1776
|
+
}),
|
|
1777
|
+
...(rest.attributes || {}),
|
|
1778
|
+
};
|
|
1779
|
+
return this.span(ctx, name || `capture-${path}`, SpanType.UnresolvedExternal, { attributes });
|
|
1545
1780
|
}
|
|
1546
1781
|
}
|
|
1547
1782
|
|
|
1548
1783
|
class LatitudeInstrumentation {
|
|
1549
1784
|
options;
|
|
1550
|
-
|
|
1785
|
+
manualTelemetry;
|
|
1551
1786
|
constructor(tracer, options) {
|
|
1552
|
-
this.
|
|
1787
|
+
this.manualTelemetry = new ManualInstrumentation(tracer);
|
|
1553
1788
|
this.options = options;
|
|
1554
1789
|
}
|
|
1555
1790
|
isEnabled() {
|
|
1556
|
-
return this.
|
|
1791
|
+
return this.manualTelemetry.isEnabled();
|
|
1557
1792
|
}
|
|
1558
1793
|
enable() {
|
|
1559
1794
|
this.options.module.instrument(this);
|
|
1560
|
-
this.
|
|
1795
|
+
this.manualTelemetry.enable();
|
|
1561
1796
|
}
|
|
1562
1797
|
disable() {
|
|
1563
|
-
this.
|
|
1798
|
+
this.manualTelemetry.disable();
|
|
1564
1799
|
this.options.module.uninstrument();
|
|
1565
1800
|
}
|
|
1566
1801
|
countTokens(messages) {
|
|
@@ -1584,7 +1819,8 @@ class LatitudeInstrumentation {
|
|
|
1584
1819
|
}
|
|
1585
1820
|
async wrapRenderChain(fn, ...args) {
|
|
1586
1821
|
const { prompt, parameters } = args[0];
|
|
1587
|
-
const $prompt = this.
|
|
1822
|
+
const $prompt = this.manualTelemetry.prompt(context.active(), {
|
|
1823
|
+
documentLogUuid: v4(),
|
|
1588
1824
|
versionUuid: prompt.versionUuid,
|
|
1589
1825
|
promptUuid: prompt.uuid,
|
|
1590
1826
|
template: prompt.content,
|
|
@@ -1601,26 +1837,13 @@ class LatitudeInstrumentation {
|
|
|
1601
1837
|
$prompt.end();
|
|
1602
1838
|
return result;
|
|
1603
1839
|
}
|
|
1604
|
-
async wrapRenderStep(fn, ...args) {
|
|
1605
|
-
const $step = this.telemetry.step(context.active());
|
|
1606
|
-
let result;
|
|
1607
|
-
try {
|
|
1608
|
-
result = await context.with($step.context, async () => await fn(...args));
|
|
1609
|
-
}
|
|
1610
|
-
catch (error) {
|
|
1611
|
-
$step.fail(error);
|
|
1612
|
-
throw error;
|
|
1613
|
-
}
|
|
1614
|
-
$step.end();
|
|
1615
|
-
return result;
|
|
1616
|
-
}
|
|
1617
1840
|
async wrapRenderCompletion(fn, ...args) {
|
|
1618
1841
|
if (!this.options.completions) {
|
|
1619
1842
|
return await fn(...args);
|
|
1620
1843
|
}
|
|
1621
1844
|
const { provider, config, messages } = args[0];
|
|
1622
1845
|
const model = config.model || 'unknown';
|
|
1623
|
-
const $completion = this.
|
|
1846
|
+
const $completion = this.manualTelemetry.completion(context.active(), {
|
|
1624
1847
|
name: `${provider} / ${model}`,
|
|
1625
1848
|
provider: provider,
|
|
1626
1849
|
model: model,
|
|
@@ -1647,14 +1870,14 @@ class LatitudeInstrumentation {
|
|
|
1647
1870
|
completion: completionTokens,
|
|
1648
1871
|
},
|
|
1649
1872
|
finishReason: result.toolRequests.length > 0
|
|
1650
|
-
?
|
|
1651
|
-
:
|
|
1873
|
+
? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
|
|
1874
|
+
: VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
|
|
1652
1875
|
});
|
|
1653
1876
|
return result;
|
|
1654
1877
|
}
|
|
1655
1878
|
async wrapRenderTool(fn, ...args) {
|
|
1656
1879
|
const { toolRequest } = args[0];
|
|
1657
|
-
const $tool = this.
|
|
1880
|
+
const $tool = this.manualTelemetry.tool(context.active(), {
|
|
1658
1881
|
name: toolRequest.toolName,
|
|
1659
1882
|
call: {
|
|
1660
1883
|
id: toolRequest.toolCallId,
|
|
@@ -1679,10 +1902,157 @@ class LatitudeInstrumentation {
|
|
|
1679
1902
|
}
|
|
1680
1903
|
}
|
|
1681
1904
|
|
|
1905
|
+
var LatitudeErrorCodes;
|
|
1906
|
+
(function (LatitudeErrorCodes) {
|
|
1907
|
+
LatitudeErrorCodes["UnexpectedError"] = "UnexpectedError";
|
|
1908
|
+
LatitudeErrorCodes["OverloadedError"] = "OverloadedError";
|
|
1909
|
+
LatitudeErrorCodes["RateLimitError"] = "RateLimitError";
|
|
1910
|
+
LatitudeErrorCodes["UnauthorizedError"] = "UnauthorizedError";
|
|
1911
|
+
LatitudeErrorCodes["ForbiddenError"] = "ForbiddenError";
|
|
1912
|
+
LatitudeErrorCodes["BadRequestError"] = "BadRequestError";
|
|
1913
|
+
LatitudeErrorCodes["NotFoundError"] = "NotFoundError";
|
|
1914
|
+
LatitudeErrorCodes["ConflictError"] = "ConflictError";
|
|
1915
|
+
LatitudeErrorCodes["UnprocessableEntityError"] = "UnprocessableEntityError";
|
|
1916
|
+
LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
|
|
1917
|
+
LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
|
|
1918
|
+
LatitudeErrorCodes["AbortedError"] = "AbortedError";
|
|
1919
|
+
LatitudeErrorCodes["BillingError"] = "BillingError";
|
|
1920
|
+
})(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
|
|
1921
|
+
// NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
|
|
1922
|
+
var RunErrorCodes;
|
|
1923
|
+
(function (RunErrorCodes) {
|
|
1924
|
+
RunErrorCodes["AIProviderConfigError"] = "ai_provider_config_error";
|
|
1925
|
+
RunErrorCodes["AIRunError"] = "ai_run_error";
|
|
1926
|
+
RunErrorCodes["ChainCompileError"] = "chain_compile_error";
|
|
1927
|
+
RunErrorCodes["DefaultProviderExceededQuota"] = "default_provider_exceeded_quota_error";
|
|
1928
|
+
RunErrorCodes["DefaultProviderInvalidModel"] = "default_provider_invalid_model_error";
|
|
1929
|
+
RunErrorCodes["DocumentConfigError"] = "document_config_error";
|
|
1930
|
+
RunErrorCodes["ErrorGeneratingMockToolResult"] = "error_generating_mock_tool_result";
|
|
1931
|
+
RunErrorCodes["FailedToWakeUpIntegrationError"] = "failed_to_wake_up_integration_error";
|
|
1932
|
+
RunErrorCodes["InvalidResponseFormatError"] = "invalid_response_format_error";
|
|
1933
|
+
RunErrorCodes["MaxStepCountExceededError"] = "max_step_count_exceeded_error";
|
|
1934
|
+
RunErrorCodes["MissingProvider"] = "missing_provider_error";
|
|
1935
|
+
RunErrorCodes["RateLimit"] = "rate_limit_error";
|
|
1936
|
+
RunErrorCodes["Unknown"] = "unknown_error";
|
|
1937
|
+
RunErrorCodes["UnsupportedProviderResponseTypeError"] = "unsupported_provider_response_type_error";
|
|
1938
|
+
RunErrorCodes["PaymentRequiredError"] = "payment_required_error";
|
|
1939
|
+
RunErrorCodes["AbortError"] = "abort_error";
|
|
1940
|
+
// DEPRECATED, but do not delete
|
|
1941
|
+
RunErrorCodes["EvaluationRunMissingProviderLogError"] = "ev_run_missing_provider_log_error";
|
|
1942
|
+
RunErrorCodes["EvaluationRunMissingWorkspaceError"] = "ev_run_missing_workspace_error";
|
|
1943
|
+
RunErrorCodes["EvaluationRunResponseJsonFormatError"] = "ev_run_response_json_format_error";
|
|
1944
|
+
RunErrorCodes["EvaluationRunUnsupportedResultTypeError"] = "ev_run_unsupported_result_type_error";
|
|
1945
|
+
})(RunErrorCodes || (RunErrorCodes = {}));
|
|
1946
|
+
var ApiErrorCodes;
|
|
1947
|
+
(function (ApiErrorCodes) {
|
|
1948
|
+
ApiErrorCodes["HTTPException"] = "http_exception";
|
|
1949
|
+
ApiErrorCodes["InternalServerError"] = "internal_server_error";
|
|
1950
|
+
})(ApiErrorCodes || (ApiErrorCodes = {}));
|
|
1951
|
+
|
|
1952
|
+
class LatitudeError extends Error {
|
|
1953
|
+
statusCode = 500;
|
|
1954
|
+
name = LatitudeErrorCodes.UnexpectedError;
|
|
1955
|
+
headers = {};
|
|
1956
|
+
details;
|
|
1957
|
+
constructor(message, details, status, name) {
|
|
1958
|
+
super(message);
|
|
1959
|
+
this.details = details ?? {};
|
|
1960
|
+
this.statusCode = status ?? this.statusCode;
|
|
1961
|
+
this.name = name ?? this.constructor.name;
|
|
1962
|
+
}
|
|
1963
|
+
serialize() {
|
|
1964
|
+
return {
|
|
1965
|
+
name: this.name,
|
|
1966
|
+
code: this.name,
|
|
1967
|
+
status: this.statusCode,
|
|
1968
|
+
message: this.message,
|
|
1969
|
+
details: this.details,
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
static deserialize(json) {
|
|
1973
|
+
return new LatitudeError(json.message, json.details, json.status, json.name);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
class BadRequestError extends LatitudeError {
|
|
1977
|
+
statusCode = 400;
|
|
1978
|
+
name = LatitudeErrorCodes.BadRequestError;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1682
1981
|
const TRACES_URL = `${env.GATEWAY_BASE_URL}/api/v3/traces`;
|
|
1683
1982
|
const SERVICE_NAME = process.env.npm_package_name || 'unknown';
|
|
1684
1983
|
const SCOPE_VERSION = process.env.npm_package_version || 'unknown';
|
|
1685
1984
|
const BACKGROUND = () => otel.ROOT_CONTEXT;
|
|
1985
|
+
class SpanFactory {
|
|
1986
|
+
telemetry;
|
|
1987
|
+
constructor(telemetry) {
|
|
1988
|
+
this.telemetry = telemetry;
|
|
1989
|
+
}
|
|
1990
|
+
tool(options, ctx) {
|
|
1991
|
+
return this.telemetry.tool(ctx ?? context.active(), options);
|
|
1992
|
+
}
|
|
1993
|
+
completion(options, ctx) {
|
|
1994
|
+
return this.telemetry.completion(ctx ?? context.active(), options);
|
|
1995
|
+
}
|
|
1996
|
+
embedding(options, ctx) {
|
|
1997
|
+
return this.telemetry.embedding(ctx ?? context.active(), options);
|
|
1998
|
+
}
|
|
1999
|
+
http(options, ctx) {
|
|
2000
|
+
return this.telemetry.http(ctx ?? context.active(), options);
|
|
2001
|
+
}
|
|
2002
|
+
prompt(options, ctx) {
|
|
2003
|
+
return this.telemetry.prompt(ctx ?? context.active(), options);
|
|
2004
|
+
}
|
|
2005
|
+
chat(options, ctx) {
|
|
2006
|
+
return this.telemetry.chat(ctx ?? context.active(), options);
|
|
2007
|
+
}
|
|
2008
|
+
external(options, ctx) {
|
|
2009
|
+
return this.telemetry.external(ctx ?? context.active(), options);
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
class ContextManager {
|
|
2013
|
+
telemetry;
|
|
2014
|
+
constructor(telemetry) {
|
|
2015
|
+
this.telemetry = telemetry;
|
|
2016
|
+
}
|
|
2017
|
+
resume(ctx) {
|
|
2018
|
+
return this.telemetry.resume(ctx);
|
|
2019
|
+
}
|
|
2020
|
+
active() {
|
|
2021
|
+
return context.active();
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
class InstrumentationManager {
|
|
2025
|
+
instrumentations;
|
|
2026
|
+
constructor(instrumentations) {
|
|
2027
|
+
this.instrumentations = instrumentations;
|
|
2028
|
+
}
|
|
2029
|
+
enable() {
|
|
2030
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
2031
|
+
if (!instrumentation.isEnabled())
|
|
2032
|
+
instrumentation.enable();
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
disable() {
|
|
2036
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
2037
|
+
if (instrumentation.isEnabled())
|
|
2038
|
+
instrumentation.disable();
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
class TracerManager {
|
|
2043
|
+
nodeProvider;
|
|
2044
|
+
scopeVersion;
|
|
2045
|
+
constructor(nodeProvider, scopeVersion) {
|
|
2046
|
+
this.nodeProvider = nodeProvider;
|
|
2047
|
+
this.scopeVersion = scopeVersion;
|
|
2048
|
+
}
|
|
2049
|
+
get(scope) {
|
|
2050
|
+
return this.provider(scope).getTracer('');
|
|
2051
|
+
}
|
|
2052
|
+
provider(scope) {
|
|
2053
|
+
return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
1686
2056
|
class ScopedTracerProvider {
|
|
1687
2057
|
scope;
|
|
1688
2058
|
version;
|
|
@@ -1720,9 +2090,13 @@ var Instrumentation;
|
|
|
1720
2090
|
})(Instrumentation || (Instrumentation = {}));
|
|
1721
2091
|
class LatitudeTelemetry {
|
|
1722
2092
|
options;
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
2093
|
+
nodeProvider;
|
|
2094
|
+
manualInstrumentation;
|
|
2095
|
+
instrumentationsList;
|
|
2096
|
+
span;
|
|
2097
|
+
context;
|
|
2098
|
+
instrumentation;
|
|
2099
|
+
tracer;
|
|
1726
2100
|
constructor(apiKey, options) {
|
|
1727
2101
|
this.options = options || {};
|
|
1728
2102
|
if (!this.options.exporter) {
|
|
@@ -1736,63 +2110,61 @@ class LatitudeTelemetry {
|
|
|
1736
2110
|
new W3CBaggagePropagator(),
|
|
1737
2111
|
],
|
|
1738
2112
|
}));
|
|
1739
|
-
this.
|
|
2113
|
+
this.nodeProvider = new NodeTracerProvider({
|
|
1740
2114
|
resource: new Resource({ [ATTR_SERVICE_NAME]: SERVICE_NAME }),
|
|
1741
2115
|
});
|
|
1742
2116
|
// Note: important, must run before the exporter span processors
|
|
1743
|
-
this.
|
|
2117
|
+
this.nodeProvider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
|
|
1744
2118
|
if (this.options.processors) {
|
|
1745
2119
|
this.options.processors.forEach((processor) => {
|
|
1746
|
-
this.
|
|
2120
|
+
this.nodeProvider.addSpanProcessor(processor);
|
|
1747
2121
|
});
|
|
1748
2122
|
}
|
|
1749
2123
|
else {
|
|
1750
|
-
this.
|
|
2124
|
+
this.nodeProvider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
|
|
1751
2125
|
}
|
|
1752
2126
|
if (this.options.disableBatch) {
|
|
1753
|
-
this.
|
|
2127
|
+
this.nodeProvider.addSpanProcessor(new SimpleSpanProcessor(this.options.exporter));
|
|
1754
2128
|
}
|
|
1755
2129
|
else {
|
|
1756
|
-
this.
|
|
2130
|
+
this.nodeProvider.addSpanProcessor(new BatchSpanProcessor(this.options.exporter));
|
|
1757
2131
|
}
|
|
1758
|
-
this.
|
|
2132
|
+
this.nodeProvider.register();
|
|
1759
2133
|
process.on('SIGTERM', async () => this.shutdown);
|
|
1760
2134
|
process.on('SIGINT', async () => this.shutdown);
|
|
1761
|
-
this.
|
|
1762
|
-
this.
|
|
2135
|
+
this.manualInstrumentation = null;
|
|
2136
|
+
this.instrumentationsList = [];
|
|
2137
|
+
this.tracer = new TracerManager(this.nodeProvider, SCOPE_VERSION);
|
|
1763
2138
|
this.initInstrumentations();
|
|
1764
|
-
this.
|
|
2139
|
+
this.instrumentation = new InstrumentationManager(this.instrumentationsList);
|
|
2140
|
+
this.instrumentation.enable();
|
|
2141
|
+
this.span = new SpanFactory(this.manualInstrumentation);
|
|
2142
|
+
this.context = new ContextManager(this.manualInstrumentation);
|
|
1765
2143
|
}
|
|
1766
2144
|
async flush() {
|
|
1767
|
-
await this.
|
|
2145
|
+
await this.nodeProvider.forceFlush();
|
|
1768
2146
|
await this.options.exporter.forceFlush?.();
|
|
1769
2147
|
}
|
|
1770
2148
|
async shutdown() {
|
|
1771
2149
|
await this.flush();
|
|
1772
|
-
await this.
|
|
2150
|
+
await this.nodeProvider.shutdown();
|
|
1773
2151
|
await this.options.exporter.shutdown?.();
|
|
1774
2152
|
}
|
|
1775
|
-
tracerProvider(instrumentation) {
|
|
1776
|
-
return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${instrumentation}`, SCOPE_VERSION, this.provider);
|
|
1777
|
-
}
|
|
1778
|
-
tracer(instrumentation) {
|
|
1779
|
-
return this.tracerProvider(instrumentation).getTracer('');
|
|
1780
|
-
}
|
|
1781
2153
|
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
1782
2154
|
initInstrumentations() {
|
|
1783
|
-
this.
|
|
1784
|
-
const tracer = this.tracer(InstrumentationScope.Manual);
|
|
1785
|
-
this.
|
|
1786
|
-
this.
|
|
2155
|
+
this.instrumentationsList = [];
|
|
2156
|
+
const tracer = this.tracer.get(InstrumentationScope.Manual);
|
|
2157
|
+
this.manualInstrumentation = new ManualInstrumentation(tracer);
|
|
2158
|
+
this.instrumentationsList.push(this.manualInstrumentation);
|
|
1787
2159
|
const latitude = this.options.instrumentations?.latitude;
|
|
1788
2160
|
if (latitude) {
|
|
1789
|
-
const tracer = this.tracer(Instrumentation.Latitude);
|
|
2161
|
+
const tracer = this.tracer.get(Instrumentation.Latitude);
|
|
1790
2162
|
const instrumentation = new LatitudeInstrumentation(tracer, typeof latitude === 'object' ? latitude : { module: latitude });
|
|
1791
|
-
this.
|
|
2163
|
+
this.instrumentationsList.push(instrumentation);
|
|
1792
2164
|
}
|
|
1793
2165
|
const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
|
|
1794
2166
|
const providerPkg = this.options.instrumentations?.[instrumentationType];
|
|
1795
|
-
const provider = this.
|
|
2167
|
+
const provider = this.tracer.provider(instrumentationType);
|
|
1796
2168
|
const instrumentation = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
|
|
1797
2169
|
instrumentation.setTracerProvider(provider);
|
|
1798
2170
|
if (providerPkg) {
|
|
@@ -1802,7 +2174,7 @@ class LatitudeTelemetry {
|
|
|
1802
2174
|
instrumentations: [instrumentation],
|
|
1803
2175
|
tracerProvider: provider,
|
|
1804
2176
|
});
|
|
1805
|
-
this.
|
|
2177
|
+
this.instrumentationsList.push(instrumentation);
|
|
1806
2178
|
};
|
|
1807
2179
|
configureInstrumentation(Instrumentation.Anthropic, AnthropicInstrumentation); // prettier-ignore
|
|
1808
2180
|
configureInstrumentation(Instrumentation.AIPlatform, AIPlatformInstrumentation); // prettier-ignore
|
|
@@ -1810,48 +2182,28 @@ class LatitudeTelemetry {
|
|
|
1810
2182
|
configureInstrumentation(Instrumentation.Cohere, CohereInstrumentation); // prettier-ignore
|
|
1811
2183
|
configureInstrumentation(Instrumentation.Langchain, LangChainInstrumentation); // prettier-ignore
|
|
1812
2184
|
configureInstrumentation(Instrumentation.LlamaIndex, LlamaIndexInstrumentation); // prettier-ignore
|
|
1813
|
-
|
|
1814
|
-
configureInstrumentation(Instrumentation.
|
|
2185
|
+
// NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
|
|
2186
|
+
configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
2187
|
+
configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
|
|
1815
2188
|
configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
|
|
1816
2189
|
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
}
|
|
1835
|
-
completion(ctx, options) {
|
|
1836
|
-
return this.telemetry.completion(ctx, options);
|
|
1837
|
-
}
|
|
1838
|
-
embedding(ctx, options) {
|
|
1839
|
-
return this.telemetry.embedding(ctx, options);
|
|
1840
|
-
}
|
|
1841
|
-
retrieval(ctx, options) {
|
|
1842
|
-
return this.telemetry.retrieval(ctx, options);
|
|
1843
|
-
}
|
|
1844
|
-
reranking(ctx, options) {
|
|
1845
|
-
return this.telemetry.reranking(ctx, options);
|
|
1846
|
-
}
|
|
1847
|
-
http(ctx, options) {
|
|
1848
|
-
return this.telemetry.http(ctx, options);
|
|
1849
|
-
}
|
|
1850
|
-
prompt(ctx, options) {
|
|
1851
|
-
return this.telemetry.prompt(ctx, options);
|
|
1852
|
-
}
|
|
1853
|
-
step(ctx, options) {
|
|
1854
|
-
return this.telemetry.step(ctx, options);
|
|
2190
|
+
async capture(options, fn) {
|
|
2191
|
+
if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
|
|
2192
|
+
throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
|
|
2193
|
+
}
|
|
2194
|
+
const span = this.manualInstrumentation.unresolvedExternal(otel.ROOT_CONTEXT, options);
|
|
2195
|
+
try {
|
|
2196
|
+
const result = await context.with(span.context, () => fn(span.context));
|
|
2197
|
+
span.end();
|
|
2198
|
+
return result;
|
|
2199
|
+
}
|
|
2200
|
+
catch (error) {
|
|
2201
|
+
span.fail(error);
|
|
2202
|
+
throw error;
|
|
2203
|
+
}
|
|
2204
|
+
finally {
|
|
2205
|
+
await this.flush();
|
|
2206
|
+
}
|
|
1855
2207
|
}
|
|
1856
2208
|
}
|
|
1857
2209
|
|