@frontmcp/observability 1.9.1-rc.3 → 1.9.2
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/esm/index.mjs +189 -101
- package/esm/package.json +3 -3
- package/index.js +196 -108
- package/package.json +3 -3
- package/plugin/observability.plugin.d.ts +3 -0
- package/process-stats/process-stats.collector.d.ts +1 -1
- package/request-log/request-log.hooks.d.ts +28 -0
- package/telemetry/telemetry.context-extension.d.ts +3 -3
package/esm/index.mjs
CHANGED
|
@@ -332,7 +332,7 @@ import {
|
|
|
332
332
|
AgentCallHook,
|
|
333
333
|
DynamicPlugin,
|
|
334
334
|
FlowHooksOf,
|
|
335
|
-
FRONTMCP_CONTEXT,
|
|
335
|
+
FRONTMCP_CONTEXT as FRONTMCP_CONTEXT2,
|
|
336
336
|
HttpHook,
|
|
337
337
|
ListResourcesHook,
|
|
338
338
|
ListResourceTemplatesHook,
|
|
@@ -772,15 +772,13 @@ var RequestLogCollector = class {
|
|
|
772
772
|
}
|
|
773
773
|
};
|
|
774
774
|
|
|
775
|
-
// libs/observability/src/
|
|
776
|
-
var REQUEST_LOG_COLLECTOR = /* @__PURE__ */ Symbol.for("frontmcp:observability:request-log-collector");
|
|
777
|
-
|
|
778
|
-
// libs/observability/src/telemetry/telemetry.accessor.ts
|
|
775
|
+
// libs/observability/src/plugin/observability.hooks.ts
|
|
779
776
|
import {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
trace as
|
|
777
|
+
context as otelContext3,
|
|
778
|
+
SpanKind as SpanKind11,
|
|
779
|
+
trace as trace3
|
|
783
780
|
} from "@opentelemetry/api";
|
|
781
|
+
import { sha256Hex } from "@frontmcp/utils";
|
|
784
782
|
|
|
785
783
|
// libs/observability/src/otel/otel.types.ts
|
|
786
784
|
var McpAttributes = {
|
|
@@ -895,43 +893,6 @@ var EnduserAttributes = {
|
|
|
895
893
|
SCOPE: "enduser.scope"
|
|
896
894
|
};
|
|
897
895
|
|
|
898
|
-
// libs/observability/src/otel/trace-context-bridge.ts
|
|
899
|
-
import {
|
|
900
|
-
TraceFlags,
|
|
901
|
-
trace,
|
|
902
|
-
context as otelContext
|
|
903
|
-
} from "@opentelemetry/api";
|
|
904
|
-
function frontmcpToOTelSpanContext(tc) {
|
|
905
|
-
return {
|
|
906
|
-
traceId: tc.traceId,
|
|
907
|
-
spanId: tc.parentId,
|
|
908
|
-
traceFlags: tc.traceFlags & TraceFlags.SAMPLED ? TraceFlags.SAMPLED : TraceFlags.NONE,
|
|
909
|
-
isRemote: true
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
function otelToFrontmcpContext(sc) {
|
|
913
|
-
const flags = sc.traceFlags.toString(16).padStart(2, "0");
|
|
914
|
-
return {
|
|
915
|
-
traceId: sc.traceId,
|
|
916
|
-
parentId: sc.spanId,
|
|
917
|
-
traceFlags: sc.traceFlags,
|
|
918
|
-
raw: `00-${sc.traceId}-${sc.spanId}-${flags}`
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
function createOTelContextFromTrace(tc) {
|
|
922
|
-
const spanContext = frontmcpToOTelSpanContext(tc);
|
|
923
|
-
const span = trace.wrapSpanContext(spanContext);
|
|
924
|
-
return trace.setSpan(otelContext.active(), span);
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
// libs/observability/src/plugin/observability.hooks.ts
|
|
928
|
-
import {
|
|
929
|
-
context as otelContext3,
|
|
930
|
-
SpanKind as SpanKind11,
|
|
931
|
-
trace as trace3
|
|
932
|
-
} from "@opentelemetry/api";
|
|
933
|
-
import { sha256Hex } from "@frontmcp/utils";
|
|
934
|
-
|
|
935
896
|
// libs/observability/src/otel/spans/auth.span.ts
|
|
936
897
|
import { SpanKind as SpanKind2 } from "@opentelemetry/api";
|
|
937
898
|
|
|
@@ -939,11 +900,11 @@ import { SpanKind as SpanKind2 } from "@opentelemetry/api";
|
|
|
939
900
|
import {
|
|
940
901
|
SpanKind,
|
|
941
902
|
SpanStatusCode,
|
|
942
|
-
context as
|
|
943
|
-
trace
|
|
903
|
+
context as otelContext,
|
|
904
|
+
trace
|
|
944
905
|
} from "@opentelemetry/api";
|
|
945
906
|
function startSpan(tracer, options) {
|
|
946
|
-
const parentCtx = options.parentContext ??
|
|
907
|
+
const parentCtx = options.parentContext ?? otelContext.active();
|
|
947
908
|
const span = tracer.startSpan(
|
|
948
909
|
options.name,
|
|
949
910
|
{
|
|
@@ -952,7 +913,7 @@ function startSpan(tracer, options) {
|
|
|
952
913
|
},
|
|
953
914
|
parentCtx
|
|
954
915
|
);
|
|
955
|
-
const spanContext =
|
|
916
|
+
const spanContext = trace.setSpan(parentCtx, span);
|
|
956
917
|
return { span, context: spanContext };
|
|
957
918
|
}
|
|
958
919
|
function endSpanOk(span) {
|
|
@@ -969,7 +930,7 @@ function endSpanError(span, error) {
|
|
|
969
930
|
}
|
|
970
931
|
async function withSpan(tracer, options, fn) {
|
|
971
932
|
const { span, context: spanContext } = startSpan(tracer, options);
|
|
972
|
-
return
|
|
933
|
+
return otelContext.with(spanContext, async () => {
|
|
973
934
|
try {
|
|
974
935
|
const result = await fn(span);
|
|
975
936
|
endSpanOk(span);
|
|
@@ -1184,6 +1145,35 @@ function setTransportRequestType(span, requestType) {
|
|
|
1184
1145
|
span.setAttribute(FrontMcpAttributes.TRANSPORT_REQUEST_TYPE, requestType);
|
|
1185
1146
|
}
|
|
1186
1147
|
|
|
1148
|
+
// libs/observability/src/otel/trace-context-bridge.ts
|
|
1149
|
+
import {
|
|
1150
|
+
TraceFlags,
|
|
1151
|
+
trace as trace2,
|
|
1152
|
+
context as otelContext2
|
|
1153
|
+
} from "@opentelemetry/api";
|
|
1154
|
+
function frontmcpToOTelSpanContext(tc) {
|
|
1155
|
+
return {
|
|
1156
|
+
traceId: tc.traceId,
|
|
1157
|
+
spanId: tc.parentId,
|
|
1158
|
+
traceFlags: tc.traceFlags & TraceFlags.SAMPLED ? TraceFlags.SAMPLED : TraceFlags.NONE,
|
|
1159
|
+
isRemote: true
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function otelToFrontmcpContext(sc) {
|
|
1163
|
+
const flags = sc.traceFlags.toString(16).padStart(2, "0");
|
|
1164
|
+
return {
|
|
1165
|
+
traceId: sc.traceId,
|
|
1166
|
+
parentId: sc.spanId,
|
|
1167
|
+
traceFlags: sc.traceFlags,
|
|
1168
|
+
raw: `00-${sc.traceId}-${sc.spanId}-${flags}`
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
function createOTelContextFromTrace(tc) {
|
|
1172
|
+
const spanContext = frontmcpToOTelSpanContext(tc);
|
|
1173
|
+
const span = trace2.wrapSpanContext(spanContext);
|
|
1174
|
+
return trace2.setSpan(otelContext2.active(), span);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1187
1177
|
// libs/observability/src/plugin/observability.hooks.ts
|
|
1188
1178
|
var SPAN_KEY = /* @__PURE__ */ Symbol.for("frontmcp:otel:span");
|
|
1189
1179
|
var SPAN_CTX_KEY = /* @__PURE__ */ Symbol.for("frontmcp:otel:span-ctx");
|
|
@@ -1375,7 +1365,7 @@ function onToolWillApplyUI(flowCtx) {
|
|
|
1375
1365
|
function onToolDidFinalize(flowCtx) {
|
|
1376
1366
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1377
1367
|
const toolSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1378
|
-
const error = flowCtx.state?.
|
|
1368
|
+
const error = flowCtx.state?.flowError;
|
|
1379
1369
|
if (error) {
|
|
1380
1370
|
if (toolSpan) endSpanError(toolSpan, error instanceof Error ? error : String(error));
|
|
1381
1371
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1428,7 +1418,7 @@ function onResourceDidExecute(flowCtx) {
|
|
|
1428
1418
|
function onResourceDidFinalize(flowCtx) {
|
|
1429
1419
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1430
1420
|
const resSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1431
|
-
const error = flowCtx.state?.
|
|
1421
|
+
const error = flowCtx.state?.flowError;
|
|
1432
1422
|
if (error) {
|
|
1433
1423
|
if (resSpan) endSpanError(resSpan, error instanceof Error ? error : String(error));
|
|
1434
1424
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1484,7 +1474,7 @@ function onPromptDidExecute(flowCtx) {
|
|
|
1484
1474
|
function onPromptDidFinalize(flowCtx) {
|
|
1485
1475
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1486
1476
|
const promptSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1487
|
-
const error = flowCtx.state?.
|
|
1477
|
+
const error = flowCtx.state?.flowError;
|
|
1488
1478
|
if (error) {
|
|
1489
1479
|
if (promptSpan) endSpanError(promptSpan, error instanceof Error ? error : String(error));
|
|
1490
1480
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1547,7 +1537,7 @@ function onAgentDidExecute(flowCtx) {
|
|
|
1547
1537
|
function onAgentDidFinalize(flowCtx) {
|
|
1548
1538
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1549
1539
|
const agentSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1550
|
-
const error = flowCtx.state?.
|
|
1540
|
+
const error = flowCtx.state?.flowError;
|
|
1551
1541
|
if (error) {
|
|
1552
1542
|
if (agentSpan) endSpanError(agentSpan, error instanceof Error ? error : String(error));
|
|
1553
1543
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1586,7 +1576,7 @@ function onGenericFlowStage(stageName, flowCtx) {
|
|
|
1586
1576
|
function onGenericFlowDidFinalize(flowCtx) {
|
|
1587
1577
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1588
1578
|
if (!span) return;
|
|
1589
|
-
const error = flowCtx.state?.
|
|
1579
|
+
const error = flowCtx.state?.flowError;
|
|
1590
1580
|
if (error) {
|
|
1591
1581
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
1592
1582
|
} else {
|
|
@@ -1625,7 +1615,7 @@ function onTransportDidFinalize(flowCtx) {
|
|
|
1625
1615
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1626
1616
|
if (!span) return;
|
|
1627
1617
|
recordStageEvent(span, "cleanup", flowCtx.state);
|
|
1628
|
-
const error = flowCtx.state?.
|
|
1618
|
+
const error = flowCtx.state?.flowError;
|
|
1629
1619
|
if (error) {
|
|
1630
1620
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
1631
1621
|
} else {
|
|
@@ -1661,7 +1651,7 @@ function onAuthStage(stageName, flowCtx) {
|
|
|
1661
1651
|
function onAuthDidFinalize(flowCtx) {
|
|
1662
1652
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1663
1653
|
if (!span) return;
|
|
1664
|
-
const error = flowCtx.state?.
|
|
1654
|
+
const error = flowCtx.state?.flowError;
|
|
1665
1655
|
if (error) {
|
|
1666
1656
|
setAuthResult(span, "unauthorized");
|
|
1667
1657
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
@@ -1710,6 +1700,64 @@ function reportStartup(data) {
|
|
|
1710
1700
|
emitStartupReport(tracer, data);
|
|
1711
1701
|
}
|
|
1712
1702
|
|
|
1703
|
+
// libs/observability/src/request-log/request-log.tokens.ts
|
|
1704
|
+
var REQUEST_LOG_COLLECTOR = /* @__PURE__ */ Symbol.for("frontmcp:observability:request-log-collector");
|
|
1705
|
+
|
|
1706
|
+
// libs/observability/src/request-log/request-log.hooks.ts
|
|
1707
|
+
var FRONTMCP_CONTEXT = /* @__PURE__ */ Symbol.for("frontmcp:CONTEXT");
|
|
1708
|
+
function resolve(flowCtx, token) {
|
|
1709
|
+
try {
|
|
1710
|
+
return flowCtx.get?.(token);
|
|
1711
|
+
} catch {
|
|
1712
|
+
return void 0;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
function currentRequestLog(flowCtx) {
|
|
1716
|
+
return resolve(flowCtx, FRONTMCP_CONTEXT)?.get(REQUEST_LOG_COLLECTOR);
|
|
1717
|
+
}
|
|
1718
|
+
function startRequestLog(flowCtx, options) {
|
|
1719
|
+
const context = resolve(flowCtx, FRONTMCP_CONTEXT);
|
|
1720
|
+
if (!context) return;
|
|
1721
|
+
const collector = new RequestLogCollector(
|
|
1722
|
+
{
|
|
1723
|
+
requestId: context.requestId,
|
|
1724
|
+
traceId: context.traceContext.traceId,
|
|
1725
|
+
sessionIdHash: sessionTracingId(context.sessionId).slice(0, 12),
|
|
1726
|
+
scopeId: context.scopeId
|
|
1727
|
+
},
|
|
1728
|
+
options
|
|
1729
|
+
);
|
|
1730
|
+
context.set(REQUEST_LOG_COLLECTOR, collector);
|
|
1731
|
+
const request = flowCtx.rawInput?.request;
|
|
1732
|
+
if (request?.method && request.path) collector.setHttpInfo(request.method, request.path);
|
|
1733
|
+
const rpcMethod = request?.body?.method;
|
|
1734
|
+
if (typeof rpcMethod === "string") collector.setRpcMethod(rpcMethod);
|
|
1735
|
+
}
|
|
1736
|
+
function recordRequestLogFailure(flowCtx) {
|
|
1737
|
+
const failure = flowCtx.state?.["flowError"];
|
|
1738
|
+
if (!failure) return;
|
|
1739
|
+
const error = failure instanceof Error ? failure : new Error(String(failure));
|
|
1740
|
+
currentRequestLog(flowCtx)?.setError({
|
|
1741
|
+
type: error.name,
|
|
1742
|
+
message: error.message,
|
|
1743
|
+
code: error.code
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
async function completeRequestLog(flowCtx) {
|
|
1747
|
+
const collector = currentRequestLog(flowCtx);
|
|
1748
|
+
if (!collector || collector.isFinalized()) return;
|
|
1749
|
+
const statusCode = flowCtx.state?.["statusCode"] ?? flowCtx.rawInput?.response?.statusCode;
|
|
1750
|
+
if (typeof statusCode === "number" && statusCode >= 400) collector.setStatus("error", statusCode);
|
|
1751
|
+
await collector.finalize();
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// libs/observability/src/telemetry/telemetry.accessor.ts
|
|
1755
|
+
import {
|
|
1756
|
+
SpanKind as SpanKind12,
|
|
1757
|
+
SpanStatusCode as SpanStatusCode2,
|
|
1758
|
+
trace as trace4
|
|
1759
|
+
} from "@opentelemetry/api";
|
|
1760
|
+
|
|
1713
1761
|
// libs/observability/src/telemetry/telemetry.counters.ts
|
|
1714
1762
|
import { metrics } from "@opentelemetry/api";
|
|
1715
1763
|
function snapshotKey(name, attributes) {
|
|
@@ -2085,8 +2133,19 @@ var ObservabilityPlugin = class extends DynamicPlugin {
|
|
|
2085
2133
|
get tracingEnabled() {
|
|
2086
2134
|
return this.options.tracing !== false;
|
|
2087
2135
|
}
|
|
2136
|
+
get requestLogsEnabled() {
|
|
2137
|
+
return this.options.requestLogs !== false;
|
|
2138
|
+
}
|
|
2139
|
+
/** Names the entry a request serves on its request log, and records the entry flow's failure. */
|
|
2140
|
+
annotateRequestLog(ctx, set) {
|
|
2141
|
+
if (!this.requestLogsEnabled) return;
|
|
2142
|
+
const flowCtx = ctx;
|
|
2143
|
+
const log = currentRequestLog(ctx);
|
|
2144
|
+
if (log && flowCtx.state?.input) set(log, flowCtx.state.input);
|
|
2145
|
+
}
|
|
2088
2146
|
_httpWillTrace(ctx) {
|
|
2089
2147
|
if (this.tracingEnabled) onHttpWillTrace(this.tracingOpts, ctx);
|
|
2148
|
+
if (this.options.requestLogs !== false) startRequestLog(ctx, this.options.requestLogs);
|
|
2090
2149
|
}
|
|
2091
2150
|
_httpWillQuota(ctx) {
|
|
2092
2151
|
if (this.tracingEnabled) onHttpWillAcquireQuota(ctx);
|
|
@@ -2108,12 +2167,14 @@ var ObservabilityPlugin = class extends DynamicPlugin {
|
|
|
2108
2167
|
}
|
|
2109
2168
|
_httpDidFinalize(ctx) {
|
|
2110
2169
|
if (this.tracingEnabled) onHttpDidFinalize(ctx);
|
|
2170
|
+
if (this.requestLogsEnabled) void completeRequestLog(ctx);
|
|
2111
2171
|
}
|
|
2112
2172
|
_toolWillParse(ctx) {
|
|
2113
2173
|
if (this.tracingEnabled) onToolWillParse(this.tracingOpts, ctx);
|
|
2114
2174
|
}
|
|
2115
2175
|
_toolWillFind(ctx) {
|
|
2116
2176
|
if (this.tracingEnabled) onToolWillFindTool(ctx);
|
|
2177
|
+
this.annotateRequestLog(ctx, (log, input) => log.setToolName(String(input["name"])));
|
|
2117
2178
|
}
|
|
2118
2179
|
_toolWillCheckAuth(ctx) {
|
|
2119
2180
|
if (this.tracingEnabled) onToolWillCheckAuth(ctx);
|
|
@@ -2144,12 +2205,14 @@ var ObservabilityPlugin = class extends DynamicPlugin {
|
|
|
2144
2205
|
}
|
|
2145
2206
|
_toolDidFinalize(ctx) {
|
|
2146
2207
|
if (this.tracingEnabled) onToolDidFinalize(ctx);
|
|
2208
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2147
2209
|
}
|
|
2148
2210
|
_resourceWillParse(ctx) {
|
|
2149
2211
|
if (this.tracingEnabled) onResourceWillParse(this.tracingOpts, ctx);
|
|
2150
2212
|
}
|
|
2151
2213
|
_resourceWillFind(ctx) {
|
|
2152
2214
|
if (this.tracingEnabled) onResourceWillFind(ctx);
|
|
2215
|
+
this.annotateRequestLog(ctx, (log, input) => log.setResourceUri(String(input["uri"])));
|
|
2153
2216
|
}
|
|
2154
2217
|
_resourceWillCheckAuthorities(ctx) {
|
|
2155
2218
|
if (this.tracingEnabled) onEntryWillCheckAuthorities(ctx);
|
|
@@ -2165,12 +2228,14 @@ var ObservabilityPlugin = class extends DynamicPlugin {
|
|
|
2165
2228
|
}
|
|
2166
2229
|
_resourceDidFinalize(ctx) {
|
|
2167
2230
|
if (this.tracingEnabled) onResourceDidFinalize(ctx);
|
|
2231
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2168
2232
|
}
|
|
2169
2233
|
_promptWillParse(ctx) {
|
|
2170
2234
|
if (this.tracingEnabled) onPromptWillParse(this.tracingOpts, ctx);
|
|
2171
2235
|
}
|
|
2172
2236
|
_promptWillFind(ctx) {
|
|
2173
2237
|
if (this.tracingEnabled) onPromptWillFind(ctx);
|
|
2238
|
+
this.annotateRequestLog(ctx, (log, input) => log.setPromptName(String(input["name"])));
|
|
2174
2239
|
}
|
|
2175
2240
|
_promptWillCheckAuthorities(ctx) {
|
|
2176
2241
|
if (this.tracingEnabled) onEntryWillCheckAuthorities(ctx);
|
|
@@ -2186,6 +2251,7 @@ var ObservabilityPlugin = class extends DynamicPlugin {
|
|
|
2186
2251
|
}
|
|
2187
2252
|
_promptDidFinalize(ctx) {
|
|
2188
2253
|
if (this.tracingEnabled) onPromptDidFinalize(ctx);
|
|
2254
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2189
2255
|
}
|
|
2190
2256
|
_agentWillParse(ctx) {
|
|
2191
2257
|
if (this.tracingEnabled) onAgentWillParse(this.tracingOpts, ctx);
|
|
@@ -2480,7 +2546,7 @@ ObservabilityPlugin.dynamicProviders = (input) => {
|
|
|
2480
2546
|
name: "observability:telemetry-accessor",
|
|
2481
2547
|
provide: TELEMETRY_ACCESSOR,
|
|
2482
2548
|
scope: ProviderScope.CONTEXT,
|
|
2483
|
-
inject: () => [
|
|
2549
|
+
inject: () => [FRONTMCP_CONTEXT2],
|
|
2484
2550
|
useFactory: (ctx) => new TelemetryAccessor(ctx)
|
|
2485
2551
|
});
|
|
2486
2552
|
providers.push({
|
|
@@ -2513,7 +2579,7 @@ ObservabilityPlugin.dynamicProviders = (input) => {
|
|
|
2513
2579
|
name: "observability:request-log-collector",
|
|
2514
2580
|
provide: REQUEST_LOG_COLLECTOR,
|
|
2515
2581
|
scope: ProviderScope.CONTEXT,
|
|
2516
|
-
inject: () => [
|
|
2582
|
+
inject: () => [FRONTMCP_CONTEXT2],
|
|
2517
2583
|
useFactory: (ctx) => {
|
|
2518
2584
|
return new RequestLogCollector(
|
|
2519
2585
|
{
|
|
@@ -3212,6 +3278,13 @@ function renderJsonExposition(counters, gauges = []) {
|
|
|
3212
3278
|
import { readdirSync } from "@frontmcp/utils";
|
|
3213
3279
|
var NS_PER_SECOND = 1e9;
|
|
3214
3280
|
var MICROS_PER_SECOND = 1e6;
|
|
3281
|
+
function probeSafely(probe) {
|
|
3282
|
+
try {
|
|
3283
|
+
return probe();
|
|
3284
|
+
} catch {
|
|
3285
|
+
return void 0;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3215
3288
|
function defaultMonitorEventLoopDelay() {
|
|
3216
3289
|
try {
|
|
3217
3290
|
const { monitorEventLoopDelay } = __require("node:perf_hooks");
|
|
@@ -3257,54 +3330,70 @@ var ProcessStatsCollector = class {
|
|
|
3257
3330
|
this.getActiveHandles = init.getActiveHandles ?? defaultGetActiveHandles;
|
|
3258
3331
|
this.getActiveRequests = init.getActiveRequests ?? defaultGetActiveRequests;
|
|
3259
3332
|
this.readFdCount = init.readFdCount ?? defaultReadFdCount;
|
|
3260
|
-
this.cpuStart = this.cpuUsage();
|
|
3333
|
+
this.cpuStart = probeSafely(() => this.cpuUsage());
|
|
3261
3334
|
if (this.options.eventLoopLag !== false) {
|
|
3262
3335
|
this.histogram = init.monitorEventLoopDelay ? init.monitorEventLoopDelay() : defaultMonitorEventLoopDelay();
|
|
3263
3336
|
}
|
|
3264
3337
|
}
|
|
3265
3338
|
collect() {
|
|
3266
3339
|
const entries = [];
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3340
|
+
this.cpuStart ??= probeSafely(() => this.cpuUsage());
|
|
3341
|
+
const cpu = this.cpuStart && probeSafely(() => this.cpuUsage(this.cpuStart));
|
|
3342
|
+
if (cpu) {
|
|
3343
|
+
entries.push({
|
|
3344
|
+
name: "frontmcp_process_cpu_seconds_total",
|
|
3345
|
+
value: cpu.user / MICROS_PER_SECOND,
|
|
3346
|
+
attributes: { mode: "user" },
|
|
3347
|
+
help: "CPU time consumed since collector start, by mode (seconds)"
|
|
3348
|
+
});
|
|
3349
|
+
entries.push({
|
|
3350
|
+
name: "frontmcp_process_cpu_seconds_total",
|
|
3351
|
+
value: cpu.system / MICROS_PER_SECOND,
|
|
3352
|
+
attributes: { mode: "system" }
|
|
3353
|
+
});
|
|
3354
|
+
}
|
|
3355
|
+
const mem = probeSafely(() => this.memoryUsage());
|
|
3356
|
+
if (mem) {
|
|
3357
|
+
entries.push({
|
|
3358
|
+
name: "frontmcp_process_resident_memory_bytes",
|
|
3359
|
+
value: mem.rss,
|
|
3360
|
+
help: "Resident memory size in bytes"
|
|
3361
|
+
});
|
|
3362
|
+
entries.push({
|
|
3363
|
+
name: "frontmcp_process_heap_bytes",
|
|
3364
|
+
value: mem.heapTotal,
|
|
3365
|
+
help: "Total V8 heap size in bytes"
|
|
3366
|
+
});
|
|
3367
|
+
entries.push({
|
|
3368
|
+
name: "frontmcp_process_heap_used_bytes",
|
|
3369
|
+
value: mem.heapUsed,
|
|
3370
|
+
help: "Used V8 heap size in bytes"
|
|
3371
|
+
});
|
|
3372
|
+
entries.push({
|
|
3373
|
+
name: "frontmcp_process_external_bytes",
|
|
3374
|
+
value: mem.external,
|
|
3375
|
+
help: "Memory used by C++ objects bound to JS in bytes"
|
|
3376
|
+
});
|
|
3377
|
+
}
|
|
3378
|
+
const uptime = probeSafely(() => this.uptime());
|
|
3379
|
+
if (uptime !== void 0) {
|
|
3380
|
+
entries.push({
|
|
3381
|
+
name: "frontmcp_process_uptime_seconds",
|
|
3382
|
+
value: uptime,
|
|
3383
|
+
help: "Time since process start in seconds"
|
|
3384
|
+
});
|
|
3385
|
+
}
|
|
3386
|
+
const histogram = this.options.eventLoopLag !== false ? this.histogram : void 0;
|
|
3387
|
+
const lag = histogram && probeSafely(() => {
|
|
3388
|
+
const sample = {
|
|
3389
|
+
meanSeconds: histogram.mean / NS_PER_SECOND,
|
|
3390
|
+
p99Seconds: histogram.percentile(99) / NS_PER_SECOND
|
|
3391
|
+
};
|
|
3392
|
+
histogram.reset();
|
|
3393
|
+
return sample;
|
|
3304
3394
|
});
|
|
3305
|
-
if (
|
|
3306
|
-
const meanSeconds
|
|
3307
|
-
const p99Seconds = this.histogram.percentile(99) / NS_PER_SECOND;
|
|
3395
|
+
if (lag) {
|
|
3396
|
+
const { meanSeconds, p99Seconds } = lag;
|
|
3308
3397
|
if (Number.isFinite(meanSeconds)) {
|
|
3309
3398
|
entries.push({
|
|
3310
3399
|
name: "frontmcp_nodejs_eventloop_lag_seconds",
|
|
@@ -3320,7 +3409,6 @@ var ProcessStatsCollector = class {
|
|
|
3320
3409
|
attributes: { quantile: "p99" }
|
|
3321
3410
|
});
|
|
3322
3411
|
}
|
|
3323
|
-
this.histogram.reset();
|
|
3324
3412
|
}
|
|
3325
3413
|
if (this.options.activeHandles !== false) {
|
|
3326
3414
|
const handles = this.getActiveHandles?.();
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/observability",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"description": "OpenTelemetry instrumentation, structured JSON logging, and request log objects for FrontMCP",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"@opentelemetry/api": "^1.9.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@frontmcp/sdk": "1.9.
|
|
55
|
-
"@frontmcp/utils": "1.9.
|
|
54
|
+
"@frontmcp/sdk": "1.9.2",
|
|
55
|
+
"@frontmcp/utils": "1.9.2",
|
|
56
56
|
"@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
|
|
57
57
|
"@opentelemetry/sdk-node": "^0.219.0",
|
|
58
58
|
"@opentelemetry/sdk-trace-base": "^2.8.0",
|
package/index.js
CHANGED
|
@@ -831,11 +831,9 @@ var RequestLogCollector = class {
|
|
|
831
831
|
}
|
|
832
832
|
};
|
|
833
833
|
|
|
834
|
-
// libs/observability/src/
|
|
835
|
-
var
|
|
836
|
-
|
|
837
|
-
// libs/observability/src/telemetry/telemetry.accessor.ts
|
|
838
|
-
var import_api14 = require("@opentelemetry/api");
|
|
834
|
+
// libs/observability/src/plugin/observability.hooks.ts
|
|
835
|
+
var import_api12 = require("@opentelemetry/api");
|
|
836
|
+
var import_utils = require("@frontmcp/utils");
|
|
839
837
|
|
|
840
838
|
// libs/observability/src/otel/otel.types.ts
|
|
841
839
|
var McpAttributes = {
|
|
@@ -950,60 +948,31 @@ var EnduserAttributes = {
|
|
|
950
948
|
SCOPE: "enduser.scope"
|
|
951
949
|
};
|
|
952
950
|
|
|
953
|
-
// libs/observability/src/otel/trace-context-bridge.ts
|
|
954
|
-
var import_api = require("@opentelemetry/api");
|
|
955
|
-
function frontmcpToOTelSpanContext(tc) {
|
|
956
|
-
return {
|
|
957
|
-
traceId: tc.traceId,
|
|
958
|
-
spanId: tc.parentId,
|
|
959
|
-
traceFlags: tc.traceFlags & import_api.TraceFlags.SAMPLED ? import_api.TraceFlags.SAMPLED : import_api.TraceFlags.NONE,
|
|
960
|
-
isRemote: true
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
function otelToFrontmcpContext(sc) {
|
|
964
|
-
const flags = sc.traceFlags.toString(16).padStart(2, "0");
|
|
965
|
-
return {
|
|
966
|
-
traceId: sc.traceId,
|
|
967
|
-
parentId: sc.spanId,
|
|
968
|
-
traceFlags: sc.traceFlags,
|
|
969
|
-
raw: `00-${sc.traceId}-${sc.spanId}-${flags}`
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
function createOTelContextFromTrace(tc) {
|
|
973
|
-
const spanContext = frontmcpToOTelSpanContext(tc);
|
|
974
|
-
const span = import_api.trace.wrapSpanContext(spanContext);
|
|
975
|
-
return import_api.trace.setSpan(import_api.context.active(), span);
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
// libs/observability/src/plugin/observability.hooks.ts
|
|
979
|
-
var import_api12 = require("@opentelemetry/api");
|
|
980
|
-
var import_utils = require("@frontmcp/utils");
|
|
981
|
-
|
|
982
951
|
// libs/observability/src/otel/spans/auth.span.ts
|
|
983
|
-
var
|
|
952
|
+
var import_api2 = require("@opentelemetry/api");
|
|
984
953
|
|
|
985
954
|
// libs/observability/src/otel/spans/span.utils.ts
|
|
986
|
-
var
|
|
955
|
+
var import_api = require("@opentelemetry/api");
|
|
987
956
|
function startSpan(tracer, options) {
|
|
988
|
-
const parentCtx = options.parentContext ??
|
|
957
|
+
const parentCtx = options.parentContext ?? import_api.context.active();
|
|
989
958
|
const span = tracer.startSpan(
|
|
990
959
|
options.name,
|
|
991
960
|
{
|
|
992
|
-
kind: options.kind ??
|
|
961
|
+
kind: options.kind ?? import_api.SpanKind.INTERNAL,
|
|
993
962
|
attributes: options.attributes
|
|
994
963
|
},
|
|
995
964
|
parentCtx
|
|
996
965
|
);
|
|
997
|
-
const spanContext =
|
|
966
|
+
const spanContext = import_api.trace.setSpan(parentCtx, span);
|
|
998
967
|
return { span, context: spanContext };
|
|
999
968
|
}
|
|
1000
969
|
function endSpanOk(span) {
|
|
1001
|
-
span.setStatus({ code:
|
|
970
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
1002
971
|
span.end();
|
|
1003
972
|
}
|
|
1004
973
|
function endSpanError(span, error) {
|
|
1005
974
|
const message = typeof error === "string" ? error : error.message;
|
|
1006
|
-
span.setStatus({ code:
|
|
975
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR, message });
|
|
1007
976
|
if (error instanceof Error) {
|
|
1008
977
|
span.recordException(error);
|
|
1009
978
|
}
|
|
@@ -1011,7 +980,7 @@ function endSpanError(span, error) {
|
|
|
1011
980
|
}
|
|
1012
981
|
async function withSpan(tracer, options, fn) {
|
|
1013
982
|
const { span, context: spanContext } = startSpan(tracer, options);
|
|
1014
|
-
return
|
|
983
|
+
return import_api.context.with(spanContext, async () => {
|
|
1015
984
|
try {
|
|
1016
985
|
const result = await fn(span);
|
|
1017
986
|
endSpanOk(span);
|
|
@@ -1027,7 +996,7 @@ async function withSpan(tracer, options, fn) {
|
|
|
1027
996
|
function startAuthSpan(tracer, options) {
|
|
1028
997
|
return startSpan(tracer, {
|
|
1029
998
|
name: `auth ${options.flowName}`,
|
|
1030
|
-
kind:
|
|
999
|
+
kind: import_api2.SpanKind.INTERNAL,
|
|
1031
1000
|
attributes: {
|
|
1032
1001
|
[FrontMcpAttributes.FLOW_NAME]: options.flowName
|
|
1033
1002
|
},
|
|
@@ -1042,11 +1011,11 @@ function setAuthResult(span, result) {
|
|
|
1042
1011
|
}
|
|
1043
1012
|
|
|
1044
1013
|
// libs/observability/src/otel/spans/fetch.span.ts
|
|
1045
|
-
var
|
|
1014
|
+
var import_api3 = require("@opentelemetry/api");
|
|
1046
1015
|
function startFetchSpan(tracer, options) {
|
|
1047
1016
|
return startSpan(tracer, {
|
|
1048
1017
|
name: options.method.toUpperCase(),
|
|
1049
|
-
kind:
|
|
1018
|
+
kind: import_api3.SpanKind.CLIENT,
|
|
1050
1019
|
attributes: {
|
|
1051
1020
|
[HttpAttributes.METHOD]: options.method.toUpperCase(),
|
|
1052
1021
|
[HttpAttributes.URL_FULL]: options.url
|
|
@@ -1059,7 +1028,7 @@ function setFetchResponseStatus(span, statusCode) {
|
|
|
1059
1028
|
}
|
|
1060
1029
|
|
|
1061
1030
|
// libs/observability/src/otel/spans/http-server.span.ts
|
|
1062
|
-
var
|
|
1031
|
+
var import_api4 = require("@opentelemetry/api");
|
|
1063
1032
|
function startHttpServerSpan(tracer, options) {
|
|
1064
1033
|
const attributes = {
|
|
1065
1034
|
[HttpAttributes.METHOD]: options.method.toUpperCase(),
|
|
@@ -1082,7 +1051,7 @@ function startHttpServerSpan(tracer, options) {
|
|
|
1082
1051
|
}
|
|
1083
1052
|
return startSpan(tracer, {
|
|
1084
1053
|
name: `${options.method.toUpperCase()} ${options.path}`,
|
|
1085
|
-
kind:
|
|
1054
|
+
kind: import_api4.SpanKind.SERVER,
|
|
1086
1055
|
attributes,
|
|
1087
1056
|
parentContext: options.parentContext
|
|
1088
1057
|
});
|
|
@@ -1092,11 +1061,11 @@ function setHttpResponseStatus(span, statusCode) {
|
|
|
1092
1061
|
}
|
|
1093
1062
|
|
|
1094
1063
|
// libs/observability/src/otel/spans/prompt.span.ts
|
|
1095
|
-
var
|
|
1064
|
+
var import_api5 = require("@opentelemetry/api");
|
|
1096
1065
|
function startPromptSpan(tracer, options) {
|
|
1097
1066
|
return startSpan(tracer, {
|
|
1098
1067
|
name: `prompt ${options.name}`,
|
|
1099
|
-
kind:
|
|
1068
|
+
kind: import_api5.SpanKind.INTERNAL,
|
|
1100
1069
|
attributes: {
|
|
1101
1070
|
[FrontMcpAttributes.PROMPT_NAME]: options.name,
|
|
1102
1071
|
[McpAttributes.COMPONENT_TYPE]: "prompt",
|
|
@@ -1107,7 +1076,7 @@ function startPromptSpan(tracer, options) {
|
|
|
1107
1076
|
}
|
|
1108
1077
|
|
|
1109
1078
|
// libs/observability/src/otel/spans/resource.span.ts
|
|
1110
|
-
var
|
|
1079
|
+
var import_api6 = require("@opentelemetry/api");
|
|
1111
1080
|
function startResourceSpan(tracer, options) {
|
|
1112
1081
|
const attributes = {
|
|
1113
1082
|
[FrontMcpAttributes.RESOURCE_URI]: options.uri,
|
|
@@ -1120,14 +1089,14 @@ function startResourceSpan(tracer, options) {
|
|
|
1120
1089
|
}
|
|
1121
1090
|
return startSpan(tracer, {
|
|
1122
1091
|
name: `resource ${options.uri}`,
|
|
1123
|
-
kind:
|
|
1092
|
+
kind: import_api6.SpanKind.INTERNAL,
|
|
1124
1093
|
attributes,
|
|
1125
1094
|
parentContext: options.parentContext
|
|
1126
1095
|
});
|
|
1127
1096
|
}
|
|
1128
1097
|
|
|
1129
1098
|
// libs/observability/src/otel/spans/rpc.span.ts
|
|
1130
|
-
var
|
|
1099
|
+
var import_api7 = require("@opentelemetry/api");
|
|
1131
1100
|
function startRpcSpan(tracer, options) {
|
|
1132
1101
|
const attributes = {
|
|
1133
1102
|
[RpcAttributes.SYSTEM]: "mcp",
|
|
@@ -1151,14 +1120,14 @@ function startRpcSpan(tracer, options) {
|
|
|
1151
1120
|
}
|
|
1152
1121
|
return startSpan(tracer, {
|
|
1153
1122
|
name: options.method,
|
|
1154
|
-
kind:
|
|
1123
|
+
kind: import_api7.SpanKind.SERVER,
|
|
1155
1124
|
attributes,
|
|
1156
1125
|
parentContext: options.parentContext
|
|
1157
1126
|
});
|
|
1158
1127
|
}
|
|
1159
1128
|
|
|
1160
1129
|
// libs/observability/src/otel/spans/startup.span.ts
|
|
1161
|
-
var
|
|
1130
|
+
var import_api8 = require("@opentelemetry/api");
|
|
1162
1131
|
function emitStartupReport(tracer, data) {
|
|
1163
1132
|
const attributes = {
|
|
1164
1133
|
[FrontMcpAttributes.STARTUP_TOOLS_COUNT]: data.toolsCount,
|
|
@@ -1172,14 +1141,14 @@ function emitStartupReport(tracer, data) {
|
|
|
1172
1141
|
}
|
|
1173
1142
|
const { span } = startSpan(tracer, {
|
|
1174
1143
|
name: "frontmcp.startup",
|
|
1175
|
-
kind:
|
|
1144
|
+
kind: import_api8.SpanKind.INTERNAL,
|
|
1176
1145
|
attributes
|
|
1177
1146
|
});
|
|
1178
1147
|
endSpanOk(span);
|
|
1179
1148
|
}
|
|
1180
1149
|
|
|
1181
1150
|
// libs/observability/src/otel/spans/tool.span.ts
|
|
1182
|
-
var
|
|
1151
|
+
var import_api9 = require("@opentelemetry/api");
|
|
1183
1152
|
function startToolSpan(tracer, options) {
|
|
1184
1153
|
const attributes = {
|
|
1185
1154
|
[FrontMcpAttributes.TOOL_NAME]: options.name,
|
|
@@ -1197,14 +1166,14 @@ function startToolSpan(tracer, options) {
|
|
|
1197
1166
|
}
|
|
1198
1167
|
return startSpan(tracer, {
|
|
1199
1168
|
name: `tool ${options.name}`,
|
|
1200
|
-
kind:
|
|
1169
|
+
kind: import_api9.SpanKind.INTERNAL,
|
|
1201
1170
|
attributes,
|
|
1202
1171
|
parentContext: options.parentContext
|
|
1203
1172
|
});
|
|
1204
1173
|
}
|
|
1205
1174
|
|
|
1206
1175
|
// libs/observability/src/otel/spans/transport.span.ts
|
|
1207
|
-
var
|
|
1176
|
+
var import_api10 = require("@opentelemetry/api");
|
|
1208
1177
|
function startTransportSpan(tracer, options) {
|
|
1209
1178
|
const attributes = {
|
|
1210
1179
|
[FrontMcpAttributes.TRANSPORT_TYPE]: options.type
|
|
@@ -1217,7 +1186,7 @@ function startTransportSpan(tracer, options) {
|
|
|
1217
1186
|
}
|
|
1218
1187
|
return startSpan(tracer, {
|
|
1219
1188
|
name: `transport ${options.type}`,
|
|
1220
|
-
kind:
|
|
1189
|
+
kind: import_api10.SpanKind.INTERNAL,
|
|
1221
1190
|
attributes,
|
|
1222
1191
|
parentContext: options.parentContext
|
|
1223
1192
|
});
|
|
@@ -1226,6 +1195,31 @@ function setTransportRequestType(span, requestType) {
|
|
|
1226
1195
|
span.setAttribute(FrontMcpAttributes.TRANSPORT_REQUEST_TYPE, requestType);
|
|
1227
1196
|
}
|
|
1228
1197
|
|
|
1198
|
+
// libs/observability/src/otel/trace-context-bridge.ts
|
|
1199
|
+
var import_api11 = require("@opentelemetry/api");
|
|
1200
|
+
function frontmcpToOTelSpanContext(tc) {
|
|
1201
|
+
return {
|
|
1202
|
+
traceId: tc.traceId,
|
|
1203
|
+
spanId: tc.parentId,
|
|
1204
|
+
traceFlags: tc.traceFlags & import_api11.TraceFlags.SAMPLED ? import_api11.TraceFlags.SAMPLED : import_api11.TraceFlags.NONE,
|
|
1205
|
+
isRemote: true
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
function otelToFrontmcpContext(sc) {
|
|
1209
|
+
const flags = sc.traceFlags.toString(16).padStart(2, "0");
|
|
1210
|
+
return {
|
|
1211
|
+
traceId: sc.traceId,
|
|
1212
|
+
parentId: sc.spanId,
|
|
1213
|
+
traceFlags: sc.traceFlags,
|
|
1214
|
+
raw: `00-${sc.traceId}-${sc.spanId}-${flags}`
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
function createOTelContextFromTrace(tc) {
|
|
1218
|
+
const spanContext = frontmcpToOTelSpanContext(tc);
|
|
1219
|
+
const span = import_api11.trace.wrapSpanContext(spanContext);
|
|
1220
|
+
return import_api11.trace.setSpan(import_api11.context.active(), span);
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1229
1223
|
// libs/observability/src/plugin/observability.hooks.ts
|
|
1230
1224
|
var SPAN_KEY = /* @__PURE__ */ Symbol.for("frontmcp:otel:span");
|
|
1231
1225
|
var SPAN_CTX_KEY = /* @__PURE__ */ Symbol.for("frontmcp:otel:span-ctx");
|
|
@@ -1417,7 +1411,7 @@ function onToolWillApplyUI(flowCtx) {
|
|
|
1417
1411
|
function onToolDidFinalize(flowCtx) {
|
|
1418
1412
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1419
1413
|
const toolSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1420
|
-
const error = flowCtx.state?.
|
|
1414
|
+
const error = flowCtx.state?.flowError;
|
|
1421
1415
|
if (error) {
|
|
1422
1416
|
if (toolSpan) endSpanError(toolSpan, error instanceof Error ? error : String(error));
|
|
1423
1417
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1470,7 +1464,7 @@ function onResourceDidExecute(flowCtx) {
|
|
|
1470
1464
|
function onResourceDidFinalize(flowCtx) {
|
|
1471
1465
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1472
1466
|
const resSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1473
|
-
const error = flowCtx.state?.
|
|
1467
|
+
const error = flowCtx.state?.flowError;
|
|
1474
1468
|
if (error) {
|
|
1475
1469
|
if (resSpan) endSpanError(resSpan, error instanceof Error ? error : String(error));
|
|
1476
1470
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1526,7 +1520,7 @@ function onPromptDidExecute(flowCtx) {
|
|
|
1526
1520
|
function onPromptDidFinalize(flowCtx) {
|
|
1527
1521
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1528
1522
|
const promptSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1529
|
-
const error = flowCtx.state?.
|
|
1523
|
+
const error = flowCtx.state?.flowError;
|
|
1530
1524
|
if (error) {
|
|
1531
1525
|
if (promptSpan) endSpanError(promptSpan, error instanceof Error ? error : String(error));
|
|
1532
1526
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1589,7 +1583,7 @@ function onAgentDidExecute(flowCtx) {
|
|
|
1589
1583
|
function onAgentDidFinalize(flowCtx) {
|
|
1590
1584
|
const rpcSpan = flowCtx.state?.[SPAN_KEY];
|
|
1591
1585
|
const agentSpan = flowCtx.state?.[EXEC_SPAN_KEY];
|
|
1592
|
-
const error = flowCtx.state?.
|
|
1586
|
+
const error = flowCtx.state?.flowError;
|
|
1593
1587
|
if (error) {
|
|
1594
1588
|
if (agentSpan) endSpanError(agentSpan, error instanceof Error ? error : String(error));
|
|
1595
1589
|
if (rpcSpan) endSpanError(rpcSpan, error instanceof Error ? error : String(error));
|
|
@@ -1628,7 +1622,7 @@ function onGenericFlowStage(stageName, flowCtx) {
|
|
|
1628
1622
|
function onGenericFlowDidFinalize(flowCtx) {
|
|
1629
1623
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1630
1624
|
if (!span) return;
|
|
1631
|
-
const error = flowCtx.state?.
|
|
1625
|
+
const error = flowCtx.state?.flowError;
|
|
1632
1626
|
if (error) {
|
|
1633
1627
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
1634
1628
|
} else {
|
|
@@ -1667,7 +1661,7 @@ function onTransportDidFinalize(flowCtx) {
|
|
|
1667
1661
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1668
1662
|
if (!span) return;
|
|
1669
1663
|
recordStageEvent(span, "cleanup", flowCtx.state);
|
|
1670
|
-
const error = flowCtx.state?.
|
|
1664
|
+
const error = flowCtx.state?.flowError;
|
|
1671
1665
|
if (error) {
|
|
1672
1666
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
1673
1667
|
} else {
|
|
@@ -1703,7 +1697,7 @@ function onAuthStage(stageName, flowCtx) {
|
|
|
1703
1697
|
function onAuthDidFinalize(flowCtx) {
|
|
1704
1698
|
const span = flowCtx.state?.[SPAN_KEY];
|
|
1705
1699
|
if (!span) return;
|
|
1706
|
-
const error = flowCtx.state?.
|
|
1700
|
+
const error = flowCtx.state?.flowError;
|
|
1707
1701
|
if (error) {
|
|
1708
1702
|
setAuthResult(span, "unauthorized");
|
|
1709
1703
|
endSpanError(span, error instanceof Error ? error : String(error));
|
|
@@ -1752,6 +1746,60 @@ function reportStartup(data) {
|
|
|
1752
1746
|
emitStartupReport(tracer, data);
|
|
1753
1747
|
}
|
|
1754
1748
|
|
|
1749
|
+
// libs/observability/src/request-log/request-log.tokens.ts
|
|
1750
|
+
var REQUEST_LOG_COLLECTOR = /* @__PURE__ */ Symbol.for("frontmcp:observability:request-log-collector");
|
|
1751
|
+
|
|
1752
|
+
// libs/observability/src/request-log/request-log.hooks.ts
|
|
1753
|
+
var FRONTMCP_CONTEXT = /* @__PURE__ */ Symbol.for("frontmcp:CONTEXT");
|
|
1754
|
+
function resolve(flowCtx, token) {
|
|
1755
|
+
try {
|
|
1756
|
+
return flowCtx.get?.(token);
|
|
1757
|
+
} catch {
|
|
1758
|
+
return void 0;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
function currentRequestLog(flowCtx) {
|
|
1762
|
+
return resolve(flowCtx, FRONTMCP_CONTEXT)?.get(REQUEST_LOG_COLLECTOR);
|
|
1763
|
+
}
|
|
1764
|
+
function startRequestLog(flowCtx, options) {
|
|
1765
|
+
const context = resolve(flowCtx, FRONTMCP_CONTEXT);
|
|
1766
|
+
if (!context) return;
|
|
1767
|
+
const collector = new RequestLogCollector(
|
|
1768
|
+
{
|
|
1769
|
+
requestId: context.requestId,
|
|
1770
|
+
traceId: context.traceContext.traceId,
|
|
1771
|
+
sessionIdHash: sessionTracingId(context.sessionId).slice(0, 12),
|
|
1772
|
+
scopeId: context.scopeId
|
|
1773
|
+
},
|
|
1774
|
+
options
|
|
1775
|
+
);
|
|
1776
|
+
context.set(REQUEST_LOG_COLLECTOR, collector);
|
|
1777
|
+
const request = flowCtx.rawInput?.request;
|
|
1778
|
+
if (request?.method && request.path) collector.setHttpInfo(request.method, request.path);
|
|
1779
|
+
const rpcMethod = request?.body?.method;
|
|
1780
|
+
if (typeof rpcMethod === "string") collector.setRpcMethod(rpcMethod);
|
|
1781
|
+
}
|
|
1782
|
+
function recordRequestLogFailure(flowCtx) {
|
|
1783
|
+
const failure = flowCtx.state?.["flowError"];
|
|
1784
|
+
if (!failure) return;
|
|
1785
|
+
const error = failure instanceof Error ? failure : new Error(String(failure));
|
|
1786
|
+
currentRequestLog(flowCtx)?.setError({
|
|
1787
|
+
type: error.name,
|
|
1788
|
+
message: error.message,
|
|
1789
|
+
code: error.code
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
async function completeRequestLog(flowCtx) {
|
|
1793
|
+
const collector = currentRequestLog(flowCtx);
|
|
1794
|
+
if (!collector || collector.isFinalized()) return;
|
|
1795
|
+
const statusCode = flowCtx.state?.["statusCode"] ?? flowCtx.rawInput?.response?.statusCode;
|
|
1796
|
+
if (typeof statusCode === "number" && statusCode >= 400) collector.setStatus("error", statusCode);
|
|
1797
|
+
await collector.finalize();
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
// libs/observability/src/telemetry/telemetry.accessor.ts
|
|
1801
|
+
var import_api14 = require("@opentelemetry/api");
|
|
1802
|
+
|
|
1755
1803
|
// libs/observability/src/telemetry/telemetry.counters.ts
|
|
1756
1804
|
var import_api13 = require("@opentelemetry/api");
|
|
1757
1805
|
function snapshotKey(name, attributes) {
|
|
@@ -2127,8 +2175,19 @@ var ObservabilityPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
2127
2175
|
get tracingEnabled() {
|
|
2128
2176
|
return this.options.tracing !== false;
|
|
2129
2177
|
}
|
|
2178
|
+
get requestLogsEnabled() {
|
|
2179
|
+
return this.options.requestLogs !== false;
|
|
2180
|
+
}
|
|
2181
|
+
/** Names the entry a request serves on its request log, and records the entry flow's failure. */
|
|
2182
|
+
annotateRequestLog(ctx, set) {
|
|
2183
|
+
if (!this.requestLogsEnabled) return;
|
|
2184
|
+
const flowCtx = ctx;
|
|
2185
|
+
const log = currentRequestLog(ctx);
|
|
2186
|
+
if (log && flowCtx.state?.input) set(log, flowCtx.state.input);
|
|
2187
|
+
}
|
|
2130
2188
|
_httpWillTrace(ctx) {
|
|
2131
2189
|
if (this.tracingEnabled) onHttpWillTrace(this.tracingOpts, ctx);
|
|
2190
|
+
if (this.options.requestLogs !== false) startRequestLog(ctx, this.options.requestLogs);
|
|
2132
2191
|
}
|
|
2133
2192
|
_httpWillQuota(ctx) {
|
|
2134
2193
|
if (this.tracingEnabled) onHttpWillAcquireQuota(ctx);
|
|
@@ -2150,12 +2209,14 @@ var ObservabilityPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
2150
2209
|
}
|
|
2151
2210
|
_httpDidFinalize(ctx) {
|
|
2152
2211
|
if (this.tracingEnabled) onHttpDidFinalize(ctx);
|
|
2212
|
+
if (this.requestLogsEnabled) void completeRequestLog(ctx);
|
|
2153
2213
|
}
|
|
2154
2214
|
_toolWillParse(ctx) {
|
|
2155
2215
|
if (this.tracingEnabled) onToolWillParse(this.tracingOpts, ctx);
|
|
2156
2216
|
}
|
|
2157
2217
|
_toolWillFind(ctx) {
|
|
2158
2218
|
if (this.tracingEnabled) onToolWillFindTool(ctx);
|
|
2219
|
+
this.annotateRequestLog(ctx, (log, input) => log.setToolName(String(input["name"])));
|
|
2159
2220
|
}
|
|
2160
2221
|
_toolWillCheckAuth(ctx) {
|
|
2161
2222
|
if (this.tracingEnabled) onToolWillCheckAuth(ctx);
|
|
@@ -2186,12 +2247,14 @@ var ObservabilityPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
2186
2247
|
}
|
|
2187
2248
|
_toolDidFinalize(ctx) {
|
|
2188
2249
|
if (this.tracingEnabled) onToolDidFinalize(ctx);
|
|
2250
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2189
2251
|
}
|
|
2190
2252
|
_resourceWillParse(ctx) {
|
|
2191
2253
|
if (this.tracingEnabled) onResourceWillParse(this.tracingOpts, ctx);
|
|
2192
2254
|
}
|
|
2193
2255
|
_resourceWillFind(ctx) {
|
|
2194
2256
|
if (this.tracingEnabled) onResourceWillFind(ctx);
|
|
2257
|
+
this.annotateRequestLog(ctx, (log, input) => log.setResourceUri(String(input["uri"])));
|
|
2195
2258
|
}
|
|
2196
2259
|
_resourceWillCheckAuthorities(ctx) {
|
|
2197
2260
|
if (this.tracingEnabled) onEntryWillCheckAuthorities(ctx);
|
|
@@ -2207,12 +2270,14 @@ var ObservabilityPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
2207
2270
|
}
|
|
2208
2271
|
_resourceDidFinalize(ctx) {
|
|
2209
2272
|
if (this.tracingEnabled) onResourceDidFinalize(ctx);
|
|
2273
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2210
2274
|
}
|
|
2211
2275
|
_promptWillParse(ctx) {
|
|
2212
2276
|
if (this.tracingEnabled) onPromptWillParse(this.tracingOpts, ctx);
|
|
2213
2277
|
}
|
|
2214
2278
|
_promptWillFind(ctx) {
|
|
2215
2279
|
if (this.tracingEnabled) onPromptWillFind(ctx);
|
|
2280
|
+
this.annotateRequestLog(ctx, (log, input) => log.setPromptName(String(input["name"])));
|
|
2216
2281
|
}
|
|
2217
2282
|
_promptWillCheckAuthorities(ctx) {
|
|
2218
2283
|
if (this.tracingEnabled) onEntryWillCheckAuthorities(ctx);
|
|
@@ -2228,6 +2293,7 @@ var ObservabilityPlugin = class extends import_sdk2.DynamicPlugin {
|
|
|
2228
2293
|
}
|
|
2229
2294
|
_promptDidFinalize(ctx) {
|
|
2230
2295
|
if (this.tracingEnabled) onPromptDidFinalize(ctx);
|
|
2296
|
+
if (this.requestLogsEnabled) recordRequestLogFailure(ctx);
|
|
2231
2297
|
}
|
|
2232
2298
|
_agentWillParse(ctx) {
|
|
2233
2299
|
if (this.tracingEnabled) onAgentWillParse(this.tracingOpts, ctx);
|
|
@@ -3252,6 +3318,13 @@ function renderJsonExposition(counters, gauges = []) {
|
|
|
3252
3318
|
var import_utils2 = require("@frontmcp/utils");
|
|
3253
3319
|
var NS_PER_SECOND = 1e9;
|
|
3254
3320
|
var MICROS_PER_SECOND = 1e6;
|
|
3321
|
+
function probeSafely(probe) {
|
|
3322
|
+
try {
|
|
3323
|
+
return probe();
|
|
3324
|
+
} catch {
|
|
3325
|
+
return void 0;
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3255
3328
|
function defaultMonitorEventLoopDelay() {
|
|
3256
3329
|
try {
|
|
3257
3330
|
const { monitorEventLoopDelay } = require("node:perf_hooks");
|
|
@@ -3297,54 +3370,70 @@ var ProcessStatsCollector = class {
|
|
|
3297
3370
|
this.getActiveHandles = init.getActiveHandles ?? defaultGetActiveHandles;
|
|
3298
3371
|
this.getActiveRequests = init.getActiveRequests ?? defaultGetActiveRequests;
|
|
3299
3372
|
this.readFdCount = init.readFdCount ?? defaultReadFdCount;
|
|
3300
|
-
this.cpuStart = this.cpuUsage();
|
|
3373
|
+
this.cpuStart = probeSafely(() => this.cpuUsage());
|
|
3301
3374
|
if (this.options.eventLoopLag !== false) {
|
|
3302
3375
|
this.histogram = init.monitorEventLoopDelay ? init.monitorEventLoopDelay() : defaultMonitorEventLoopDelay();
|
|
3303
3376
|
}
|
|
3304
3377
|
}
|
|
3305
3378
|
collect() {
|
|
3306
3379
|
const entries = [];
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3380
|
+
this.cpuStart ??= probeSafely(() => this.cpuUsage());
|
|
3381
|
+
const cpu = this.cpuStart && probeSafely(() => this.cpuUsage(this.cpuStart));
|
|
3382
|
+
if (cpu) {
|
|
3383
|
+
entries.push({
|
|
3384
|
+
name: "frontmcp_process_cpu_seconds_total",
|
|
3385
|
+
value: cpu.user / MICROS_PER_SECOND,
|
|
3386
|
+
attributes: { mode: "user" },
|
|
3387
|
+
help: "CPU time consumed since collector start, by mode (seconds)"
|
|
3388
|
+
});
|
|
3389
|
+
entries.push({
|
|
3390
|
+
name: "frontmcp_process_cpu_seconds_total",
|
|
3391
|
+
value: cpu.system / MICROS_PER_SECOND,
|
|
3392
|
+
attributes: { mode: "system" }
|
|
3393
|
+
});
|
|
3394
|
+
}
|
|
3395
|
+
const mem = probeSafely(() => this.memoryUsage());
|
|
3396
|
+
if (mem) {
|
|
3397
|
+
entries.push({
|
|
3398
|
+
name: "frontmcp_process_resident_memory_bytes",
|
|
3399
|
+
value: mem.rss,
|
|
3400
|
+
help: "Resident memory size in bytes"
|
|
3401
|
+
});
|
|
3402
|
+
entries.push({
|
|
3403
|
+
name: "frontmcp_process_heap_bytes",
|
|
3404
|
+
value: mem.heapTotal,
|
|
3405
|
+
help: "Total V8 heap size in bytes"
|
|
3406
|
+
});
|
|
3407
|
+
entries.push({
|
|
3408
|
+
name: "frontmcp_process_heap_used_bytes",
|
|
3409
|
+
value: mem.heapUsed,
|
|
3410
|
+
help: "Used V8 heap size in bytes"
|
|
3411
|
+
});
|
|
3412
|
+
entries.push({
|
|
3413
|
+
name: "frontmcp_process_external_bytes",
|
|
3414
|
+
value: mem.external,
|
|
3415
|
+
help: "Memory used by C++ objects bound to JS in bytes"
|
|
3416
|
+
});
|
|
3417
|
+
}
|
|
3418
|
+
const uptime = probeSafely(() => this.uptime());
|
|
3419
|
+
if (uptime !== void 0) {
|
|
3420
|
+
entries.push({
|
|
3421
|
+
name: "frontmcp_process_uptime_seconds",
|
|
3422
|
+
value: uptime,
|
|
3423
|
+
help: "Time since process start in seconds"
|
|
3424
|
+
});
|
|
3425
|
+
}
|
|
3426
|
+
const histogram = this.options.eventLoopLag !== false ? this.histogram : void 0;
|
|
3427
|
+
const lag = histogram && probeSafely(() => {
|
|
3428
|
+
const sample = {
|
|
3429
|
+
meanSeconds: histogram.mean / NS_PER_SECOND,
|
|
3430
|
+
p99Seconds: histogram.percentile(99) / NS_PER_SECOND
|
|
3431
|
+
};
|
|
3432
|
+
histogram.reset();
|
|
3433
|
+
return sample;
|
|
3344
3434
|
});
|
|
3345
|
-
if (
|
|
3346
|
-
const meanSeconds
|
|
3347
|
-
const p99Seconds = this.histogram.percentile(99) / NS_PER_SECOND;
|
|
3435
|
+
if (lag) {
|
|
3436
|
+
const { meanSeconds, p99Seconds } = lag;
|
|
3348
3437
|
if (Number.isFinite(meanSeconds)) {
|
|
3349
3438
|
entries.push({
|
|
3350
3439
|
name: "frontmcp_nodejs_eventloop_lag_seconds",
|
|
@@ -3360,7 +3449,6 @@ var ProcessStatsCollector = class {
|
|
|
3360
3449
|
attributes: { quantile: "p99" }
|
|
3361
3450
|
});
|
|
3362
3451
|
}
|
|
3363
|
-
this.histogram.reset();
|
|
3364
3452
|
}
|
|
3365
3453
|
if (this.options.activeHandles !== false) {
|
|
3366
3454
|
const handles = this.getActiveHandles?.();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/observability",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"description": "OpenTelemetry instrumentation, structured JSON logging, and request log objects for FrontMCP",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"@opentelemetry/api": "^1.9.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@frontmcp/sdk": "1.9.
|
|
55
|
-
"@frontmcp/utils": "1.9.
|
|
54
|
+
"@frontmcp/sdk": "1.9.2",
|
|
55
|
+
"@frontmcp/utils": "1.9.2",
|
|
56
56
|
"@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
|
|
57
57
|
"@opentelemetry/sdk-node": "^0.219.0",
|
|
58
58
|
"@opentelemetry/sdk-trace-base": "^2.8.0",
|
|
@@ -25,6 +25,9 @@ export default class ObservabilityPlugin extends DynamicPlugin<ObservabilityPlug
|
|
|
25
25
|
private tracingOpts;
|
|
26
26
|
constructor(options?: ObservabilityPluginOptionsInput);
|
|
27
27
|
private get tracingEnabled();
|
|
28
|
+
private get requestLogsEnabled();
|
|
29
|
+
/** Names the entry a request serves on its request log, and records the entry flow's failure. */
|
|
30
|
+
private annotateRequestLog;
|
|
28
31
|
_httpWillTrace(ctx: unknown): void;
|
|
29
32
|
_httpWillQuota(ctx: unknown): void;
|
|
30
33
|
_httpDidSemaphore(ctx: unknown): void;
|
|
@@ -53,7 +53,7 @@ export declare class ProcessStatsCollector {
|
|
|
53
53
|
private readonly getActiveHandles?;
|
|
54
54
|
private readonly getActiveRequests?;
|
|
55
55
|
private readonly readFdCount;
|
|
56
|
-
private cpuStart
|
|
56
|
+
private cpuStart?;
|
|
57
57
|
constructor(init?: ProcessStatsCollectorOptions);
|
|
58
58
|
collect(): GaugeSnapshotEntry[];
|
|
59
59
|
/**
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RequestLogCollector } from './request-log.collector';
|
|
2
|
+
import type { RequestLogCollectorOptions } from './request-log.types';
|
|
3
|
+
interface RequestLogFlowContext {
|
|
4
|
+
get?(token: unknown): unknown;
|
|
5
|
+
rawInput?: {
|
|
6
|
+
request?: {
|
|
7
|
+
method?: string;
|
|
8
|
+
path?: string;
|
|
9
|
+
body?: unknown;
|
|
10
|
+
};
|
|
11
|
+
response?: {
|
|
12
|
+
statusCode?: unknown;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
state?: Record<string | symbol, unknown>;
|
|
16
|
+
}
|
|
17
|
+
/** The open request log of the request `flowCtx` serves; entry flows annotate it. */
|
|
18
|
+
export declare function currentRequestLog(flowCtx: RequestLogFlowContext): RequestLogCollector | undefined;
|
|
19
|
+
/** Opens the request's log, kept on the request context so the entry flows and log entries reach it. */
|
|
20
|
+
export declare function startRequestLog(flowCtx: RequestLogFlowContext, options: RequestLogCollectorOptions): void;
|
|
21
|
+
/** Records why an entry flow failed (its `state.flowError`) on the request's log. */
|
|
22
|
+
export declare function recordRequestLogFailure(flowCtx: RequestLogFlowContext): void;
|
|
23
|
+
/**
|
|
24
|
+
* Closes the request's log with its HTTP status, which fires `requestLogs.onRequestComplete`: the status the
|
|
25
|
+
* flow responded with (`state.statusCode`), else the one a transport wrote to the response itself.
|
|
26
|
+
*/
|
|
27
|
+
export declare function completeRequestLog(flowCtx: RequestLogFlowContext): Promise<void>;
|
|
28
|
+
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module augmentation for TypeScript — adds `this.telemetry` to every
|
|
3
3
|
* execution context: ExecutionContextBase (ToolContext, ResourceContext,
|
|
4
|
-
* AgentContext, JobContext, SkillContext, ...)
|
|
4
|
+
* AgentContext, JobContext, SkillContext, PromptContext, ...).
|
|
5
5
|
*
|
|
6
6
|
* This file provides type information only. The runtime getter is
|
|
7
7
|
* installed by the SDK's context extension mechanism when the
|
|
8
|
-
* ObservabilityPlugin registers its `contextExtensions`, on
|
|
9
|
-
*
|
|
8
|
+
* ObservabilityPlugin registers its `contextExtensions`, on
|
|
9
|
+
* ExecutionContextBase.prototype, which PromptContext inherits.
|
|
10
10
|
*/
|
|
11
11
|
import type { TelemetryAccessor } from './telemetry.accessor';
|
|
12
12
|
declare module '@frontmcp/sdk' {
|