@latitude-data/telemetry 1.0.4 → 1.1.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 +343 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +194 -62
- package/dist/index.js +344 -103
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import * as otel from '@opentelemetry/api';
|
|
3
|
-
import {
|
|
3
|
+
import { trace, propagation, context } from '@opentelemetry/api';
|
|
4
4
|
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
5
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 { 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,
|
|
@@ -188,6 +189,7 @@ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
|
188
189
|
evaluationUuids: z.array(z.string()),
|
|
189
190
|
minThreshold: z.number().optional(), // Threshold percentage
|
|
190
191
|
maxThreshold: z.number().optional(), // Threshold percentage
|
|
192
|
+
defaultTarget: z.boolean().optional(), // Default for optimizations and distillations
|
|
191
193
|
});
|
|
192
194
|
const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
193
195
|
results: z.record(z.string(), // Evaluation uuid
|
|
@@ -255,7 +257,7 @@ const CompositeEvaluationSpecification = {
|
|
|
255
257
|
};
|
|
256
258
|
|
|
257
259
|
const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
|
|
258
|
-
enableControls: z.boolean().optional(),
|
|
260
|
+
enableControls: z.boolean().optional(), // UI annotation controls
|
|
259
261
|
criteria: z.string().optional(),
|
|
260
262
|
});
|
|
261
263
|
const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
|
|
@@ -783,6 +785,9 @@ var SpanType;
|
|
|
783
785
|
SpanType["Http"] = "http";
|
|
784
786
|
SpanType["Unknown"] = "unknown";
|
|
785
787
|
SpanType["Prompt"] = "prompt";
|
|
788
|
+
SpanType["Chat"] = "chat";
|
|
789
|
+
SpanType["External"] = "external";
|
|
790
|
+
SpanType["UnresolvedExternal"] = "unresolved_external";
|
|
786
791
|
SpanType["Step"] = "step";
|
|
787
792
|
})(SpanType || (SpanType = {}));
|
|
788
793
|
const SPAN_SPECIFICATIONS = {
|
|
@@ -834,6 +839,24 @@ const SPAN_SPECIFICATIONS = {
|
|
|
834
839
|
isGenAI: false,
|
|
835
840
|
isHidden: false,
|
|
836
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
|
+
},
|
|
837
860
|
[SpanType.Step]: {
|
|
838
861
|
name: 'Step',
|
|
839
862
|
description: 'A step span',
|
|
@@ -887,7 +910,16 @@ var InstrumentationScope;
|
|
|
887
910
|
/* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
|
|
888
911
|
const ATTR_LATITUDE = 'latitude';
|
|
889
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`;
|
|
890
921
|
const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
|
|
922
|
+
const ATTR_LATITUDE_PREVIOUS_TRACE_ID = `${ATTR_LATITUDE}.previous_trace_id`;
|
|
891
923
|
const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
|
|
892
924
|
const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
|
|
893
925
|
const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
|
|
@@ -1044,6 +1076,7 @@ var DocumentTriggerParameters;
|
|
|
1044
1076
|
DocumentTriggerParameters["Body"] = "body";
|
|
1045
1077
|
DocumentTriggerParameters["Attachments"] = "attachments";
|
|
1046
1078
|
})(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
|
|
1079
|
+
const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
|
|
1047
1080
|
|
|
1048
1081
|
class ManualInstrumentation {
|
|
1049
1082
|
enabled;
|
|
@@ -1062,7 +1095,33 @@ class ManualInstrumentation {
|
|
|
1062
1095
|
this.enabled = false;
|
|
1063
1096
|
}
|
|
1064
1097
|
resume(ctx) {
|
|
1065
|
-
|
|
1098
|
+
const parts = ctx.traceparent.split('-');
|
|
1099
|
+
if (parts.length !== 4) {
|
|
1100
|
+
return otel.ROOT_CONTEXT;
|
|
1101
|
+
}
|
|
1102
|
+
const [, traceId, spanId, flags] = parts;
|
|
1103
|
+
if (!traceId || !spanId) {
|
|
1104
|
+
return otel.ROOT_CONTEXT;
|
|
1105
|
+
}
|
|
1106
|
+
const spanContext = {
|
|
1107
|
+
traceId,
|
|
1108
|
+
spanId,
|
|
1109
|
+
traceFlags: parseInt(flags ?? '01', 16),
|
|
1110
|
+
isRemote: true,
|
|
1111
|
+
};
|
|
1112
|
+
let context = trace.setSpanContext(otel.ROOT_CONTEXT, spanContext);
|
|
1113
|
+
if (ctx.baggage) {
|
|
1114
|
+
const baggageEntries = {};
|
|
1115
|
+
for (const pair of ctx.baggage.split(',')) {
|
|
1116
|
+
const [key, value] = pair.split('=');
|
|
1117
|
+
if (key && value) {
|
|
1118
|
+
baggageEntries[key] = { value: decodeURIComponent(value) };
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
const baggage = propagation.createBaggage(baggageEntries);
|
|
1122
|
+
context = propagation.setBaggage(context, baggage);
|
|
1123
|
+
}
|
|
1124
|
+
return context;
|
|
1066
1125
|
}
|
|
1067
1126
|
capitalize(str) {
|
|
1068
1127
|
if (str.length === 0)
|
|
@@ -1369,7 +1428,7 @@ class ManualInstrumentation {
|
|
|
1369
1428
|
completion(ctx, options) {
|
|
1370
1429
|
const start = options;
|
|
1371
1430
|
const configuration = {
|
|
1372
|
-
...start.configuration,
|
|
1431
|
+
...(start.configuration ?? {}),
|
|
1373
1432
|
model: start.model,
|
|
1374
1433
|
};
|
|
1375
1434
|
let jsonConfiguration = '';
|
|
@@ -1380,14 +1439,15 @@ class ManualInstrumentation {
|
|
|
1380
1439
|
jsonConfiguration = '{}';
|
|
1381
1440
|
}
|
|
1382
1441
|
const attrConfiguration = this.attribifyConfiguration('input', configuration);
|
|
1442
|
+
const input = start.input ?? [];
|
|
1383
1443
|
let jsonInput = '';
|
|
1384
1444
|
try {
|
|
1385
|
-
jsonInput = JSON.stringify(
|
|
1445
|
+
jsonInput = JSON.stringify(input);
|
|
1386
1446
|
}
|
|
1387
1447
|
catch (error) {
|
|
1388
1448
|
jsonInput = '[]';
|
|
1389
1449
|
}
|
|
1390
|
-
const attrInput = this.attribifyMessages('input',
|
|
1450
|
+
const attrInput = this.attribifyMessages('input', input);
|
|
1391
1451
|
const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
|
|
1392
1452
|
attributes: {
|
|
1393
1453
|
[ATTR_GEN_AI_SYSTEM]: start.provider,
|
|
@@ -1396,37 +1456,45 @@ class ManualInstrumentation {
|
|
|
1396
1456
|
[ATTR_GEN_AI_REQUEST_MESSAGES]: jsonInput,
|
|
1397
1457
|
...attrInput,
|
|
1398
1458
|
...(start.attributes || {}),
|
|
1399
|
-
[
|
|
1400
|
-
[
|
|
1401
|
-
[
|
|
1459
|
+
[ATTR_LATITUDE_COMMIT_UUID]: start.versionUuid,
|
|
1460
|
+
[ATTR_LATITUDE_DOCUMENT_UUID]: start.promptUuid,
|
|
1461
|
+
[ATTR_LATITUDE_EXPERIMENT_UUID]: start.experimentUuid,
|
|
1402
1462
|
},
|
|
1403
1463
|
});
|
|
1404
1464
|
return {
|
|
1405
1465
|
context: span.context,
|
|
1406
1466
|
end: (options) => {
|
|
1407
|
-
const end = options;
|
|
1467
|
+
const end = options ?? {};
|
|
1468
|
+
const output = end.output ?? [];
|
|
1408
1469
|
let jsonOutput = '';
|
|
1409
1470
|
try {
|
|
1410
|
-
jsonOutput = JSON.stringify(
|
|
1471
|
+
jsonOutput = JSON.stringify(output);
|
|
1411
1472
|
}
|
|
1412
1473
|
catch (error) {
|
|
1413
1474
|
jsonOutput = '[]';
|
|
1414
1475
|
}
|
|
1415
|
-
const attrOutput = this.attribifyMessages('output',
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1476
|
+
const attrOutput = this.attribifyMessages('output', output);
|
|
1477
|
+
const tokens = {
|
|
1478
|
+
prompt: end.tokens?.prompt ?? 0,
|
|
1479
|
+
cached: end.tokens?.cached ?? 0,
|
|
1480
|
+
reasoning: end.tokens?.reasoning ?? 0,
|
|
1481
|
+
completion: end.tokens?.completion ?? 0,
|
|
1482
|
+
};
|
|
1483
|
+
const inputTokens = tokens.prompt + tokens.cached;
|
|
1484
|
+
const outputTokens = tokens.reasoning + tokens.completion;
|
|
1485
|
+
const finishReason = end.finishReason ?? '';
|
|
1418
1486
|
span.end({
|
|
1419
1487
|
attributes: {
|
|
1420
1488
|
[ATTR_GEN_AI_RESPONSE_MESSAGES]: jsonOutput,
|
|
1421
1489
|
...attrOutput,
|
|
1422
1490
|
[ATTR_GEN_AI_USAGE_INPUT_TOKENS]: inputTokens,
|
|
1423
|
-
[ATTR_GEN_AI_USAGE_PROMPT_TOKENS]:
|
|
1424
|
-
[ATTR_GEN_AI_USAGE_CACHED_TOKENS]:
|
|
1425
|
-
[ATTR_GEN_AI_USAGE_REASONING_TOKENS]:
|
|
1426
|
-
[ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]:
|
|
1491
|
+
[ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: tokens.prompt,
|
|
1492
|
+
[ATTR_GEN_AI_USAGE_CACHED_TOKENS]: tokens.cached,
|
|
1493
|
+
[ATTR_GEN_AI_USAGE_REASONING_TOKENS]: tokens.reasoning,
|
|
1494
|
+
[ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: tokens.completion,
|
|
1427
1495
|
[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: outputTokens,
|
|
1428
1496
|
[ATTR_GEN_AI_RESPONSE_MODEL]: start.model,
|
|
1429
|
-
[ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
1497
|
+
[ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [finishReason],
|
|
1430
1498
|
...(end.attributes || {}),
|
|
1431
1499
|
},
|
|
1432
1500
|
});
|
|
@@ -1524,16 +1592,18 @@ class ManualInstrumentation {
|
|
|
1524
1592
|
const attributes = {
|
|
1525
1593
|
[ATTR_GEN_AI_REQUEST_TEMPLATE]: template,
|
|
1526
1594
|
[ATTR_GEN_AI_REQUEST_PARAMETERS]: jsonParameters,
|
|
1527
|
-
[
|
|
1528
|
-
[
|
|
1529
|
-
[
|
|
1530
|
-
|
|
1531
|
-
...(experimentUuid && {
|
|
1595
|
+
[ATTR_LATITUDE_COMMIT_UUID]: versionUuid || HEAD_COMMIT,
|
|
1596
|
+
[ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
|
|
1597
|
+
[ATTR_LATITUDE_PROJECT_ID]: projectId,
|
|
1598
|
+
[ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
|
|
1599
|
+
...(experimentUuid && {
|
|
1600
|
+
[ATTR_LATITUDE_EXPERIMENT_UUID]: experimentUuid,
|
|
1601
|
+
}),
|
|
1532
1602
|
...(testDeploymentId && {
|
|
1533
1603
|
[ATTR_LATITUDE_TEST_DEPLOYMENT_ID]: testDeploymentId,
|
|
1534
1604
|
}),
|
|
1535
|
-
...(externalId && { [
|
|
1536
|
-
...(source && { [
|
|
1605
|
+
...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
|
|
1606
|
+
...(source && { [ATTR_LATITUDE_SOURCE]: source }),
|
|
1537
1607
|
...(rest.attributes || {}),
|
|
1538
1608
|
};
|
|
1539
1609
|
return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
|
|
@@ -1543,24 +1613,58 @@ class ManualInstrumentation {
|
|
|
1543
1613
|
step(ctx, options) {
|
|
1544
1614
|
return this.span(ctx, 'step', SpanType.Step, options);
|
|
1545
1615
|
}
|
|
1616
|
+
chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
|
|
1617
|
+
const attributes = {
|
|
1618
|
+
[ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
|
|
1619
|
+
[ATTR_LATITUDE_PREVIOUS_TRACE_ID]: previousTraceId,
|
|
1620
|
+
...(source && { [ATTR_LATITUDE_SOURCE]: source }),
|
|
1621
|
+
...(rest.attributes || {}),
|
|
1622
|
+
};
|
|
1623
|
+
return this.span(ctx, name || 'chat', SpanType.Chat, { attributes });
|
|
1624
|
+
}
|
|
1625
|
+
external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
|
|
1626
|
+
const attributes = {
|
|
1627
|
+
[ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
|
|
1628
|
+
[ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
|
|
1629
|
+
[ATTR_LATITUDE_SOURCE]: source ?? LogSources.API,
|
|
1630
|
+
...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
|
|
1631
|
+
...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
|
|
1632
|
+
...(rest.attributes || {}),
|
|
1633
|
+
};
|
|
1634
|
+
return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
|
|
1635
|
+
attributes,
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
|
|
1639
|
+
const attributes = {
|
|
1640
|
+
[ATTR_LATITUDE_PROMPT_PATH]: path,
|
|
1641
|
+
[ATTR_LATITUDE_PROJECT_ID]: projectId,
|
|
1642
|
+
...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
|
|
1643
|
+
...(conversationUuid && {
|
|
1644
|
+
[ATTR_LATITUDE_DOCUMENT_LOG_UUID]: conversationUuid,
|
|
1645
|
+
}),
|
|
1646
|
+
...(rest.attributes || {}),
|
|
1647
|
+
};
|
|
1648
|
+
return this.span(ctx, name || `capture-${path}`, SpanType.UnresolvedExternal, { attributes });
|
|
1649
|
+
}
|
|
1546
1650
|
}
|
|
1547
1651
|
|
|
1548
1652
|
class LatitudeInstrumentation {
|
|
1549
1653
|
options;
|
|
1550
|
-
|
|
1654
|
+
manualTelemetry;
|
|
1551
1655
|
constructor(tracer, options) {
|
|
1552
|
-
this.
|
|
1656
|
+
this.manualTelemetry = new ManualInstrumentation(tracer);
|
|
1553
1657
|
this.options = options;
|
|
1554
1658
|
}
|
|
1555
1659
|
isEnabled() {
|
|
1556
|
-
return this.
|
|
1660
|
+
return this.manualTelemetry.isEnabled();
|
|
1557
1661
|
}
|
|
1558
1662
|
enable() {
|
|
1559
1663
|
this.options.module.instrument(this);
|
|
1560
|
-
this.
|
|
1664
|
+
this.manualTelemetry.enable();
|
|
1561
1665
|
}
|
|
1562
1666
|
disable() {
|
|
1563
|
-
this.
|
|
1667
|
+
this.manualTelemetry.disable();
|
|
1564
1668
|
this.options.module.uninstrument();
|
|
1565
1669
|
}
|
|
1566
1670
|
countTokens(messages) {
|
|
@@ -1584,7 +1688,8 @@ class LatitudeInstrumentation {
|
|
|
1584
1688
|
}
|
|
1585
1689
|
async wrapRenderChain(fn, ...args) {
|
|
1586
1690
|
const { prompt, parameters } = args[0];
|
|
1587
|
-
const $prompt = this.
|
|
1691
|
+
const $prompt = this.manualTelemetry.prompt(context.active(), {
|
|
1692
|
+
documentLogUuid: v4(),
|
|
1588
1693
|
versionUuid: prompt.versionUuid,
|
|
1589
1694
|
promptUuid: prompt.uuid,
|
|
1590
1695
|
template: prompt.content,
|
|
@@ -1602,7 +1707,7 @@ class LatitudeInstrumentation {
|
|
|
1602
1707
|
return result;
|
|
1603
1708
|
}
|
|
1604
1709
|
async wrapRenderStep(fn, ...args) {
|
|
1605
|
-
const $step = this.
|
|
1710
|
+
const $step = this.manualTelemetry.step(context.active());
|
|
1606
1711
|
let result;
|
|
1607
1712
|
try {
|
|
1608
1713
|
result = await context.with($step.context, async () => await fn(...args));
|
|
@@ -1620,7 +1725,7 @@ class LatitudeInstrumentation {
|
|
|
1620
1725
|
}
|
|
1621
1726
|
const { provider, config, messages } = args[0];
|
|
1622
1727
|
const model = config.model || 'unknown';
|
|
1623
|
-
const $completion = this.
|
|
1728
|
+
const $completion = this.manualTelemetry.completion(context.active(), {
|
|
1624
1729
|
name: `${provider} / ${model}`,
|
|
1625
1730
|
provider: provider,
|
|
1626
1731
|
model: model,
|
|
@@ -1654,7 +1759,7 @@ class LatitudeInstrumentation {
|
|
|
1654
1759
|
}
|
|
1655
1760
|
async wrapRenderTool(fn, ...args) {
|
|
1656
1761
|
const { toolRequest } = args[0];
|
|
1657
|
-
const $tool = this.
|
|
1762
|
+
const $tool = this.manualTelemetry.tool(context.active(), {
|
|
1658
1763
|
name: toolRequest.toolName,
|
|
1659
1764
|
call: {
|
|
1660
1765
|
id: toolRequest.toolCallId,
|
|
@@ -1679,10 +1784,165 @@ class LatitudeInstrumentation {
|
|
|
1679
1784
|
}
|
|
1680
1785
|
}
|
|
1681
1786
|
|
|
1787
|
+
var LatitudeErrorCodes;
|
|
1788
|
+
(function (LatitudeErrorCodes) {
|
|
1789
|
+
LatitudeErrorCodes["UnexpectedError"] = "UnexpectedError";
|
|
1790
|
+
LatitudeErrorCodes["OverloadedError"] = "OverloadedError";
|
|
1791
|
+
LatitudeErrorCodes["RateLimitError"] = "RateLimitError";
|
|
1792
|
+
LatitudeErrorCodes["UnauthorizedError"] = "UnauthorizedError";
|
|
1793
|
+
LatitudeErrorCodes["ForbiddenError"] = "ForbiddenError";
|
|
1794
|
+
LatitudeErrorCodes["BadRequestError"] = "BadRequestError";
|
|
1795
|
+
LatitudeErrorCodes["NotFoundError"] = "NotFoundError";
|
|
1796
|
+
LatitudeErrorCodes["ConflictError"] = "ConflictError";
|
|
1797
|
+
LatitudeErrorCodes["UnprocessableEntityError"] = "UnprocessableEntityError";
|
|
1798
|
+
LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
|
|
1799
|
+
LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
|
|
1800
|
+
LatitudeErrorCodes["AbortedError"] = "AbortedError";
|
|
1801
|
+
})(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
|
|
1802
|
+
// NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
|
|
1803
|
+
var RunErrorCodes;
|
|
1804
|
+
(function (RunErrorCodes) {
|
|
1805
|
+
RunErrorCodes["AIProviderConfigError"] = "ai_provider_config_error";
|
|
1806
|
+
RunErrorCodes["AIRunError"] = "ai_run_error";
|
|
1807
|
+
RunErrorCodes["ChainCompileError"] = "chain_compile_error";
|
|
1808
|
+
RunErrorCodes["DefaultProviderExceededQuota"] = "default_provider_exceeded_quota_error";
|
|
1809
|
+
RunErrorCodes["DefaultProviderInvalidModel"] = "default_provider_invalid_model_error";
|
|
1810
|
+
RunErrorCodes["DocumentConfigError"] = "document_config_error";
|
|
1811
|
+
RunErrorCodes["ErrorGeneratingMockToolResult"] = "error_generating_mock_tool_result";
|
|
1812
|
+
RunErrorCodes["FailedToWakeUpIntegrationError"] = "failed_to_wake_up_integration_error";
|
|
1813
|
+
RunErrorCodes["InvalidResponseFormatError"] = "invalid_response_format_error";
|
|
1814
|
+
RunErrorCodes["MaxStepCountExceededError"] = "max_step_count_exceeded_error";
|
|
1815
|
+
RunErrorCodes["MissingProvider"] = "missing_provider_error";
|
|
1816
|
+
RunErrorCodes["RateLimit"] = "rate_limit_error";
|
|
1817
|
+
RunErrorCodes["Unknown"] = "unknown_error";
|
|
1818
|
+
RunErrorCodes["UnsupportedProviderResponseTypeError"] = "unsupported_provider_response_type_error";
|
|
1819
|
+
RunErrorCodes["PaymentRequiredError"] = "payment_required_error";
|
|
1820
|
+
RunErrorCodes["AbortError"] = "abort_error";
|
|
1821
|
+
// DEPRECATED, but do not delete
|
|
1822
|
+
RunErrorCodes["EvaluationRunMissingProviderLogError"] = "ev_run_missing_provider_log_error";
|
|
1823
|
+
RunErrorCodes["EvaluationRunMissingWorkspaceError"] = "ev_run_missing_workspace_error";
|
|
1824
|
+
RunErrorCodes["EvaluationRunResponseJsonFormatError"] = "ev_run_response_json_format_error";
|
|
1825
|
+
RunErrorCodes["EvaluationRunUnsupportedResultTypeError"] = "ev_run_unsupported_result_type_error";
|
|
1826
|
+
})(RunErrorCodes || (RunErrorCodes = {}));
|
|
1827
|
+
var ApiErrorCodes;
|
|
1828
|
+
(function (ApiErrorCodes) {
|
|
1829
|
+
ApiErrorCodes["HTTPException"] = "http_exception";
|
|
1830
|
+
ApiErrorCodes["InternalServerError"] = "internal_server_error";
|
|
1831
|
+
})(ApiErrorCodes || (ApiErrorCodes = {}));
|
|
1832
|
+
|
|
1833
|
+
class LatitudeError extends Error {
|
|
1834
|
+
statusCode = 500;
|
|
1835
|
+
name = LatitudeErrorCodes.UnexpectedError;
|
|
1836
|
+
headers = {};
|
|
1837
|
+
details;
|
|
1838
|
+
constructor(message, details, status, name) {
|
|
1839
|
+
super(message);
|
|
1840
|
+
this.details = details ?? {};
|
|
1841
|
+
this.statusCode = status ?? this.statusCode;
|
|
1842
|
+
this.name = name ?? this.constructor.name;
|
|
1843
|
+
}
|
|
1844
|
+
serialize() {
|
|
1845
|
+
return {
|
|
1846
|
+
name: this.name,
|
|
1847
|
+
code: this.name,
|
|
1848
|
+
status: this.statusCode,
|
|
1849
|
+
message: this.message,
|
|
1850
|
+
details: this.details,
|
|
1851
|
+
};
|
|
1852
|
+
}
|
|
1853
|
+
static deserialize(json) {
|
|
1854
|
+
return new LatitudeError(json.message, json.details, json.status, json.name);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
class BadRequestError extends LatitudeError {
|
|
1858
|
+
statusCode = 400;
|
|
1859
|
+
name = LatitudeErrorCodes.BadRequestError;
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1682
1862
|
const TRACES_URL = `${env.GATEWAY_BASE_URL}/api/v3/traces`;
|
|
1683
1863
|
const SERVICE_NAME = process.env.npm_package_name || 'unknown';
|
|
1684
1864
|
const SCOPE_VERSION = process.env.npm_package_version || 'unknown';
|
|
1685
1865
|
const BACKGROUND = () => otel.ROOT_CONTEXT;
|
|
1866
|
+
class SpanFactory {
|
|
1867
|
+
telemetry;
|
|
1868
|
+
constructor(telemetry) {
|
|
1869
|
+
this.telemetry = telemetry;
|
|
1870
|
+
}
|
|
1871
|
+
tool(options, ctx) {
|
|
1872
|
+
return this.telemetry.tool(ctx ?? context.active(), options);
|
|
1873
|
+
}
|
|
1874
|
+
completion(options, ctx) {
|
|
1875
|
+
return this.telemetry.completion(ctx ?? context.active(), options);
|
|
1876
|
+
}
|
|
1877
|
+
embedding(options, ctx) {
|
|
1878
|
+
return this.telemetry.embedding(ctx ?? context.active(), options);
|
|
1879
|
+
}
|
|
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
|
+
http(options, ctx) {
|
|
1887
|
+
return this.telemetry.http(ctx ?? context.active(), options);
|
|
1888
|
+
}
|
|
1889
|
+
prompt(options, ctx) {
|
|
1890
|
+
return this.telemetry.prompt(ctx ?? context.active(), options);
|
|
1891
|
+
}
|
|
1892
|
+
step(options, ctx) {
|
|
1893
|
+
return this.telemetry.step(ctx ?? context.active(), options);
|
|
1894
|
+
}
|
|
1895
|
+
chat(options, ctx) {
|
|
1896
|
+
return this.telemetry.chat(ctx ?? context.active(), options);
|
|
1897
|
+
}
|
|
1898
|
+
external(options, ctx) {
|
|
1899
|
+
return this.telemetry.external(ctx ?? context.active(), options);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
class ContextManager {
|
|
1903
|
+
telemetry;
|
|
1904
|
+
constructor(telemetry) {
|
|
1905
|
+
this.telemetry = telemetry;
|
|
1906
|
+
}
|
|
1907
|
+
resume(ctx) {
|
|
1908
|
+
return this.telemetry.resume(ctx);
|
|
1909
|
+
}
|
|
1910
|
+
active() {
|
|
1911
|
+
return context.active();
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
class InstrumentationManager {
|
|
1915
|
+
instrumentations;
|
|
1916
|
+
constructor(instrumentations) {
|
|
1917
|
+
this.instrumentations = instrumentations;
|
|
1918
|
+
}
|
|
1919
|
+
enable() {
|
|
1920
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
1921
|
+
if (!instrumentation.isEnabled())
|
|
1922
|
+
instrumentation.enable();
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
disable() {
|
|
1926
|
+
this.instrumentations.forEach((instrumentation) => {
|
|
1927
|
+
if (instrumentation.isEnabled())
|
|
1928
|
+
instrumentation.disable();
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
class TracerManager {
|
|
1933
|
+
nodeProvider;
|
|
1934
|
+
scopeVersion;
|
|
1935
|
+
constructor(nodeProvider, scopeVersion) {
|
|
1936
|
+
this.nodeProvider = nodeProvider;
|
|
1937
|
+
this.scopeVersion = scopeVersion;
|
|
1938
|
+
}
|
|
1939
|
+
get(scope) {
|
|
1940
|
+
return this.provider(scope).getTracer('');
|
|
1941
|
+
}
|
|
1942
|
+
provider(scope) {
|
|
1943
|
+
return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1686
1946
|
class ScopedTracerProvider {
|
|
1687
1947
|
scope;
|
|
1688
1948
|
version;
|
|
@@ -1720,9 +1980,13 @@ var Instrumentation;
|
|
|
1720
1980
|
})(Instrumentation || (Instrumentation = {}));
|
|
1721
1981
|
class LatitudeTelemetry {
|
|
1722
1982
|
options;
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1983
|
+
nodeProvider;
|
|
1984
|
+
manualInstrumentation;
|
|
1985
|
+
instrumentationsList;
|
|
1986
|
+
span;
|
|
1987
|
+
context;
|
|
1988
|
+
instrumentation;
|
|
1989
|
+
tracer;
|
|
1726
1990
|
constructor(apiKey, options) {
|
|
1727
1991
|
this.options = options || {};
|
|
1728
1992
|
if (!this.options.exporter) {
|
|
@@ -1736,63 +2000,61 @@ class LatitudeTelemetry {
|
|
|
1736
2000
|
new W3CBaggagePropagator(),
|
|
1737
2001
|
],
|
|
1738
2002
|
}));
|
|
1739
|
-
this.
|
|
2003
|
+
this.nodeProvider = new NodeTracerProvider({
|
|
1740
2004
|
resource: new Resource({ [ATTR_SERVICE_NAME]: SERVICE_NAME }),
|
|
1741
2005
|
});
|
|
1742
2006
|
// Note: important, must run before the exporter span processors
|
|
1743
|
-
this.
|
|
2007
|
+
this.nodeProvider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
|
|
1744
2008
|
if (this.options.processors) {
|
|
1745
2009
|
this.options.processors.forEach((processor) => {
|
|
1746
|
-
this.
|
|
2010
|
+
this.nodeProvider.addSpanProcessor(processor);
|
|
1747
2011
|
});
|
|
1748
2012
|
}
|
|
1749
2013
|
else {
|
|
1750
|
-
this.
|
|
2014
|
+
this.nodeProvider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
|
|
1751
2015
|
}
|
|
1752
2016
|
if (this.options.disableBatch) {
|
|
1753
|
-
this.
|
|
2017
|
+
this.nodeProvider.addSpanProcessor(new SimpleSpanProcessor(this.options.exporter));
|
|
1754
2018
|
}
|
|
1755
2019
|
else {
|
|
1756
|
-
this.
|
|
2020
|
+
this.nodeProvider.addSpanProcessor(new BatchSpanProcessor(this.options.exporter));
|
|
1757
2021
|
}
|
|
1758
|
-
this.
|
|
2022
|
+
this.nodeProvider.register();
|
|
1759
2023
|
process.on('SIGTERM', async () => this.shutdown);
|
|
1760
2024
|
process.on('SIGINT', async () => this.shutdown);
|
|
1761
|
-
this.
|
|
1762
|
-
this.
|
|
2025
|
+
this.manualInstrumentation = null;
|
|
2026
|
+
this.instrumentationsList = [];
|
|
2027
|
+
this.tracer = new TracerManager(this.nodeProvider, SCOPE_VERSION);
|
|
1763
2028
|
this.initInstrumentations();
|
|
1764
|
-
this.
|
|
2029
|
+
this.instrumentation = new InstrumentationManager(this.instrumentationsList);
|
|
2030
|
+
this.instrumentation.enable();
|
|
2031
|
+
this.span = new SpanFactory(this.manualInstrumentation);
|
|
2032
|
+
this.context = new ContextManager(this.manualInstrumentation);
|
|
1765
2033
|
}
|
|
1766
2034
|
async flush() {
|
|
1767
|
-
await this.
|
|
2035
|
+
await this.nodeProvider.forceFlush();
|
|
1768
2036
|
await this.options.exporter.forceFlush?.();
|
|
1769
2037
|
}
|
|
1770
2038
|
async shutdown() {
|
|
1771
2039
|
await this.flush();
|
|
1772
|
-
await this.
|
|
2040
|
+
await this.nodeProvider.shutdown();
|
|
1773
2041
|
await this.options.exporter.shutdown?.();
|
|
1774
2042
|
}
|
|
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
2043
|
// TODO(tracing): auto instrument outgoing HTTP requests
|
|
1782
2044
|
initInstrumentations() {
|
|
1783
|
-
this.
|
|
1784
|
-
const tracer = this.tracer(InstrumentationScope.Manual);
|
|
1785
|
-
this.
|
|
1786
|
-
this.
|
|
2045
|
+
this.instrumentationsList = [];
|
|
2046
|
+
const tracer = this.tracer.get(InstrumentationScope.Manual);
|
|
2047
|
+
this.manualInstrumentation = new ManualInstrumentation(tracer);
|
|
2048
|
+
this.instrumentationsList.push(this.manualInstrumentation);
|
|
1787
2049
|
const latitude = this.options.instrumentations?.latitude;
|
|
1788
2050
|
if (latitude) {
|
|
1789
|
-
const tracer = this.tracer(Instrumentation.Latitude);
|
|
2051
|
+
const tracer = this.tracer.get(Instrumentation.Latitude);
|
|
1790
2052
|
const instrumentation = new LatitudeInstrumentation(tracer, typeof latitude === 'object' ? latitude : { module: latitude });
|
|
1791
|
-
this.
|
|
2053
|
+
this.instrumentationsList.push(instrumentation);
|
|
1792
2054
|
}
|
|
1793
2055
|
const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
|
|
1794
2056
|
const providerPkg = this.options.instrumentations?.[instrumentationType];
|
|
1795
|
-
const provider = this.
|
|
2057
|
+
const provider = this.tracer.provider(instrumentationType);
|
|
1796
2058
|
const instrumentation = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
|
|
1797
2059
|
instrumentation.setTracerProvider(provider);
|
|
1798
2060
|
if (providerPkg) {
|
|
@@ -1802,7 +2064,7 @@ class LatitudeTelemetry {
|
|
|
1802
2064
|
instrumentations: [instrumentation],
|
|
1803
2065
|
tracerProvider: provider,
|
|
1804
2066
|
});
|
|
1805
|
-
this.
|
|
2067
|
+
this.instrumentationsList.push(instrumentation);
|
|
1806
2068
|
};
|
|
1807
2069
|
configureInstrumentation(Instrumentation.Anthropic, AnthropicInstrumentation); // prettier-ignore
|
|
1808
2070
|
configureInstrumentation(Instrumentation.AIPlatform, AIPlatformInstrumentation); // prettier-ignore
|
|
@@ -1814,44 +2076,23 @@ class LatitudeTelemetry {
|
|
|
1814
2076
|
configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: true }); // prettier-ignore
|
|
1815
2077
|
configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
|
|
1816
2078
|
}
|
|
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);
|
|
2079
|
+
async capture(options, fn) {
|
|
2080
|
+
if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
|
|
2081
|
+
throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
|
|
2082
|
+
}
|
|
2083
|
+
const span = this.manualInstrumentation.unresolvedExternal(otel.ROOT_CONTEXT, options);
|
|
2084
|
+
try {
|
|
2085
|
+
const result = await context.with(span.context, () => fn(span.context));
|
|
2086
|
+
span.end();
|
|
2087
|
+
return result;
|
|
2088
|
+
}
|
|
2089
|
+
catch (error) {
|
|
2090
|
+
span.fail(error);
|
|
2091
|
+
throw error;
|
|
2092
|
+
}
|
|
2093
|
+
finally {
|
|
2094
|
+
await this.flush();
|
|
2095
|
+
}
|
|
1855
2096
|
}
|
|
1856
2097
|
}
|
|
1857
2098
|
|