feat(perf): add performance.mark/measure to SSE pipeline + request-size metric

- streamingPipeline.ts: mark/measure around assembly of SSE transform
  chain — 'omni-pipeline-start'/'omni-pipeline-end'/'omni-pipeline'
- stream.ts: compute JSON body byte count on stream creation, emit as
  performance.mark('omni-request-body-size', { detail: bytes })

Marks are visible via performance.getEntriesByType('mark') and
performance.getEntriesByType('measure') for DevTools/monitoring.
This commit is contained in:
oyi77
2026-07-13 19:44:35 +07:00
parent dee97504ef
commit b48ba21c42
2 changed files with 27 additions and 1 deletions

View File

@@ -23,6 +23,17 @@ import { createPiiSseTransform as defaultPiiSse } from "@/lib/streamingPiiTransf
import { isFeatureFlagEnabled as defaultFeatureFlag } from "@/shared/utils/featureFlags";
import { OMNIROUTE_RESPONSE_HEADERS } from "@/shared/constants/headers";
import { SSE_HEARTBEAT_INTERVAL_MS } from "../../config/constants.ts";
/**
* Pipeline assembly instrumentation — performance.mark() along the SSE hot path.
* Marks are visible to Node.js perf_hooks consumers and DevTools' Performance
* panel when NODE_OPTIONS=--enable-node-performance-clinician or similar.
*
* Each call to assembleStreamingPipeline creates one measure record:
* "omni-pipeline" — wall-clock duration of the full transform chain assembly.
*/
const PIPELINE_START = "omni-pipeline-start";
const PIPELINE_END = "omni-pipeline-end";
const PIPELINE_MEASURE = "omni-pipeline";
type HeadersLike = Headers | Record<string, unknown> | null | undefined;
@@ -61,6 +72,7 @@ export function assembleStreamingPipeline(
},
deps: StreamingPipelineDeps = DEFAULT_DEPS
) {
performance.mark(PIPELINE_START);
// ── Phase 9.3: Progress tracking (opt-in) ──
const progressEnabled = deps.wantsProgress(args.clientRawRequestHeaders);
let finalStream;
@@ -77,7 +89,9 @@ export function assembleStreamingPipeline(
}
if (progressEnabled) {
const progressTransform = deps.createProgressTransform({ signal: args.streamController.signal });
const progressTransform = deps.createProgressTransform({
signal: args.streamController.signal,
});
// Chain: provider → transform → progress → client
finalStream = piiStream.pipeThrough(progressTransform);
args.responseHeaders[OMNIROUTE_RESPONSE_HEADERS.progress] = "enabled";
@@ -95,5 +109,7 @@ export function assembleStreamingPipeline(
if (args.echoModel) {
finalStream = finalStream.pipeThrough(deps.createModelEchoTransform(args.echoModel));
}
performance.mark(PIPELINE_END);
performance.measure(PIPELINE_MEASURE, PIPELINE_START, PIPELINE_END);
return finalStream;
}

View File

@@ -639,6 +639,16 @@ export function createSSEStream(options: StreamOptions = {}) {
dropResponsesCommentary,
} = options;
const signatureNamespace = connectionId;
// Request-body-size metric (for monitoring payload size distribution & correlation with TTFT).
// The size is JSON-serialised byte count; stored as a performance mark detail so monitoring
// tools can query performance.getEntriesByType("mark") filtered by name.
let bodySize = 0;
try {
bodySize = body ? new TextEncoder().encode(JSON.stringify(body)).length : 0;
} catch {
/* body may not be JSON-serialisable (e.g. FormData, Blob) — metric stays 0 */
}
if (bodySize > 0) performance.mark("omni-request-body-size", { detail: bodySize });
// Drop internal commentary-phase Responses output before forwarding (#6199).
// Explicit option wins; otherwise read the feature flag (default on). Resolved