agent-inspect 6.31.5 → 6.31.7
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/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/docs/AI-SDK-ADOPTION.md +62 -34
- package/docs/SAFE-TRACE-SHARING.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-LKEPABND.mjs → chunk-QV73NM25.mjs} +100 -31
- package/packages/cli/dist/chunk-QV73NM25.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +474 -92
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +379 -67
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-4WYF5RFI.mjs → src-KFOBXFPN.mjs} +3 -3
- package/packages/cli/dist/{src-4WYF5RFI.mjs.map → src-KFOBXFPN.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +95 -23
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +11 -11
- package/packages/core/dist/checks.cjs +2 -5
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +3 -3
- package/packages/core/dist/{chunk-OSGNGRHF.mjs → chunk-3RV3JILQ.mjs} +34 -16
- package/packages/core/dist/chunk-3RV3JILQ.mjs.map +1 -0
- package/packages/core/dist/{chunk-NY4ILMXK.mjs → chunk-7YYS742B.mjs} +50 -13
- package/packages/core/dist/chunk-7YYS742B.mjs.map +1 -0
- package/packages/core/dist/{chunk-2KJR6X4V.mjs → chunk-DK3OW6UI.mjs} +3 -3
- package/packages/core/dist/chunk-DK3OW6UI.mjs.map +1 -0
- package/packages/core/dist/{chunk-PKDBFBJ7.mjs → chunk-LXYPM2ZO.mjs} +5 -8
- package/packages/core/dist/{chunk-PKDBFBJ7.mjs.map → chunk-LXYPM2ZO.mjs.map} +1 -1
- package/packages/core/dist/{chunk-INE5IWLN.mjs → chunk-N5PZAI6Q.mjs} +3 -3
- package/packages/core/dist/{chunk-INE5IWLN.mjs.map → chunk-N5PZAI6Q.mjs.map} +1 -1
- package/packages/core/dist/{chunk-Q5SLKV2Y.mjs → chunk-QLYUWKK7.mjs} +19 -2
- package/packages/core/dist/chunk-QLYUWKK7.mjs.map +1 -0
- package/packages/core/dist/{chunk-MTMTXTJL.mjs → chunk-VQUB3WRI.mjs} +4 -4
- package/packages/core/dist/{chunk-MTMTXTJL.mjs.map → chunk-VQUB3WRI.mjs.map} +1 -1
- package/packages/core/dist/exporters.cjs +253 -50
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +208 -42
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/index.cjs +1 -1
- package/packages/core/dist/index.cjs.map +1 -1
- package/packages/core/dist/index.mjs +4 -4
- package/packages/core/dist/persisted.cjs +17 -0
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +2 -2
- package/packages/core/dist/readers.cjs +48 -13
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +2 -2
- package/packages/core/dist/writers.cjs +1 -1
- package/packages/core/dist/writers.cjs.map +1 -1
- package/packages/core/dist/writers.mjs +1 -1
- package/packages/cli/dist/chunk-LKEPABND.mjs.map +0 -1
- package/packages/core/dist/chunk-2KJR6X4V.mjs.map +0 -1
- package/packages/core/dist/chunk-NY4ILMXK.mjs.map +0 -1
- package/packages/core/dist/chunk-OSGNGRHF.mjs.map +0 -1
- package/packages/core/dist/chunk-Q5SLKV2Y.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-
|
|
2
|
-
import { summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml } from './chunk-
|
|
1
|
+
import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-7YYS742B.mjs';
|
|
2
|
+
import { summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml } from './chunk-N5PZAI6Q.mjs';
|
|
3
3
|
import { escapeHtml, flattenTree, safeString, compactAttributes, stableJson, escapeMarkdown, zeroKinds } from './chunk-CAWPF22J.mjs';
|
|
4
4
|
export { compactAttributes, escapeHtml, escapeMarkdown, flattenTree, safeString, stableJson, summarizeTree } from './chunk-CAWPF22J.mjs';
|
|
5
|
-
import { resolveRedactionProfile, applyProfileMetadataCaps, truncateStringForProfile, stringContainsHighConfidenceCredential } from './chunk-
|
|
5
|
+
import { resolveRedactionProfile, applyProfileMetadataCaps, truncateStringForProfile, stringContainsHighConfidenceCredential } from './chunk-DK3OW6UI.mjs';
|
|
6
6
|
import { Redactor, DEFAULT_REDACT_KEYS, isCredentialSensitiveKey } from './chunk-VLVCLAPB.mjs';
|
|
7
7
|
import './chunk-7DHSWDKB.mjs';
|
|
8
8
|
import './chunk-EE5Z2GQ3.mjs';
|
|
@@ -27,6 +27,8 @@ var CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
|
27
27
|
"amqps:"
|
|
28
28
|
]);
|
|
29
29
|
var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
30
|
+
var CONNECTION_USERINFO = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
|
|
31
|
+
var CONNECTION_HAS_USERINFO = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
|
|
30
32
|
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31
33
|
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
32
34
|
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
@@ -50,6 +52,28 @@ function parseRedactableUrl(value) {
|
|
|
50
52
|
return void 0;
|
|
51
53
|
}
|
|
52
54
|
}
|
|
55
|
+
function redactConnectionUserinfoFallback(value, replacement) {
|
|
56
|
+
const trimmed = value.trim();
|
|
57
|
+
const match = CONNECTION_USERINFO.exec(trimmed);
|
|
58
|
+
if (match) {
|
|
59
|
+
const [, scheme, , rest] = match;
|
|
60
|
+
if (scheme && rest && rest.length > 0) {
|
|
61
|
+
return {
|
|
62
|
+
value: `${scheme}://${rest}`,
|
|
63
|
+
credentialRedacted: true,
|
|
64
|
+
identifiersMasked: false
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {
|
|
69
|
+
return {
|
|
70
|
+
value: replacement,
|
|
71
|
+
credentialRedacted: true,
|
|
72
|
+
identifiersMasked: false
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
53
77
|
function isHttpProtocol(protocol) {
|
|
54
78
|
return protocol === "http:" || protocol === "https:";
|
|
55
79
|
}
|
|
@@ -91,9 +115,11 @@ function redactUrlString(value, options) {
|
|
|
91
115
|
identifiersMasked: false
|
|
92
116
|
};
|
|
93
117
|
if (!looksLikeUrlForRedaction(value)) return unchanged;
|
|
94
|
-
const url = parseRedactableUrl(value);
|
|
95
|
-
if (!url) return unchanged;
|
|
96
118
|
const replacement = options.replacement ?? "[REDACTED]";
|
|
119
|
+
const url = parseRedactableUrl(value);
|
|
120
|
+
if (!url) {
|
|
121
|
+
return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;
|
|
122
|
+
}
|
|
97
123
|
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
98
124
|
const http = isHttpProtocol(url.protocol);
|
|
99
125
|
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
@@ -782,6 +808,10 @@ function exportOpenInference(tree, options) {
|
|
|
782
808
|
warnings
|
|
783
809
|
};
|
|
784
810
|
}
|
|
811
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
812
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
813
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
814
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
785
815
|
function hexFrom2(seed, byteLen) {
|
|
786
816
|
return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
787
817
|
}
|
|
@@ -794,7 +824,19 @@ function stringAttr(key, value) {
|
|
|
794
824
|
return { key, value: { stringValue: value } };
|
|
795
825
|
}
|
|
796
826
|
function intAttr(key, value) {
|
|
797
|
-
return { key, value: { intValue: String(value) } };
|
|
827
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
828
|
+
}
|
|
829
|
+
function doubleAttr(key, value) {
|
|
830
|
+
return { key, value: { doubleValue: value } };
|
|
831
|
+
}
|
|
832
|
+
function boolAttr(key, value) {
|
|
833
|
+
return { key, value: { boolValue: value } };
|
|
834
|
+
}
|
|
835
|
+
function numberAttr(key, value) {
|
|
836
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
837
|
+
return doubleAttr(key, value);
|
|
838
|
+
}
|
|
839
|
+
return intAttr(key, value);
|
|
798
840
|
}
|
|
799
841
|
function genAiOperationName(kind) {
|
|
800
842
|
switch (kind) {
|
|
@@ -808,10 +850,27 @@ function genAiOperationName(kind) {
|
|
|
808
850
|
return void 0;
|
|
809
851
|
}
|
|
810
852
|
}
|
|
853
|
+
function resolveSpanTimes(ev) {
|
|
854
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
855
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
856
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
857
|
+
const startNs = String(unixNano2(startMs));
|
|
858
|
+
if (endedAtMs !== void 0) {
|
|
859
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
860
|
+
}
|
|
861
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
862
|
+
return {
|
|
863
|
+
startNs,
|
|
864
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
return { startNs };
|
|
868
|
+
}
|
|
811
869
|
function exportOtlpJson(tree, options) {
|
|
812
870
|
const warnings = [
|
|
813
871
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
814
|
-
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
|
|
872
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
873
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
815
874
|
];
|
|
816
875
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
817
876
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -823,11 +882,7 @@ function exportOtlpJson(tree, options) {
|
|
|
823
882
|
const ev = n.event;
|
|
824
883
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
825
884
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
826
|
-
const startNs =
|
|
827
|
-
let endNs;
|
|
828
|
-
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
829
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
830
|
-
}
|
|
885
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
831
886
|
const attrs = [
|
|
832
887
|
stringAttr("agent_inspect.kind", ev.kind),
|
|
833
888
|
stringAttr("agent_inspect.confidence", ev.confidence),
|
|
@@ -857,29 +912,28 @@ function exportOtlpJson(tree, options) {
|
|
|
857
912
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
858
913
|
for (const [k, v] of Object.entries(meta)) {
|
|
859
914
|
if (k === "tokens" || k === "model") continue;
|
|
860
|
-
if (typeof v === "string"
|
|
861
|
-
attrs.push(
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
);
|
|
915
|
+
if (typeof v === "string") {
|
|
916
|
+
attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
917
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
918
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
919
|
+
} else if (typeof v === "boolean") {
|
|
920
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
867
921
|
}
|
|
868
922
|
}
|
|
869
923
|
}
|
|
870
|
-
let statusCode =
|
|
924
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
871
925
|
let statusMessage;
|
|
872
926
|
if (ev.status === "error") {
|
|
873
|
-
statusCode =
|
|
927
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
874
928
|
statusMessage = meta && typeof meta.error === "object" && meta.error !== null ? String(meta.error.message ?? "error").slice(0, maxLen) : "error";
|
|
875
929
|
} else if (ev.status === "ok") {
|
|
876
|
-
statusCode =
|
|
930
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
877
931
|
}
|
|
878
932
|
const spanJson = {
|
|
879
933
|
traceId,
|
|
880
934
|
spanId,
|
|
881
935
|
name: ev.name,
|
|
882
|
-
kind:
|
|
936
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
883
937
|
startTimeUnixNano: startNs,
|
|
884
938
|
attributes: attrs,
|
|
885
939
|
status: {
|
|
@@ -921,6 +975,136 @@ function exportOtlpJson(tree, options) {
|
|
|
921
975
|
|
|
922
976
|
// packages/core/src/exporters/validation.ts
|
|
923
977
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
978
|
+
function pushPath(errors, path, message) {
|
|
979
|
+
errors.push(`${path}: ${message}`);
|
|
980
|
+
}
|
|
981
|
+
function isRecord2(value) {
|
|
982
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
983
|
+
}
|
|
984
|
+
function validateOtlpJson(content) {
|
|
985
|
+
const errors = [];
|
|
986
|
+
const warnings = [
|
|
987
|
+
EXPERIMENTAL,
|
|
988
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
989
|
+
"protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
|
|
990
|
+
];
|
|
991
|
+
let parsed;
|
|
992
|
+
try {
|
|
993
|
+
parsed = JSON.parse(content);
|
|
994
|
+
} catch {
|
|
995
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
996
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
997
|
+
}
|
|
998
|
+
if (!isRecord2(parsed)) {
|
|
999
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
1000
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
1001
|
+
}
|
|
1002
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
1003
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
1004
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
1005
|
+
}
|
|
1006
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
1007
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
1008
|
+
if (!isRecord2(resourceSpan)) {
|
|
1009
|
+
pushPath(errors, rsPath, "must be an object");
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
1013
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
1017
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
1018
|
+
if (!isRecord2(scopeSpan)) {
|
|
1019
|
+
pushPath(errors, ssPath, "must be an object");
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
1023
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
1027
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
1028
|
+
if (!isRecord2(span)) {
|
|
1029
|
+
pushPath(errors, spanPath, "must be an object");
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
if (typeof span.traceId !== "string" || span.traceId.length === 0) {
|
|
1033
|
+
pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
|
|
1034
|
+
}
|
|
1035
|
+
if (typeof span.spanId !== "string" || span.spanId.length === 0) {
|
|
1036
|
+
pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
|
|
1037
|
+
}
|
|
1038
|
+
if (typeof span.name !== "string") {
|
|
1039
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
1040
|
+
}
|
|
1041
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
1042
|
+
pushPath(
|
|
1043
|
+
errors,
|
|
1044
|
+
`${spanPath}.startTimeUnixNano`,
|
|
1045
|
+
"must be a decimal-string 64-bit integer"
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
1049
|
+
pushPath(
|
|
1050
|
+
errors,
|
|
1051
|
+
`${spanPath}.endTimeUnixNano`,
|
|
1052
|
+
"must be a decimal-string 64-bit integer when present"
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
if (typeof span.kind === "number") {
|
|
1056
|
+
if (!Number.isInteger(span.kind)) {
|
|
1057
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
1058
|
+
}
|
|
1059
|
+
} else if (typeof span.kind === "string") {
|
|
1060
|
+
warnings.push(
|
|
1061
|
+
`${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
|
|
1062
|
+
);
|
|
1063
|
+
} else if (span.kind !== void 0) {
|
|
1064
|
+
pushPath(
|
|
1065
|
+
errors,
|
|
1066
|
+
`${spanPath}.kind`,
|
|
1067
|
+
"must be numeric SpanKind or historical string enum"
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
if (!isRecord2(span.status)) {
|
|
1071
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
1072
|
+
} else {
|
|
1073
|
+
const code = span.status.code;
|
|
1074
|
+
if (typeof code === "number") {
|
|
1075
|
+
if (![0, 1, 2].includes(code)) {
|
|
1076
|
+
pushPath(
|
|
1077
|
+
errors,
|
|
1078
|
+
`${spanPath}.status.code`,
|
|
1079
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
} else if (typeof code === "string") {
|
|
1083
|
+
const upper = code.toUpperCase();
|
|
1084
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
1085
|
+
pushPath(
|
|
1086
|
+
errors,
|
|
1087
|
+
`${spanPath}.status.code`,
|
|
1088
|
+
"unrecognized StatusCode string"
|
|
1089
|
+
);
|
|
1090
|
+
} else {
|
|
1091
|
+
warnings.push(
|
|
1092
|
+
`${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
} else {
|
|
1096
|
+
pushPath(
|
|
1097
|
+
errors,
|
|
1098
|
+
`${spanPath}.status.code`,
|
|
1099
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
});
|
|
1105
|
+
});
|
|
1106
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
1107
|
+
}
|
|
924
1108
|
function validateExportContent(format, content) {
|
|
925
1109
|
const errors = [];
|
|
926
1110
|
const warnings = [EXPERIMENTAL];
|
|
@@ -966,25 +1150,7 @@ function validateExportContent(format, content) {
|
|
|
966
1150
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
967
1151
|
}
|
|
968
1152
|
if (format === "otlp-json") {
|
|
969
|
-
|
|
970
|
-
try {
|
|
971
|
-
parsed = JSON.parse(content);
|
|
972
|
-
} catch {
|
|
973
|
-
errors.push("OTLP JSON export is not valid JSON");
|
|
974
|
-
return { ok: false, format, errors, warnings };
|
|
975
|
-
}
|
|
976
|
-
if (!parsed || typeof parsed !== "object") {
|
|
977
|
-
errors.push("OTLP JSON export must be an object");
|
|
978
|
-
return { ok: false, format, errors, warnings };
|
|
979
|
-
}
|
|
980
|
-
const o = parsed;
|
|
981
|
-
if (!Array.isArray(o.resourceSpans)) {
|
|
982
|
-
errors.push("OTLP JSON export must include resourceSpans array");
|
|
983
|
-
}
|
|
984
|
-
warnings.push(
|
|
985
|
-
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
|
|
986
|
-
);
|
|
987
|
-
return { ok: errors.length === 0, format, errors, warnings };
|
|
1153
|
+
return validateOtlpJson(content);
|
|
988
1154
|
}
|
|
989
1155
|
errors.push(`Unsupported export format`);
|
|
990
1156
|
return { ok: false, format, errors, warnings };
|