mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-14 12:43:42 +01:00
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import type { Flow } from "@yaakapp-internal/proxy-lib";
|
|
|
|
export type PhaseKind = "start" | "step" | "end" | "error" | "cancelled";
|
|
|
|
/** One row of a flow's Timeline: a moment in the exchange, and how long it took to reach it */
|
|
export interface FlowPhase {
|
|
key: string;
|
|
label: string;
|
|
kind: PhaseKind;
|
|
/** Milliseconds from the start */
|
|
atMs: number;
|
|
/** Milliseconds since the phase before */
|
|
tookMs: number;
|
|
detail?: string;
|
|
}
|
|
|
|
export type PhaseFlow = Pick<
|
|
Flow,
|
|
| "elapsedHeadersMs"
|
|
| "elapsedMs"
|
|
| "status"
|
|
| "error"
|
|
| "cancelled"
|
|
| "streamKind"
|
|
| "elapsedConnectMs"
|
|
| "elapsedTlsMs"
|
|
| "elapsedRequestMs"
|
|
>;
|
|
|
|
/**
|
|
* The phases the engine recorded for a flow, in order: started, connected, TLS, request sent,
|
|
* headers, and how it ended. A phase the engine has no time for is left out; an open flow has
|
|
* no end yet.
|
|
*/
|
|
export function flowPhases(flow: PhaseFlow): FlowPhase[] {
|
|
const steps: Omit<FlowPhase, "tookMs">[] = [
|
|
{ key: "start", label: "Started", kind: "start", atMs: 0 },
|
|
];
|
|
const add = (key: string, label: string, atMs: number | null | undefined) => {
|
|
if (atMs != null) steps.push({ key, label, kind: "step", atMs });
|
|
};
|
|
add("connect", "Connected", flow.elapsedConnectMs);
|
|
add("tls", "TLS handshake", flow.elapsedTlsMs);
|
|
add("request", "Request sent", flow.elapsedRequestMs);
|
|
add(
|
|
"headers",
|
|
flow.status == null ? "Headers received" : `Headers received, ${flow.status}`,
|
|
flow.elapsedHeadersMs,
|
|
);
|
|
|
|
if (flow.elapsedMs != null || flow.error != null || flow.cancelled) {
|
|
const atMs = flow.elapsedMs ?? steps[steps.length - 1]?.atMs ?? 0;
|
|
if (flow.error != null) {
|
|
steps.push({ key: "end", label: "Failed", kind: "error", atMs, detail: flow.error });
|
|
} else if (flow.cancelled) {
|
|
steps.push({ key: "end", label: "Cancelled", kind: "cancelled", atMs });
|
|
} else {
|
|
const label = flow.streamKind == null ? "Body received" : "Closed";
|
|
steps.push({ key: "end", label, kind: "end", atMs });
|
|
}
|
|
}
|
|
|
|
// Times come from different clocks in the engine; keep them in order regardless
|
|
steps.sort((a, b) => a.atMs - b.atMs);
|
|
return steps.map((s, i) => ({ ...s, tookMs: i === 0 ? 0 : s.atMs - (steps[i - 1]?.atMs ?? 0) }));
|
|
}
|