neatlogs 1.1.19 → 1.1.21
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/README.md +34 -2
- package/dist/ai-sdk.cjs +186 -11
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.d.ts +17 -7
- package/dist/ai-sdk.mjs +189 -12
- package/dist/ai-sdk.mjs.map +1 -1
- package/dist/anthropic.cjs +31 -14
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.mjs +31 -14
- package/dist/anthropic.mjs.map +1 -1
- package/dist/azure-openai.cjs +31 -14
- package/dist/azure-openai.cjs.map +1 -1
- package/dist/azure-openai.mjs +31 -14
- package/dist/azure-openai.mjs.map +1 -1
- package/dist/bedrock.cjs +31 -14
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.mjs +31 -14
- package/dist/bedrock.mjs.map +1 -1
- package/dist/browser.cjs +26 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.mjs +26 -1
- package/dist/browser.mjs.map +1 -1
- package/dist/claude-agent-sdk.cjs +2 -2
- package/dist/claude-agent-sdk.cjs.map +1 -1
- package/dist/claude-agent-sdk.mjs +2 -2
- package/dist/claude-agent-sdk.mjs.map +1 -1
- package/dist/cli.cjs +452 -200
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +427 -173
- package/dist/cli.mjs.map +1 -1
- package/dist/google-genai.cjs +31 -14
- package/dist/google-genai.cjs.map +1 -1
- package/dist/google-genai.mjs +31 -14
- package/dist/google-genai.mjs.map +1 -1
- package/dist/index.cjs +652 -333
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +505 -184
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +3 -3
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.mjs +3 -3
- package/dist/langchain.mjs.map +1 -1
- package/dist/mastra-wrap.cjs +2 -2
- package/dist/mastra-wrap.cjs.map +1 -1
- package/dist/mastra-wrap.mjs +2 -2
- package/dist/mastra-wrap.mjs.map +1 -1
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.mjs.map +1 -1
- package/dist/openai.cjs +31 -14
- package/dist/openai.cjs.map +1 -1
- package/dist/openai.mjs +31 -14
- package/dist/openai.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +1 -1
- package/dist/opencode-plugin.cjs.map +1 -1
- package/dist/opencode-plugin.mjs +1 -1
- package/dist/opencode-plugin.mjs.map +1 -1
- package/dist/openrouter-agent.cjs +31 -14
- package/dist/openrouter-agent.cjs.map +1 -1
- package/dist/openrouter-agent.mjs +31 -14
- package/dist/openrouter-agent.mjs.map +1 -1
- package/dist/pi-agent.cjs.map +1 -1
- package/dist/pi-agent.mjs.map +1 -1
- package/dist/vertex-ai.cjs +31 -14
- package/dist/vertex-ai.cjs.map +1 -1
- package/dist/vertex-ai.mjs +31 -14
- package/dist/vertex-ai.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/doctor-cli.ts
|
|
27
|
-
var
|
|
27
|
+
var import_api11 = require("@opentelemetry/api");
|
|
28
28
|
|
|
29
29
|
// src/core/doctor-capture.ts
|
|
30
30
|
var import_api = require("@opentelemetry/api");
|
|
@@ -81,6 +81,110 @@ function enableLogging() {
|
|
|
81
81
|
_disabled = false;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
// src/span-kinds/constants.ts
|
|
85
|
+
var VECTOR_DB_SYSTEMS = /* @__PURE__ */ new Set([
|
|
86
|
+
"chroma",
|
|
87
|
+
"chromadb",
|
|
88
|
+
"pinecone",
|
|
89
|
+
"qdrant",
|
|
90
|
+
"milvus",
|
|
91
|
+
"marqo",
|
|
92
|
+
"weaviate",
|
|
93
|
+
"lancedb",
|
|
94
|
+
"pgvector",
|
|
95
|
+
"elasticsearch"
|
|
96
|
+
]);
|
|
97
|
+
var RETRIEVAL_OPS = [
|
|
98
|
+
"query",
|
|
99
|
+
"search",
|
|
100
|
+
"get",
|
|
101
|
+
"fetch",
|
|
102
|
+
"find",
|
|
103
|
+
"retrieve",
|
|
104
|
+
"scroll",
|
|
105
|
+
"peek",
|
|
106
|
+
"discover",
|
|
107
|
+
"recommend",
|
|
108
|
+
"aggregate",
|
|
109
|
+
"hybrid_search",
|
|
110
|
+
"select"
|
|
111
|
+
];
|
|
112
|
+
var VECTOR_DB_NAMES = [
|
|
113
|
+
"chroma",
|
|
114
|
+
"pinecone",
|
|
115
|
+
"weaviate",
|
|
116
|
+
"qdrant",
|
|
117
|
+
"milvus",
|
|
118
|
+
"lancedb",
|
|
119
|
+
"marqo"
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
// src/span-kinds/mapping.ts
|
|
123
|
+
var VALID_SPAN_KINDS = /* @__PURE__ */ new Set([
|
|
124
|
+
"WORKFLOW",
|
|
125
|
+
"AGENT",
|
|
126
|
+
"CHAIN",
|
|
127
|
+
"TOOL",
|
|
128
|
+
"RETRIEVER",
|
|
129
|
+
"EMBEDDING",
|
|
130
|
+
"MCP_TOOL",
|
|
131
|
+
"GUARDRAIL",
|
|
132
|
+
"EVALUATOR"
|
|
133
|
+
]);
|
|
134
|
+
var ALL_SPAN_KINDS = /* @__PURE__ */ new Set([
|
|
135
|
+
...VALID_SPAN_KINDS,
|
|
136
|
+
"LLM",
|
|
137
|
+
"RERANKER",
|
|
138
|
+
"VECTOR_STORE"
|
|
139
|
+
]);
|
|
140
|
+
function resolveExplicitSpanKind(attributes) {
|
|
141
|
+
for (const key of [
|
|
142
|
+
"neatlogs.span.kind",
|
|
143
|
+
"openinference.span.kind",
|
|
144
|
+
"traceloop.span.kind"
|
|
145
|
+
]) {
|
|
146
|
+
const value = String(attributes[key] ?? "").trim();
|
|
147
|
+
if (value) return value;
|
|
148
|
+
}
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
151
|
+
function inferSpanKindFromName(spanName) {
|
|
152
|
+
const nameLower = spanName.toLowerCase();
|
|
153
|
+
if (["openai", "anthropic", "cohere", "bedrock", "chat", "completion", "llm", "gemini", "google_genai"].some(
|
|
154
|
+
(kw) => nameLower.includes(kw)
|
|
155
|
+
)) {
|
|
156
|
+
return "LLM";
|
|
157
|
+
}
|
|
158
|
+
if (nameLower.includes("embed")) {
|
|
159
|
+
return "EMBEDDING";
|
|
160
|
+
}
|
|
161
|
+
if (VECTOR_DB_NAMES.some((db) => nameLower.includes(db))) {
|
|
162
|
+
if (RETRIEVAL_OPS.some((kw) => nameLower.includes(kw))) {
|
|
163
|
+
return "RETRIEVER";
|
|
164
|
+
}
|
|
165
|
+
return "VECTOR_STORE";
|
|
166
|
+
}
|
|
167
|
+
if (["retriev", "search", "query"].some((kw) => nameLower.includes(kw))) {
|
|
168
|
+
return "RETRIEVER";
|
|
169
|
+
}
|
|
170
|
+
if (nameLower.includes("rerank")) {
|
|
171
|
+
return "RERANKER";
|
|
172
|
+
}
|
|
173
|
+
if (nameLower.includes("agent")) {
|
|
174
|
+
return "AGENT";
|
|
175
|
+
}
|
|
176
|
+
if (["tool", "function"].some((kw) => nameLower.includes(kw))) {
|
|
177
|
+
return "TOOL";
|
|
178
|
+
}
|
|
179
|
+
if (["guardrail", "validate", "moderate", "safety"].some((kw) => nameLower.includes(kw))) {
|
|
180
|
+
return "GUARDRAIL";
|
|
181
|
+
}
|
|
182
|
+
if (["evaluat", "score", "metric"].some((kw) => nameLower.includes(kw))) {
|
|
183
|
+
return "EVALUATOR";
|
|
184
|
+
}
|
|
185
|
+
return "CHAIN";
|
|
186
|
+
}
|
|
187
|
+
|
|
84
188
|
// src/config/attribute-mapping.json
|
|
85
189
|
var attribute_mapping_default = {
|
|
86
190
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
@@ -1258,27 +1362,11 @@ var AttributeMapper = class {
|
|
|
1258
1362
|
/** Extract and normalize span kind from multiple possible sources. */
|
|
1259
1363
|
mapSpanKind(attributes) {
|
|
1260
1364
|
const spanKindConfig = this.mappings.span_kind ?? {};
|
|
1261
|
-
const sources = spanKindConfig.sources ?? [];
|
|
1262
1365
|
const valuesMap = spanKindConfig.values ?? {};
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
if (
|
|
1267
|
-
spanKindValue = attributes["openinference.span.kind"];
|
|
1268
|
-
}
|
|
1269
|
-
} else {
|
|
1270
|
-
for (const source of sources) {
|
|
1271
|
-
if (source in attributes) {
|
|
1272
|
-
spanKindValue = attributes[source];
|
|
1273
|
-
break;
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
if (!spanKindValue && "neatlogs.span.kind" in attributes) {
|
|
1278
|
-
spanKindValue = attributes["neatlogs.span.kind"];
|
|
1279
|
-
}
|
|
1280
|
-
if (spanKindValue && spanKindValue in valuesMap) {
|
|
1281
|
-
return valuesMap[spanKindValue];
|
|
1366
|
+
const spanKindValue = resolveExplicitSpanKind(attributes);
|
|
1367
|
+
if (spanKindValue) {
|
|
1368
|
+
const mapped = valuesMap[spanKindValue] ?? valuesMap[spanKindValue.toUpperCase()];
|
|
1369
|
+
if (mapped) return mapped;
|
|
1282
1370
|
}
|
|
1283
1371
|
if (spanKindValue && Object.values(valuesMap).includes(spanKindValue)) {
|
|
1284
1372
|
return spanKindValue;
|
|
@@ -1851,7 +1939,7 @@ function clearDoctorCapture() {
|
|
|
1851
1939
|
}
|
|
1852
1940
|
|
|
1853
1941
|
// src/core/context.ts
|
|
1854
|
-
var
|
|
1942
|
+
var import_api5 = require("@opentelemetry/api");
|
|
1855
1943
|
|
|
1856
1944
|
// src/prompt/template.ts
|
|
1857
1945
|
var import_node_async_hooks = require("async_hooks");
|
|
@@ -2190,11 +2278,11 @@ function getNeatlogsRootSpan() {
|
|
|
2190
2278
|
function getNeatlogsParentContext(baseContext) {
|
|
2191
2279
|
return baseContext ?? getNeatlogsActiveContext();
|
|
2192
2280
|
}
|
|
2193
|
-
function withNeatlogsSpan(span2, fn, baseContext) {
|
|
2281
|
+
function withNeatlogsSpan(span2, fn, baseContext, rootSpan) {
|
|
2194
2282
|
const base = baseContext ?? getNeatlogsActiveContext();
|
|
2195
2283
|
let ctx = import_api2.trace.setSpan(base, span2);
|
|
2196
2284
|
if (base.getValue(NEATLOGS_ROOT_SPAN_KEY) === void 0) {
|
|
2197
|
-
ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, span2);
|
|
2285
|
+
ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, rootSpan ?? span2);
|
|
2198
2286
|
}
|
|
2199
2287
|
return privateContextStorage.run(ctx, fn);
|
|
2200
2288
|
}
|
|
@@ -3926,8 +4014,84 @@ function discardPendingMediaOwner(owner) {
|
|
|
3926
4014
|
pendingMediaOwners.delete(owner ?? defaultPendingMediaOwner);
|
|
3927
4015
|
}
|
|
3928
4016
|
|
|
3929
|
-
// src/
|
|
4017
|
+
// src/core/auto-root.ts
|
|
3930
4018
|
var import_api3 = require("@opentelemetry/api");
|
|
4019
|
+
var boundAutoRoots = /* @__PURE__ */ new WeakMap();
|
|
4020
|
+
var ROOT_KINDS = /* @__PURE__ */ new Set(["workflow", "chain", "agent", "mcp_tool", "llm"]);
|
|
4021
|
+
function autoRootEnabled() {
|
|
4022
|
+
const val = (process.env.NEATLOGS_AUTO_ROOT ?? "").trim().toLowerCase();
|
|
4023
|
+
return !["false", "0", "no", "off"].includes(val);
|
|
4024
|
+
}
|
|
4025
|
+
function resolveRootWorkflowName() {
|
|
4026
|
+
const clientName = getActiveClient()?.workflowName;
|
|
4027
|
+
if (typeof clientName === "string" && clientName.trim()) return clientName;
|
|
4028
|
+
try {
|
|
4029
|
+
const name = getSessionConfig()?.workflowName;
|
|
4030
|
+
if (typeof name === "string" && name.trim()) return name;
|
|
4031
|
+
} catch {
|
|
4032
|
+
}
|
|
4033
|
+
return "workflow";
|
|
4034
|
+
}
|
|
4035
|
+
function stampRootIdentity(root) {
|
|
4036
|
+
applySessionAttributes(root, void 0, true);
|
|
4037
|
+
applyEndUserAttributes(root, void 0, void 0, true);
|
|
4038
|
+
}
|
|
4039
|
+
function bindSpanToAutoRoot(child, root) {
|
|
4040
|
+
if (!root) return child;
|
|
4041
|
+
let ended = false;
|
|
4042
|
+
const proxy = new Proxy(child, {
|
|
4043
|
+
get(target, prop, _receiver) {
|
|
4044
|
+
if (prop === "end") {
|
|
4045
|
+
return (...args) => {
|
|
4046
|
+
if (ended) return;
|
|
4047
|
+
ended = true;
|
|
4048
|
+
try {
|
|
4049
|
+
target.end(...args);
|
|
4050
|
+
} finally {
|
|
4051
|
+
try {
|
|
4052
|
+
root.end();
|
|
4053
|
+
} catch {
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
};
|
|
4057
|
+
}
|
|
4058
|
+
const value = Reflect.get(target, prop, target);
|
|
4059
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
4060
|
+
}
|
|
4061
|
+
});
|
|
4062
|
+
boundAutoRoots.set(proxy, root);
|
|
4063
|
+
aliasMediaCaptureSpan(proxy, child);
|
|
4064
|
+
return proxy;
|
|
4065
|
+
}
|
|
4066
|
+
function maybeOpenAutoRoot(tracer, kind, baseCtx) {
|
|
4067
|
+
const k = String(kind ?? "").toLowerCase();
|
|
4068
|
+
const existing = getActiveNeatlogsSpan();
|
|
4069
|
+
if (!autoRootEnabled() || ROOT_KINDS.has(k) || existing !== void 0 && existing.isRecording()) {
|
|
4070
|
+
return { root: void 0, ctx: baseCtx };
|
|
4071
|
+
}
|
|
4072
|
+
const root = tracer.startSpan(
|
|
4073
|
+
resolveRootWorkflowName(),
|
|
4074
|
+
{ attributes: { "neatlogs.span.kind": "workflow", "neatlogs.auto_root": true } },
|
|
4075
|
+
baseCtx
|
|
4076
|
+
);
|
|
4077
|
+
stampRootIdentity(root);
|
|
4078
|
+
return { root, ctx: import_api3.trace.setSpan(baseCtx, root) };
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
// src/errors.ts
|
|
4082
|
+
var NeatlogsConfigurationError = class extends TypeError {
|
|
4083
|
+
code;
|
|
4084
|
+
option;
|
|
4085
|
+
constructor(code, option, message) {
|
|
4086
|
+
super(message);
|
|
4087
|
+
this.name = "NeatlogsConfigurationError";
|
|
4088
|
+
this.code = code;
|
|
4089
|
+
this.option = option;
|
|
4090
|
+
}
|
|
4091
|
+
};
|
|
4092
|
+
|
|
4093
|
+
// src/decorators/base.ts
|
|
4094
|
+
var import_api4 = require("@opentelemetry/api");
|
|
3931
4095
|
var logger5 = getLogger();
|
|
3932
4096
|
var TRACER_NAME = "neatlogs";
|
|
3933
4097
|
var STREAM_CAPTURE_TRUNCATED = "[TRUNCATED_STREAM_OUTPUT]";
|
|
@@ -3999,8 +4163,29 @@ function decorateSpan(opts, fn) {
|
|
|
3999
4163
|
const wrapped = (...args) => {
|
|
4000
4164
|
const tracer = getNeatlogsTracer(TRACER_NAME);
|
|
4001
4165
|
const isRoot = isRootSpan();
|
|
4002
|
-
const parentContext = isRoot ?
|
|
4003
|
-
const
|
|
4166
|
+
const parentContext = isRoot ? import_api4.ROOT_CONTEXT : getNeatlogsParentContext();
|
|
4167
|
+
const autoRoot = maybeOpenAutoRoot(
|
|
4168
|
+
tracer,
|
|
4169
|
+
String(opts.kind ?? ""),
|
|
4170
|
+
parentContext
|
|
4171
|
+
);
|
|
4172
|
+
if (autoRoot.root) {
|
|
4173
|
+
applySessionAttributes(autoRoot.root, opts.sessionId, true, {
|
|
4174
|
+
parentSessionId: opts.parentSessionId,
|
|
4175
|
+
sessionFeatureName: opts.sessionFeatureName,
|
|
4176
|
+
sessionEntryPoint: opts.sessionEntryPoint
|
|
4177
|
+
});
|
|
4178
|
+
applyEndUserAttributes(
|
|
4179
|
+
autoRoot.root,
|
|
4180
|
+
opts.endUserId,
|
|
4181
|
+
opts.endUserMetadata,
|
|
4182
|
+
true
|
|
4183
|
+
);
|
|
4184
|
+
}
|
|
4185
|
+
const span2 = bindSpanToAutoRoot(
|
|
4186
|
+
tracer.startSpan(spanName, {}, autoRoot.ctx),
|
|
4187
|
+
autoRoot.root
|
|
4188
|
+
);
|
|
4004
4189
|
return withNeatlogsSpan(span2, () => {
|
|
4005
4190
|
let finished = false;
|
|
4006
4191
|
let streamInterrupted = false;
|
|
@@ -4040,7 +4225,7 @@ function decorateSpan(opts, fn) {
|
|
|
4040
4225
|
if (finished) return;
|
|
4041
4226
|
finished = true;
|
|
4042
4227
|
captureResult(result);
|
|
4043
|
-
span2.setStatus({ code:
|
|
4228
|
+
span2.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
4044
4229
|
span2.end();
|
|
4045
4230
|
};
|
|
4046
4231
|
const setStreamCounts = () => {
|
|
@@ -4079,12 +4264,12 @@ function decorateSpan(opts, fn) {
|
|
|
4079
4264
|
setStreamCounts();
|
|
4080
4265
|
captureResult(streamCaptureValue());
|
|
4081
4266
|
}
|
|
4082
|
-
span2.setStatus({ code:
|
|
4267
|
+
span2.setStatus({ code: import_api4.SpanStatusCode.UNSET });
|
|
4083
4268
|
span2.end();
|
|
4084
4269
|
return;
|
|
4085
4270
|
}
|
|
4086
4271
|
span2.setStatus({
|
|
4087
|
-
code:
|
|
4272
|
+
code: import_api4.SpanStatusCode.ERROR,
|
|
4088
4273
|
message: error?.message ?? String(error)
|
|
4089
4274
|
});
|
|
4090
4275
|
span2.recordException(
|
|
@@ -4149,7 +4334,7 @@ function decorateSpan(opts, fn) {
|
|
|
4149
4334
|
finished = true;
|
|
4150
4335
|
span2.setAttribute("neatlogs.stream.cancelled", true);
|
|
4151
4336
|
captureResult(streamCaptureValue());
|
|
4152
|
-
span2.setStatus({ code:
|
|
4337
|
+
span2.setStatus({ code: import_api4.SpanStatusCode.UNSET });
|
|
4153
4338
|
span2.end();
|
|
4154
4339
|
};
|
|
4155
4340
|
const wrapAsyncIterator = (iterator) => {
|
|
@@ -4369,7 +4554,8 @@ function decorateSpan(opts, fn) {
|
|
|
4369
4554
|
});
|
|
4370
4555
|
try {
|
|
4371
4556
|
setCommonSpanAttrs(span2, opts);
|
|
4372
|
-
|
|
4557
|
+
const spanIsRoot = isRoot && !autoRoot.root;
|
|
4558
|
+
applySessionAttributes(span2, opts.sessionId, spanIsRoot, {
|
|
4373
4559
|
parentSessionId: opts.parentSessionId,
|
|
4374
4560
|
sessionFeatureName: opts.sessionFeatureName,
|
|
4375
4561
|
sessionEntryPoint: opts.sessionEntryPoint
|
|
@@ -4378,7 +4564,7 @@ function decorateSpan(opts, fn) {
|
|
|
4378
4564
|
span2,
|
|
4379
4565
|
opts.endUserId,
|
|
4380
4566
|
opts.endUserMetadata,
|
|
4381
|
-
|
|
4567
|
+
spanIsRoot
|
|
4382
4568
|
);
|
|
4383
4569
|
if (captureInput && args.length > 0) {
|
|
4384
4570
|
try {
|
|
@@ -4418,7 +4604,7 @@ function decorateSpan(opts, fn) {
|
|
|
4418
4604
|
finishError(error);
|
|
4419
4605
|
throw error;
|
|
4420
4606
|
}
|
|
4421
|
-
});
|
|
4607
|
+
}, autoRoot.ctx, autoRoot.root);
|
|
4422
4608
|
};
|
|
4423
4609
|
Object.defineProperty(wrapped, "name", {
|
|
4424
4610
|
value: spanName,
|
|
@@ -4447,11 +4633,14 @@ var _sessionConfig = {};
|
|
|
4447
4633
|
function _setSessionConfig(config) {
|
|
4448
4634
|
_sessionConfig = config;
|
|
4449
4635
|
}
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
var
|
|
4454
|
-
var
|
|
4636
|
+
function getSessionConfig() {
|
|
4637
|
+
return { ..._sessionConfig };
|
|
4638
|
+
}
|
|
4639
|
+
var PROMPT_VARIABLES_KEY = (0, import_api5.createContextKey)("neatlogs.prompt_variables");
|
|
4640
|
+
var PROMPT_TEMPLATE_KEY = (0, import_api5.createContextKey)("neatlogs.prompt_template");
|
|
4641
|
+
var PROMPT_VERSION_KEY = (0, import_api5.createContextKey)("neatlogs.prompt_version");
|
|
4642
|
+
var USER_PROMPT_TEMPLATE_KEY = (0, import_api5.createContextKey)("neatlogs.user_prompt_template");
|
|
4643
|
+
var USER_PROMPT_VARIABLES_KEY = (0, import_api5.createContextKey)("neatlogs.user_prompt_variables");
|
|
4455
4644
|
var KNOWN_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
4456
4645
|
"name",
|
|
4457
4646
|
"kind",
|
|
@@ -4470,6 +4659,20 @@ var KNOWN_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
4470
4659
|
"endUserId",
|
|
4471
4660
|
"endUserMetadata"
|
|
4472
4661
|
]);
|
|
4662
|
+
function assertNoHttpSpanKind(kind, attributes) {
|
|
4663
|
+
const candidates = [
|
|
4664
|
+
kind,
|
|
4665
|
+
attributes?.["neatlogs.span.kind"],
|
|
4666
|
+
attributes?.["openinference.span.kind"]
|
|
4667
|
+
];
|
|
4668
|
+
if (candidates.some((value) => String(value ?? "").trim().toUpperCase() === "HTTP")) {
|
|
4669
|
+
throw new NeatlogsConfigurationError(
|
|
4670
|
+
"UNSUPPORTED_SPAN_KIND",
|
|
4671
|
+
"kind",
|
|
4672
|
+
"HTTP spans are not supported. Trace the semantic LLM, TOOL, RETRIEVER, or other AI operation instead."
|
|
4673
|
+
);
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4473
4676
|
function _setSpanAttributes(span2, kind, attributes) {
|
|
4474
4677
|
if (kind?.toUpperCase() === "LLM") {
|
|
4475
4678
|
span2.setAttribute("neatlogs.internal", true);
|
|
@@ -4540,6 +4743,7 @@ async function trace(options, fn) {
|
|
|
4540
4743
|
attributes: explicitAttributes,
|
|
4541
4744
|
...extraOptions
|
|
4542
4745
|
} = options;
|
|
4746
|
+
assertNoHttpSpanKind(kind, explicitAttributes);
|
|
4543
4747
|
const sessionId = sessionIdOption ?? currentSessionId();
|
|
4544
4748
|
const currentSpan = getActiveNeatlogsSpan();
|
|
4545
4749
|
const rootSpan = getNeatlogsRootSpan();
|
|
@@ -4584,7 +4788,7 @@ async function trace(options, fn) {
|
|
|
4584
4788
|
}
|
|
4585
4789
|
let ctx = getNeatlogsActiveContext();
|
|
4586
4790
|
if (shouldFallbackToRoot) {
|
|
4587
|
-
ctx =
|
|
4791
|
+
ctx = import_api5.trace.setSpan(ctx, rootSpan);
|
|
4588
4792
|
}
|
|
4589
4793
|
const variablesJson = promptVariables ? JSON.stringify(promptVariables) : void 0;
|
|
4590
4794
|
const userVariablesJson = userPromptVariables ? JSON.stringify(userPromptVariables) : void 0;
|
|
@@ -4618,12 +4822,13 @@ async function trace(options, fn) {
|
|
|
4618
4822
|
const tracer = getNeatlogsTracer("neatlogs.trace");
|
|
4619
4823
|
const spanCallback = async (span3) => {
|
|
4620
4824
|
_setSpanAttributes(span3, kind, extraAttributes);
|
|
4621
|
-
|
|
4825
|
+
const spanIsRoot = isRootTrace && !autoRoot.root;
|
|
4826
|
+
applySessionAttributes(span3, sessionId, spanIsRoot, {
|
|
4622
4827
|
parentSessionId,
|
|
4623
4828
|
sessionFeatureName,
|
|
4624
4829
|
sessionEntryPoint
|
|
4625
4830
|
});
|
|
4626
|
-
applyEndUserAttributes(span3, endUserId, endUserMetadata,
|
|
4831
|
+
applyEndUserAttributes(span3, endUserId, endUserMetadata, spanIsRoot);
|
|
4627
4832
|
if (input !== void 0 && input !== null) {
|
|
4628
4833
|
const capturedInput = captureMedia(
|
|
4629
4834
|
span3,
|
|
@@ -4656,7 +4861,7 @@ async function trace(options, fn) {
|
|
|
4656
4861
|
return result;
|
|
4657
4862
|
} catch (error) {
|
|
4658
4863
|
span3.setStatus({
|
|
4659
|
-
code:
|
|
4864
|
+
code: import_api5.SpanStatusCode.ERROR,
|
|
4660
4865
|
message: error instanceof Error ? error.message : String(error)
|
|
4661
4866
|
});
|
|
4662
4867
|
span3.recordException(
|
|
@@ -4673,108 +4878,36 @@ async function trace(options, fn) {
|
|
|
4673
4878
|
span3.end();
|
|
4674
4879
|
}
|
|
4675
4880
|
};
|
|
4676
|
-
const parentContext = shouldCreateRootTrace ?
|
|
4881
|
+
const parentContext = shouldCreateRootTrace ? import_api5.ROOT_CONTEXT : getNeatlogsParentContext(ctx);
|
|
4677
4882
|
const startAttributes = kind ? { "openinference.span.kind": kind } : void 0;
|
|
4678
|
-
const
|
|
4883
|
+
const autoRoot = isRootTrace ? maybeOpenAutoRoot(tracer, String(kind ?? "CHAIN"), parentContext) : { root: void 0, ctx: parentContext };
|
|
4884
|
+
if (autoRoot.root) {
|
|
4885
|
+
applySessionAttributes(autoRoot.root, sessionId, true, {
|
|
4886
|
+
parentSessionId,
|
|
4887
|
+
sessionFeatureName,
|
|
4888
|
+
sessionEntryPoint
|
|
4889
|
+
});
|
|
4890
|
+
applyEndUserAttributes(autoRoot.root, endUserId, endUserMetadata, true);
|
|
4891
|
+
}
|
|
4892
|
+
const span2 = bindSpanToAutoRoot(
|
|
4893
|
+
tracer.startSpan(
|
|
4894
|
+
name,
|
|
4895
|
+
startAttributes ? { attributes: startAttributes } : {},
|
|
4896
|
+
autoRoot.ctx
|
|
4897
|
+
),
|
|
4898
|
+
autoRoot.root
|
|
4899
|
+
);
|
|
4679
4900
|
if (shouldCreateRootTrace) {
|
|
4680
4901
|
logger6.debug(`[trace] Creating NEW root trace '${name}' (sessionId=${sessionId})`);
|
|
4681
4902
|
} else {
|
|
4682
4903
|
logger6.debug(`[trace] Creating child span '${name}'`);
|
|
4683
4904
|
}
|
|
4684
|
-
return withNeatlogsSpan(
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
"chromadb",
|
|
4691
|
-
"pinecone",
|
|
4692
|
-
"qdrant",
|
|
4693
|
-
"milvus",
|
|
4694
|
-
"marqo",
|
|
4695
|
-
"weaviate",
|
|
4696
|
-
"lancedb",
|
|
4697
|
-
"pgvector",
|
|
4698
|
-
"elasticsearch"
|
|
4699
|
-
]);
|
|
4700
|
-
var RETRIEVAL_OPS = [
|
|
4701
|
-
"query",
|
|
4702
|
-
"search",
|
|
4703
|
-
"get",
|
|
4704
|
-
"fetch",
|
|
4705
|
-
"find",
|
|
4706
|
-
"retrieve",
|
|
4707
|
-
"scroll",
|
|
4708
|
-
"peek",
|
|
4709
|
-
"discover",
|
|
4710
|
-
"recommend",
|
|
4711
|
-
"aggregate",
|
|
4712
|
-
"hybrid_search",
|
|
4713
|
-
"select"
|
|
4714
|
-
];
|
|
4715
|
-
var VECTOR_DB_NAMES = [
|
|
4716
|
-
"chroma",
|
|
4717
|
-
"pinecone",
|
|
4718
|
-
"weaviate",
|
|
4719
|
-
"qdrant",
|
|
4720
|
-
"milvus",
|
|
4721
|
-
"lancedb",
|
|
4722
|
-
"marqo"
|
|
4723
|
-
];
|
|
4724
|
-
|
|
4725
|
-
// src/span-kinds/mapping.ts
|
|
4726
|
-
var VALID_SPAN_KINDS = /* @__PURE__ */ new Set([
|
|
4727
|
-
"WORKFLOW",
|
|
4728
|
-
"AGENT",
|
|
4729
|
-
"CHAIN",
|
|
4730
|
-
"TOOL",
|
|
4731
|
-
"RETRIEVER",
|
|
4732
|
-
"EMBEDDING",
|
|
4733
|
-
"MCP_TOOL",
|
|
4734
|
-
"GUARDRAIL"
|
|
4735
|
-
]);
|
|
4736
|
-
var ALL_SPAN_KINDS = /* @__PURE__ */ new Set([
|
|
4737
|
-
...VALID_SPAN_KINDS,
|
|
4738
|
-
"LLM",
|
|
4739
|
-
"RERANKER",
|
|
4740
|
-
"EVALUATOR",
|
|
4741
|
-
"VECTOR_STORE"
|
|
4742
|
-
]);
|
|
4743
|
-
function inferSpanKindFromName(spanName) {
|
|
4744
|
-
const nameLower = spanName.toLowerCase();
|
|
4745
|
-
if (["openai", "anthropic", "cohere", "bedrock", "chat", "completion", "llm", "gemini", "google_genai"].some(
|
|
4746
|
-
(kw) => nameLower.includes(kw)
|
|
4747
|
-
)) {
|
|
4748
|
-
return "LLM";
|
|
4749
|
-
}
|
|
4750
|
-
if (nameLower.includes("embed")) {
|
|
4751
|
-
return "EMBEDDING";
|
|
4752
|
-
}
|
|
4753
|
-
if (VECTOR_DB_NAMES.some((db) => nameLower.includes(db))) {
|
|
4754
|
-
if (RETRIEVAL_OPS.some((kw) => nameLower.includes(kw))) {
|
|
4755
|
-
return "RETRIEVER";
|
|
4756
|
-
}
|
|
4757
|
-
return "VECTOR_STORE";
|
|
4758
|
-
}
|
|
4759
|
-
if (["retriev", "search", "query"].some((kw) => nameLower.includes(kw))) {
|
|
4760
|
-
return "RETRIEVER";
|
|
4761
|
-
}
|
|
4762
|
-
if (nameLower.includes("rerank")) {
|
|
4763
|
-
return "RERANKER";
|
|
4764
|
-
}
|
|
4765
|
-
if (nameLower.includes("agent")) {
|
|
4766
|
-
return "AGENT";
|
|
4767
|
-
}
|
|
4768
|
-
if (["tool", "function"].some((kw) => nameLower.includes(kw))) {
|
|
4769
|
-
return "TOOL";
|
|
4770
|
-
}
|
|
4771
|
-
if (["guardrail", "validate", "moderate", "safety"].some((kw) => nameLower.includes(kw))) {
|
|
4772
|
-
return "GUARDRAIL";
|
|
4773
|
-
}
|
|
4774
|
-
if (["evaluat", "score", "metric"].some((kw) => nameLower.includes(kw))) {
|
|
4775
|
-
return "EVALUATOR";
|
|
4776
|
-
}
|
|
4777
|
-
return "CHAIN";
|
|
4905
|
+
return withNeatlogsSpan(
|
|
4906
|
+
span2,
|
|
4907
|
+
() => spanCallback(span2),
|
|
4908
|
+
autoRoot.ctx,
|
|
4909
|
+
autoRoot.root
|
|
4910
|
+
);
|
|
4778
4911
|
}
|
|
4779
4912
|
|
|
4780
4913
|
// src/decorators/orchestration.ts
|
|
@@ -5294,6 +5427,7 @@ var neatlogs_telemetry_schema_default = {
|
|
|
5294
5427
|
"VECTOR_STORE",
|
|
5295
5428
|
"MEMORY",
|
|
5296
5429
|
"GUARDRAIL",
|
|
5430
|
+
"EVALUATOR",
|
|
5297
5431
|
"LOG",
|
|
5298
5432
|
"HTTP",
|
|
5299
5433
|
"UNKNOWN"
|
|
@@ -6722,6 +6856,7 @@ var neatlogs_telemetry_schema_default = {
|
|
|
6722
6856
|
"AGENT",
|
|
6723
6857
|
"CHAIN",
|
|
6724
6858
|
"TASK",
|
|
6859
|
+
"EVALUATOR",
|
|
6725
6860
|
"HTTP",
|
|
6726
6861
|
"UNKNOWN"
|
|
6727
6862
|
]
|
|
@@ -6885,6 +7020,7 @@ var neatlogs_telemetry_schema_default = {
|
|
|
6885
7020
|
"neatlogs.vector_store.*",
|
|
6886
7021
|
"neatlogs.memory.*",
|
|
6887
7022
|
"neatlogs.guardrail.*",
|
|
7023
|
+
"neatlogs.evaluator.*",
|
|
6888
7024
|
"neatlogs.mcp.*",
|
|
6889
7025
|
"neatlogs.code.*"
|
|
6890
7026
|
],
|
|
@@ -6968,7 +7104,7 @@ var TELEMETRY_CONFLICT_PRECEDENCE = Object.freeze(
|
|
|
6968
7104
|
);
|
|
6969
7105
|
|
|
6970
7106
|
// src/version.ts
|
|
6971
|
-
var __version__ = "1.1.
|
|
7107
|
+
var __version__ = "1.1.21";
|
|
6972
7108
|
|
|
6973
7109
|
// src/init.ts
|
|
6974
7110
|
var path2 = __toESM(require("path"));
|
|
@@ -6987,16 +7123,16 @@ var import_exporter_logs_otlp_proto = require("@opentelemetry/exporter-logs-otlp
|
|
|
6987
7123
|
var fs = __toESM(require("fs"));
|
|
6988
7124
|
var path = __toESM(require("path"));
|
|
6989
7125
|
var import_node_perf_hooks = require("perf_hooks");
|
|
6990
|
-
var
|
|
7126
|
+
var import_api7 = require("@opentelemetry/api");
|
|
6991
7127
|
|
|
6992
7128
|
// src/core/instrumentation-scope-parser.ts
|
|
6993
7129
|
var SCOPE_PATTERNS = {
|
|
6994
7130
|
// Neatlogs custom instrumentations
|
|
6995
7131
|
"@neatlogs/instrumentation-google-genai": { provider: "google", framework: "google_genai" },
|
|
6996
7132
|
"@neatlogs/instrumentation-mastra": { framework: "mastra" },
|
|
6997
|
-
"@neatlogs/instrumentation-ai-sdk": { framework: "
|
|
7133
|
+
"@neatlogs/instrumentation-ai-sdk": { framework: "vercel_ai_sdk" },
|
|
6998
7134
|
// Vercel AI SDK native scope (the `ai` package emits this directly)
|
|
6999
|
-
ai: { framework: "
|
|
7135
|
+
ai: { framework: "vercel_ai_sdk" },
|
|
7000
7136
|
// OpenInference instrumentations (npm @arizeai scope names)
|
|
7001
7137
|
"@arizeai/openinference-instrumentation-openai": { provider: "openai", framework: "openai" },
|
|
7002
7138
|
"@arizeai/openinference-instrumentation-anthropic": { provider: "anthropic", framework: "anthropic" },
|
|
@@ -7085,7 +7221,7 @@ function parseInstrumentationScope(scopeName) {
|
|
|
7085
7221
|
} else if (scopeLower.includes("dspy")) {
|
|
7086
7222
|
result.framework = "dspy";
|
|
7087
7223
|
} else if (scopeLower.includes("vercel-ai") || scopeLower.includes("ai-sdk")) {
|
|
7088
|
-
result.framework = "
|
|
7224
|
+
result.framework = "vercel_ai_sdk";
|
|
7089
7225
|
}
|
|
7090
7226
|
if (scopeLower.includes("openai")) {
|
|
7091
7227
|
result.provider = "openai";
|
|
@@ -8974,6 +9110,46 @@ function addVerificationMarkerResourceAttribute(attributes) {
|
|
|
8974
9110
|
if (marker) attributes[VERIFICATION_MARKER_KEY] = marker;
|
|
8975
9111
|
}
|
|
8976
9112
|
|
|
9113
|
+
// src/core/http-span.ts
|
|
9114
|
+
var import_api6 = require("@opentelemetry/api");
|
|
9115
|
+
var HTTP_SCOPE_PREFIXES = [
|
|
9116
|
+
"@opentelemetry/instrumentation-http",
|
|
9117
|
+
"@opentelemetry/instrumentation-fetch",
|
|
9118
|
+
"@opentelemetry/instrumentation-undici"
|
|
9119
|
+
];
|
|
9120
|
+
var HTTP_ATTRIBUTE_KEYS = [
|
|
9121
|
+
"http.method",
|
|
9122
|
+
"http.request.method",
|
|
9123
|
+
"http.url",
|
|
9124
|
+
"http.route",
|
|
9125
|
+
"url.full"
|
|
9126
|
+
];
|
|
9127
|
+
var SEMANTIC_AI_KINDS = /* @__PURE__ */ new Set([
|
|
9128
|
+
"WORKFLOW",
|
|
9129
|
+
"AGENT",
|
|
9130
|
+
"CHAIN",
|
|
9131
|
+
"TOOL",
|
|
9132
|
+
"RETRIEVER",
|
|
9133
|
+
"EMBEDDING",
|
|
9134
|
+
"GUARDRAIL",
|
|
9135
|
+
"LLM",
|
|
9136
|
+
"RERANKER",
|
|
9137
|
+
"VECTOR_STORE",
|
|
9138
|
+
"TASK",
|
|
9139
|
+
"EVALUATOR",
|
|
9140
|
+
"LOG",
|
|
9141
|
+
"MEMORY",
|
|
9142
|
+
"MCP_TOOL"
|
|
9143
|
+
]);
|
|
9144
|
+
function isHttpSpan(span2, attributes = span2.attributes ?? {}) {
|
|
9145
|
+
const resolvedKind = resolveExplicitSpanKind(attributes).toUpperCase();
|
|
9146
|
+
if (resolvedKind === "HTTP") return true;
|
|
9147
|
+
if (SEMANTIC_AI_KINDS.has(resolvedKind)) return false;
|
|
9148
|
+
const scopeName = span2.instrumentationLibrary.name ?? "";
|
|
9149
|
+
if (HTTP_SCOPE_PREFIXES.some((prefix) => scopeName.startsWith(prefix))) return true;
|
|
9150
|
+
return span2.kind === import_api6.SpanKind.CLIENT && HTTP_ATTRIBUTE_KEYS.some((key) => key in attributes);
|
|
9151
|
+
}
|
|
9152
|
+
|
|
8977
9153
|
// src/core/span-processor.ts
|
|
8978
9154
|
var logger11 = getLogger();
|
|
8979
9155
|
function resolveLogFilePath(configuredPath) {
|
|
@@ -9245,6 +9421,7 @@ var NeatlogsSpanProcessor = class {
|
|
|
9245
9421
|
onEnd(span2) {
|
|
9246
9422
|
this._activeSpans.delete(span2.spanContext().spanId);
|
|
9247
9423
|
if (this._closed) return;
|
|
9424
|
+
if (isHttpSpan(span2)) return;
|
|
9248
9425
|
if (span2.name === "neatlogs.trace.complete") {
|
|
9249
9426
|
const markerData = spanToDict(span2, { includeScope: true });
|
|
9250
9427
|
markerData.resource = { attributes: markerData.resource };
|
|
@@ -9361,7 +9538,7 @@ var NeatlogsSpanProcessor = class {
|
|
|
9361
9538
|
attributes: unifiedAttrs,
|
|
9362
9539
|
resource: { attributes: resourceAttrs },
|
|
9363
9540
|
status: {
|
|
9364
|
-
code:
|
|
9541
|
+
code: import_api7.SpanStatusCode[span2.status.code] ?? String(span2.status.code),
|
|
9365
9542
|
description: span2.status.message ?? null
|
|
9366
9543
|
},
|
|
9367
9544
|
links: span2.links.map((link) => ({
|
|
@@ -9404,6 +9581,7 @@ var NeatlogsSpanProcessor = class {
|
|
|
9404
9581
|
const maskResult = scheduleMask(span2, spanData, this.mask ?? null);
|
|
9405
9582
|
const pending = maskResult.then((maskedSpanData) => {
|
|
9406
9583
|
if (maskedSpanData === null) return;
|
|
9584
|
+
if (isHttpSpan(span2, maskedSpanData.attributes ?? {})) return;
|
|
9407
9585
|
if (this._processedLogStream && !this._processedLogStream.destroyed) {
|
|
9408
9586
|
try {
|
|
9409
9587
|
this._processedLogStream.write(JSON.stringify(maskedSpanData) + "\n");
|
|
@@ -9483,9 +9661,9 @@ var NeatlogsSpanProcessor = class {
|
|
|
9483
9661
|
_markInterrupted(span2, cleanReason) {
|
|
9484
9662
|
span2.setAttribute("neatlogs.trace.interrupted", true);
|
|
9485
9663
|
span2.setAttribute("neatlogs.trace.termination.reason", cleanReason);
|
|
9486
|
-
if (span2.status.code ===
|
|
9664
|
+
if (span2.status.code === import_api7.SpanStatusCode.UNSET) {
|
|
9487
9665
|
span2.setStatus({
|
|
9488
|
-
code:
|
|
9666
|
+
code: import_api7.SpanStatusCode.ERROR,
|
|
9489
9667
|
message: `Interrupted during ${cleanReason}`
|
|
9490
9668
|
});
|
|
9491
9669
|
}
|
|
@@ -9500,10 +9678,10 @@ var NeatlogsSpanProcessor = class {
|
|
|
9500
9678
|
traceId: rootSpan.spanContext().traceId,
|
|
9501
9679
|
spanId: rootSpan.spanContext().spanId,
|
|
9502
9680
|
isRemote: false,
|
|
9503
|
-
traceFlags:
|
|
9681
|
+
traceFlags: import_api7.TraceFlags.SAMPLED
|
|
9504
9682
|
};
|
|
9505
|
-
const wrappedSpan =
|
|
9506
|
-
const ctx =
|
|
9683
|
+
const wrappedSpan = import_api7.trace.wrapSpanContext(spanCtx);
|
|
9684
|
+
const ctx = import_api7.trace.setSpan(import_api7.ROOT_CONTEXT, wrappedSpan);
|
|
9507
9685
|
const marker = markerTracer.startSpan("neatlogs.trace.complete", void 0, ctx);
|
|
9508
9686
|
marker.setAttribute("neatlogs.trace.complete", true);
|
|
9509
9687
|
marker.setAttribute("neatlogs.internal", true);
|
|
@@ -9672,7 +9850,8 @@ var CompletionMarkerSpanProcessor = class {
|
|
|
9672
9850
|
onStart(_span, _parentContext) {
|
|
9673
9851
|
}
|
|
9674
9852
|
onEnd(span2) {
|
|
9675
|
-
if (this.closed || span2.name === "neatlogs.trace.complete" || span2.parentSpanId)
|
|
9853
|
+
if (this.closed || span2.name === "neatlogs.trace.complete" || span2.parentSpanId || isHttpSpan(span2))
|
|
9854
|
+
return;
|
|
9676
9855
|
if (!this.source.ownsSpan(span2)) return;
|
|
9677
9856
|
const task = this.source.whenMaskComplete(span2).then((eligible) => {
|
|
9678
9857
|
if (!eligible || this.closed) return;
|
|
@@ -9709,7 +9888,7 @@ var CompletionMarkerSpanProcessor = class {
|
|
|
9709
9888
|
};
|
|
9710
9889
|
|
|
9711
9890
|
// src/core/filtering-exporter.ts
|
|
9712
|
-
var
|
|
9891
|
+
var import_api8 = require("@opentelemetry/api");
|
|
9713
9892
|
var import_core = require("@opentelemetry/core");
|
|
9714
9893
|
var import_resources = require("@opentelemetry/resources");
|
|
9715
9894
|
var MEDIA_RESOLUTION_CONCURRENCY = 4;
|
|
@@ -9748,7 +9927,7 @@ function toAttributes(value) {
|
|
|
9748
9927
|
function statusCode(value, fallback) {
|
|
9749
9928
|
if (typeof value === "number") return value;
|
|
9750
9929
|
if (typeof value === "string") {
|
|
9751
|
-
const resolved =
|
|
9930
|
+
const resolved = import_api8.SpanStatusCode[value];
|
|
9752
9931
|
if (typeof resolved === "number") return resolved;
|
|
9753
9932
|
}
|
|
9754
9933
|
return fallback;
|
|
@@ -9812,6 +9991,10 @@ var FilteringExporter = class {
|
|
|
9812
9991
|
_onPrepared;
|
|
9813
9992
|
export(spans, resultCallback) {
|
|
9814
9993
|
void mapWithConcurrency(spans, MEDIA_RESOLUTION_CONCURRENCY, async (span2) => {
|
|
9994
|
+
if (isHttpSpan(span2)) {
|
|
9995
|
+
discardPendingMedia(span2);
|
|
9996
|
+
return { span: null, mediaReady: true };
|
|
9997
|
+
}
|
|
9815
9998
|
if (span2.instrumentationLibrary.name === "next.js") {
|
|
9816
9999
|
discardPendingMedia(span2);
|
|
9817
10000
|
this.diagnostics?.recordFrameworkSpanDrop();
|
|
@@ -9832,6 +10015,11 @@ var FilteringExporter = class {
|
|
|
9832
10015
|
...masked.attributes && typeof masked.attributes === "object" ? masked.attributes : {}
|
|
9833
10016
|
};
|
|
9834
10017
|
const maskedData = { ...masked, attributes };
|
|
10018
|
+
const maskedSpan = maskedReadableSpan(span2, maskedData);
|
|
10019
|
+
if (isHttpSpan(maskedSpan)) {
|
|
10020
|
+
discardPendingMedia(span2);
|
|
10021
|
+
return { span: null, mediaReady: true };
|
|
10022
|
+
}
|
|
9835
10023
|
captureMediaInSnapshot(
|
|
9836
10024
|
span2,
|
|
9837
10025
|
maskedData,
|
|
@@ -10299,7 +10487,7 @@ var DeliveryDiagnostics = class {
|
|
|
10299
10487
|
};
|
|
10300
10488
|
|
|
10301
10489
|
// src/core/observable-batch-processors.ts
|
|
10302
|
-
var
|
|
10490
|
+
var import_api9 = require("@opentelemetry/api");
|
|
10303
10491
|
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
10304
10492
|
var import_sdk_logs = require("@opentelemetry/sdk-logs");
|
|
10305
10493
|
var ObservableBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProcessor {
|
|
@@ -10310,7 +10498,7 @@ var ObservableBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpan
|
|
|
10310
10498
|
diagnostics;
|
|
10311
10499
|
onEnd(span2) {
|
|
10312
10500
|
const state = this;
|
|
10313
|
-
if ((span2.spanContext().traceFlags &
|
|
10501
|
+
if ((span2.spanContext().traceFlags & import_api9.TraceFlags.SAMPLED) !== 0 && state._finishedSpans.length >= state._maxQueueSize) {
|
|
10314
10502
|
discardPendingMedia(span2);
|
|
10315
10503
|
this.diagnostics.recordQueueDrop("span");
|
|
10316
10504
|
}
|
|
@@ -10344,7 +10532,7 @@ function _setOtelLogger(otelLogger, debug) {
|
|
|
10344
10532
|
}
|
|
10345
10533
|
|
|
10346
10534
|
// src/prompt/client.ts
|
|
10347
|
-
var
|
|
10535
|
+
var import_api10 = require("@opentelemetry/api");
|
|
10348
10536
|
var import_core4 = require("@opentelemetry/core");
|
|
10349
10537
|
var PromptClientError = class extends Error {
|
|
10350
10538
|
constructor(message) {
|
|
@@ -11057,8 +11245,8 @@ var PromptClient = class _PromptClient {
|
|
|
11057
11245
|
let contextResult;
|
|
11058
11246
|
try {
|
|
11059
11247
|
try {
|
|
11060
|
-
const suppressedContext = (0, import_core4.suppressTracing)(
|
|
11061
|
-
contextResult =
|
|
11248
|
+
const suppressedContext = (0, import_core4.suppressTracing)(import_api10.context.active());
|
|
11249
|
+
contextResult = import_api10.context.with(suppressedContext, startTransport);
|
|
11062
11250
|
} catch {
|
|
11063
11251
|
}
|
|
11064
11252
|
if (contextResult && contextResult !== transportPromise) {
|
|
@@ -11135,18 +11323,6 @@ function closeSharedClient() {
|
|
|
11135
11323
|
function _resetMastraCache() {
|
|
11136
11324
|
}
|
|
11137
11325
|
|
|
11138
|
-
// src/errors.ts
|
|
11139
|
-
var NeatlogsConfigurationError = class extends TypeError {
|
|
11140
|
-
code;
|
|
11141
|
-
option;
|
|
11142
|
-
constructor(code, option, message) {
|
|
11143
|
-
super(message);
|
|
11144
|
-
this.name = "NeatlogsConfigurationError";
|
|
11145
|
-
this.code = code;
|
|
11146
|
-
this.option = option;
|
|
11147
|
-
}
|
|
11148
|
-
};
|
|
11149
|
-
|
|
11150
11326
|
// src/core/deadline.ts
|
|
11151
11327
|
async function runByDeadline(operation, deadlineMs) {
|
|
11152
11328
|
const remaining = Math.max(0, deadlineMs - Date.now());
|
|
@@ -11247,6 +11423,24 @@ var INIT_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
11247
11423
|
"piiSpanTypes",
|
|
11248
11424
|
"uploadAuthority"
|
|
11249
11425
|
]);
|
|
11426
|
+
function resolveInitEndpoint(endpoint) {
|
|
11427
|
+
const explicit = (endpoint ?? "").trim();
|
|
11428
|
+
if (explicit) return explicit;
|
|
11429
|
+
const fromEnv = (process.env.NEATLOGS_ENDPOINT ?? "").trim();
|
|
11430
|
+
return fromEnv || DEFAULT_INGEST_ENDPOINT;
|
|
11431
|
+
}
|
|
11432
|
+
function resolveIngestBaseUrl(endpoint) {
|
|
11433
|
+
const parsed = new URL(endpoint.trim());
|
|
11434
|
+
const path3 = parsed.pathname.replace(/\/+$/, "");
|
|
11435
|
+
if (path3 !== "" && path3 !== "/v1/traces") {
|
|
11436
|
+
throw new NeatlogsConfigurationError(
|
|
11437
|
+
"INVALID_ENDPOINT",
|
|
11438
|
+
"endpoint",
|
|
11439
|
+
"endpoint must be a base URL or an OTLP traces URL ending in /v1/traces."
|
|
11440
|
+
);
|
|
11441
|
+
}
|
|
11442
|
+
return parsed.origin;
|
|
11443
|
+
}
|
|
11250
11444
|
function validateInitOptions(options) {
|
|
11251
11445
|
const raw = options;
|
|
11252
11446
|
if (Object.prototype.hasOwnProperty.call(raw, "instrumentations")) {
|
|
@@ -11330,8 +11524,13 @@ function stableValue(value, ancestors = /* @__PURE__ */ new WeakSet(), location
|
|
|
11330
11524
|
ancestors.delete(value);
|
|
11331
11525
|
}
|
|
11332
11526
|
}
|
|
11527
|
+
function resolveApiKey(apiKey) {
|
|
11528
|
+
const explicit = (apiKey ?? "").trim();
|
|
11529
|
+
if (explicit) return explicit;
|
|
11530
|
+
return (process.env.NEATLOGS_API_KEY ?? "").trim();
|
|
11531
|
+
}
|
|
11333
11532
|
function initIdentity(options) {
|
|
11334
|
-
const apiKey = (options.apiKey
|
|
11533
|
+
const apiKey = resolveApiKey(options.apiKey);
|
|
11335
11534
|
const apiKeyDigest = (0, import_node_crypto4.createHash)("sha256").update(apiKey).digest("hex");
|
|
11336
11535
|
const serialized = stableValue({
|
|
11337
11536
|
apiKeyDigest,
|
|
@@ -11351,7 +11550,7 @@ function initIdentity(options) {
|
|
|
11351
11550
|
captureLogs: options.captureLogs ?? false,
|
|
11352
11551
|
pii: options.pii ?? null,
|
|
11353
11552
|
version: options.version ?? null,
|
|
11354
|
-
endpoint: options.endpoint
|
|
11553
|
+
endpoint: resolveInitEndpoint(options.endpoint),
|
|
11355
11554
|
batchSize: options.batchSize ?? 100,
|
|
11356
11555
|
flushInterval: options.flushInterval ?? 5,
|
|
11357
11556
|
piiEnabled: options.piiEnabled ?? null,
|
|
@@ -11431,12 +11630,7 @@ async function _performInit(options) {
|
|
|
11431
11630
|
);
|
|
11432
11631
|
}
|
|
11433
11632
|
_deliveryDiagnostics = new DeliveryDiagnostics();
|
|
11434
|
-
let resolvedKey;
|
|
11435
|
-
if (options.apiKey && options.apiKey.trim()) {
|
|
11436
|
-
resolvedKey = options.apiKey.trim();
|
|
11437
|
-
} else {
|
|
11438
|
-
resolvedKey = (process.env.NEATLOGS_API_KEY ?? "").trim();
|
|
11439
|
-
}
|
|
11633
|
+
let resolvedKey = resolveApiKey(options.apiKey);
|
|
11440
11634
|
let disableExportResolved = !!options.disableExport || ["true", "1", "yes"].includes(
|
|
11441
11635
|
(process.env.NEATLOGS_DISABLE_EXPORT ?? "").toLowerCase()
|
|
11442
11636
|
);
|
|
@@ -11457,8 +11651,8 @@ async function _performInit(options) {
|
|
|
11457
11651
|
}
|
|
11458
11652
|
_debugMode2 = options.debug ?? false;
|
|
11459
11653
|
const resolvedWorkflowName = _resolveWorkflowName(options.workflowName);
|
|
11460
|
-
const endpoint = options.endpoint
|
|
11461
|
-
const baseUrl =
|
|
11654
|
+
const endpoint = resolveInitEndpoint(options.endpoint);
|
|
11655
|
+
const baseUrl = resolveIngestBaseUrl(endpoint);
|
|
11462
11656
|
const uploadAuthority = disableExportResolved ? new DisabledUploadAuthority("export_disabled") : resolveUploadAuthority(
|
|
11463
11657
|
options.uploadAuthority,
|
|
11464
11658
|
process.env.NEATLOGS_UPLOADS_ENABLED,
|
|
@@ -12178,6 +12372,36 @@ var INGESTION_STAGES = /* @__PURE__ */ new Set([
|
|
|
12178
12372
|
]);
|
|
12179
12373
|
var INGESTION_STATES = /* @__PURE__ */ new Set(["processing", "failed", "succeeded"]);
|
|
12180
12374
|
var SAFE_FAILURE_CODE = /^[A-Z0-9_]{1,64}$/;
|
|
12375
|
+
var PROBE_FAILURE = {
|
|
12376
|
+
AUTH_FAILED: {
|
|
12377
|
+
remediationCode: "CHECK_INGEST_CREDENTIAL",
|
|
12378
|
+
message: "The project key was rejected by the existing trace API"
|
|
12379
|
+
},
|
|
12380
|
+
BACKEND_PROBE_UNAVAILABLE: {
|
|
12381
|
+
remediationCode: "CHECK_TRACE_ENDPOINT",
|
|
12382
|
+
message: "The existing trace ingestion or read path is unavailable"
|
|
12383
|
+
},
|
|
12384
|
+
TRACE_READBACK_TIMEOUT: {
|
|
12385
|
+
remediationCode: "WAIT_FOR_TRACE",
|
|
12386
|
+
message: "Timed out waiting for the exact Doctor trace"
|
|
12387
|
+
},
|
|
12388
|
+
INGESTION_PIPELINE_FAILED: {
|
|
12389
|
+
remediationCode: "CONTACT_SUPPORT",
|
|
12390
|
+
message: "Trace ingestion reported a terminal pipeline failure"
|
|
12391
|
+
},
|
|
12392
|
+
BACKEND_HTTP_ERROR: {
|
|
12393
|
+
remediationCode: "CHECK_TRACE_ENDPOINT",
|
|
12394
|
+
message: "The existing trace read path returned an unexpected HTTP status"
|
|
12395
|
+
},
|
|
12396
|
+
BACKEND_CONNECTION_FAILED: {
|
|
12397
|
+
remediationCode: "CHECK_TRACE_ENDPOINT",
|
|
12398
|
+
message: "Could not connect to the existing trace read path"
|
|
12399
|
+
},
|
|
12400
|
+
TRACE_READBACK_INVALID: {
|
|
12401
|
+
remediationCode: "CONTACT_SUPPORT",
|
|
12402
|
+
message: "Trace read-back returned an invalid response"
|
|
12403
|
+
}
|
|
12404
|
+
};
|
|
12181
12405
|
var ProbeReadError = class extends Error {
|
|
12182
12406
|
constructor(reasonCode, message, details) {
|
|
12183
12407
|
super(message);
|
|
@@ -12297,7 +12521,7 @@ function validateLocalFixture(traceId) {
|
|
|
12297
12521
|
check("controlled_fixture_bounds", stats.droppedSpans === 0, "CONTROLLED_BOUNDS_VALID", "CONTROLLED_CAPTURE_TRUNCATED", "REDUCE_DIAGNOSTIC_CAPTURE", "Doctor stayed inside the bounded capture budget")
|
|
12298
12522
|
];
|
|
12299
12523
|
}
|
|
12300
|
-
async function withTimeout(operation, timeoutMs, onTimeout) {
|
|
12524
|
+
async function withTimeout(operation, timeoutMs, onTimeout, timeoutReason = "BACKEND_PROBE_UNAVAILABLE") {
|
|
12301
12525
|
let timer;
|
|
12302
12526
|
try {
|
|
12303
12527
|
return await Promise.race([
|
|
@@ -12305,7 +12529,7 @@ async function withTimeout(operation, timeoutMs, onTimeout) {
|
|
|
12305
12529
|
new Promise((_resolve, reject) => {
|
|
12306
12530
|
timer = setTimeout(() => {
|
|
12307
12531
|
onTimeout?.();
|
|
12308
|
-
reject(new ProbeReadError(
|
|
12532
|
+
reject(new ProbeReadError(timeoutReason, "Doctor operation timed out"));
|
|
12309
12533
|
}, Math.max(1, timeoutMs));
|
|
12310
12534
|
})
|
|
12311
12535
|
]);
|
|
@@ -12360,7 +12584,7 @@ async function localResult(env, options = {}) {
|
|
|
12360
12584
|
markDoctorSpan("LLM");
|
|
12361
12585
|
const output = { text: "generated diagnostic output" };
|
|
12362
12586
|
llm.setAttribute("output.value", JSON.stringify(output));
|
|
12363
|
-
llm.setStatus({ code:
|
|
12587
|
+
llm.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
12364
12588
|
llm.end();
|
|
12365
12589
|
return output;
|
|
12366
12590
|
}
|
|
@@ -12379,7 +12603,7 @@ async function localResult(env, options = {}) {
|
|
|
12379
12603
|
const output = await diagnosticTool({ value: 1 });
|
|
12380
12604
|
const result2 = { result: output };
|
|
12381
12605
|
setTraceOutput(result2);
|
|
12382
|
-
root.setStatus({ code:
|
|
12606
|
+
root.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
12383
12607
|
return result2;
|
|
12384
12608
|
});
|
|
12385
12609
|
let flushed = false;
|
|
@@ -12493,12 +12717,13 @@ function failedProbeResult(local, reasonCode, details) {
|
|
|
12493
12717
|
};
|
|
12494
12718
|
}
|
|
12495
12719
|
function failedProbeTransportCheck(reasonCode, details) {
|
|
12720
|
+
const failure2 = PROBE_FAILURE[reasonCode];
|
|
12496
12721
|
return {
|
|
12497
12722
|
name: "probe_transport",
|
|
12498
12723
|
status: "fail",
|
|
12499
12724
|
reason_code: reasonCode,
|
|
12500
|
-
remediation_code:
|
|
12501
|
-
message:
|
|
12725
|
+
remediation_code: failure2.remediationCode,
|
|
12726
|
+
message: failure2.message,
|
|
12502
12727
|
...details ? { details } : {}
|
|
12503
12728
|
};
|
|
12504
12729
|
}
|
|
@@ -12576,16 +12801,23 @@ function human(result) {
|
|
|
12576
12801
|
if (result.note) lines.push(result.note);
|
|
12577
12802
|
return lines.join("\n");
|
|
12578
12803
|
}
|
|
12804
|
+
function readbackTimeoutReason(remainingMs, requestTimeoutMs) {
|
|
12805
|
+
return remainingMs <= requestTimeoutMs ? "TRACE_READBACK_TIMEOUT" : "BACKEND_CONNECTION_FAILED";
|
|
12806
|
+
}
|
|
12807
|
+
function responseBodyFailureReason(status, remainingMs, requestTimeoutMs) {
|
|
12808
|
+
return status === 409 || status >= 200 && status < 300 && status !== 202 ? "TRACE_READBACK_INVALID" : readbackTimeoutReason(remainingMs, requestTimeoutMs);
|
|
12809
|
+
}
|
|
12579
12810
|
async function boundedFetch(io, input, initOptions, deadline) {
|
|
12580
12811
|
const remaining = deadline - Date.now();
|
|
12581
12812
|
if (remaining <= 0) {
|
|
12582
|
-
throw new ProbeReadError("
|
|
12813
|
+
throw new ProbeReadError("TRACE_READBACK_TIMEOUT", "Doctor probe deadline expired");
|
|
12583
12814
|
}
|
|
12584
12815
|
const controller = new AbortController();
|
|
12585
12816
|
return withTimeout(
|
|
12586
12817
|
() => io.fetch(input, { ...initOptions, signal: controller.signal }),
|
|
12587
12818
|
Math.min(io.requestTimeoutMs, remaining),
|
|
12588
|
-
() => controller.abort()
|
|
12819
|
+
() => controller.abort(),
|
|
12820
|
+
readbackTimeoutReason(remaining, io.requestTimeoutMs)
|
|
12589
12821
|
);
|
|
12590
12822
|
}
|
|
12591
12823
|
async function discardResponseBody(response, reader) {
|
|
@@ -12607,7 +12839,7 @@ async function boundedJson2(response, io, deadline) {
|
|
|
12607
12839
|
const remaining = deadline - Date.now();
|
|
12608
12840
|
if (remaining <= 0) {
|
|
12609
12841
|
await discardResponseBody(response);
|
|
12610
|
-
throw new ProbeReadError("
|
|
12842
|
+
throw new ProbeReadError("TRACE_READBACK_TIMEOUT", "Doctor probe deadline expired");
|
|
12611
12843
|
}
|
|
12612
12844
|
const contentLength = Number(response.headers.get("content-length"));
|
|
12613
12845
|
if (Number.isFinite(contentLength) && contentLength > MAX_READBACK_BYTES) {
|
|
@@ -12642,9 +12874,17 @@ async function boundedJson2(response, io, deadline) {
|
|
|
12642
12874
|
}
|
|
12643
12875
|
}, Math.min(io.requestTimeoutMs, remaining), () => {
|
|
12644
12876
|
void discardResponseBody(response, reader);
|
|
12645
|
-
}
|
|
12877
|
+
}, responseBodyFailureReason(
|
|
12878
|
+
response.status,
|
|
12879
|
+
remaining,
|
|
12880
|
+
io.requestTimeoutMs
|
|
12881
|
+
)).catch(async (error) => {
|
|
12646
12882
|
await discardResponseBody(response, reader);
|
|
12647
|
-
|
|
12883
|
+
if (error instanceof ProbeReadError) throw error;
|
|
12884
|
+
throw new ProbeReadError(
|
|
12885
|
+
"BACKEND_CONNECTION_FAILED",
|
|
12886
|
+
"Trace read-back response could not be read"
|
|
12887
|
+
);
|
|
12648
12888
|
});
|
|
12649
12889
|
}
|
|
12650
12890
|
function usage() {
|
|
@@ -12749,10 +12989,11 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12749
12989
|
"x-neatlogs-doctor": DOCTOR_MARKER_VERSION
|
|
12750
12990
|
}
|
|
12751
12991
|
}, deadline);
|
|
12752
|
-
} catch {
|
|
12992
|
+
} catch (error) {
|
|
12993
|
+
if (error instanceof ProbeReadError) throw error;
|
|
12753
12994
|
throw new ProbeReadError(
|
|
12754
|
-
"
|
|
12755
|
-
"
|
|
12995
|
+
"BACKEND_CONNECTION_FAILED",
|
|
12996
|
+
"Could not connect to the existing trace read path",
|
|
12756
12997
|
lastDiagnostics
|
|
12757
12998
|
);
|
|
12758
12999
|
}
|
|
@@ -12760,7 +13001,7 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12760
13001
|
const value = await boundedJson2(response, io, deadline);
|
|
12761
13002
|
if (!value || typeof value !== "object") {
|
|
12762
13003
|
throw new ProbeReadError(
|
|
12763
|
-
"
|
|
13004
|
+
"TRACE_READBACK_INVALID",
|
|
12764
13005
|
"Trace read-back returned an invalid response"
|
|
12765
13006
|
);
|
|
12766
13007
|
}
|
|
@@ -12773,12 +13014,23 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12773
13014
|
throw new ProbeReadError("AUTH_FAILED", "Trace read-back rejected the project key");
|
|
12774
13015
|
}
|
|
12775
13016
|
if ([202, 404, 409].includes(response.status)) {
|
|
12776
|
-
const value = await boundedJson2(response, io, deadline)
|
|
13017
|
+
const value = await boundedJson2(response, io, deadline);
|
|
12777
13018
|
const currentDiagnostics = ingestionDiagnosticDetails(value);
|
|
12778
13019
|
if (currentDiagnostics) lastDiagnostics = currentDiagnostics;
|
|
12779
13020
|
if (response.status === 409) {
|
|
13021
|
+
const terminalValue = objectValue(value);
|
|
13022
|
+
const isDlq = terminalValue.finalizationStatus === "dlq";
|
|
13023
|
+
const hasDiagnostics = Object.hasOwn(terminalValue, "ingestionDiagnostics");
|
|
13024
|
+
const validDlq = typeof terminalValue.error === "string" && (terminalValue.message === void 0 || typeof terminalValue.message === "string") && (!hasDiagnostics || currentDiagnostics !== void 0);
|
|
13025
|
+
const validReceipt = currentDiagnostics?.ingestion_state === "failed";
|
|
13026
|
+
if (isDlq ? !validDlq : !validReceipt) {
|
|
13027
|
+
throw new ProbeReadError(
|
|
13028
|
+
"TRACE_READBACK_INVALID",
|
|
13029
|
+
"Trace read-back returned an invalid terminal receipt"
|
|
13030
|
+
);
|
|
13031
|
+
}
|
|
12780
13032
|
throw new ProbeReadError(
|
|
12781
|
-
"
|
|
13033
|
+
"INGESTION_PIPELINE_FAILED",
|
|
12782
13034
|
"Trace ingestion reported a terminal failure",
|
|
12783
13035
|
currentDiagnostics
|
|
12784
13036
|
);
|
|
@@ -12786,7 +13038,7 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12786
13038
|
} else {
|
|
12787
13039
|
await discardResponseBody(response);
|
|
12788
13040
|
throw new ProbeReadError(
|
|
12789
|
-
"
|
|
13041
|
+
"BACKEND_HTTP_ERROR",
|
|
12790
13042
|
`Trace read-back failed with HTTP ${response.status}`,
|
|
12791
13043
|
response.status >= 500 ? lastDiagnostics : void 0
|
|
12792
13044
|
);
|
|
@@ -12796,7 +13048,7 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12796
13048
|
}
|
|
12797
13049
|
if (!persisted) {
|
|
12798
13050
|
throw new ProbeReadError(
|
|
12799
|
-
"
|
|
13051
|
+
"TRACE_READBACK_TIMEOUT",
|
|
12800
13052
|
"Timed out waiting for the exact Doctor trace",
|
|
12801
13053
|
lastDiagnostics
|
|
12802
13054
|
);
|
|
@@ -12805,7 +13057,7 @@ async function runDoctorCli(argv, overrides = {}) {
|
|
|
12805
13057
|
io.stdout(json ? JSON.stringify(result, null, 2) : human(result));
|
|
12806
13058
|
return result.status === "pass" ? 0 : 3;
|
|
12807
13059
|
} catch (error) {
|
|
12808
|
-
const reason = error instanceof ProbeReadError
|
|
13060
|
+
const reason = error instanceof ProbeReadError ? error.reasonCode : "BACKEND_PROBE_UNAVAILABLE";
|
|
12809
13061
|
const result = local ? failedProbeResult(
|
|
12810
13062
|
local,
|
|
12811
13063
|
reason,
|