2026-06-02 17:23:51 +02:00
|
|
|
import { formatErrorDetail, scrubErrorClass } from './scrubber.js';
|
2026-05-22 18:18:47 +02:00
|
|
|
|
|
|
|
|
export type CommandOutcome = 'ok' | 'error' | 'aborted';
|
|
|
|
|
|
|
|
|
|
interface CommandSpan {
|
|
|
|
|
commandPath: string[];
|
|
|
|
|
flagsPresent: Record<string, boolean>;
|
|
|
|
|
projectDir?: string;
|
|
|
|
|
hasProject: boolean;
|
|
|
|
|
attachProjectGroup: boolean;
|
|
|
|
|
startedAt: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CompletedCommandSpan {
|
|
|
|
|
commandPath: string[];
|
|
|
|
|
durationMs: number;
|
|
|
|
|
outcome: CommandOutcome;
|
|
|
|
|
errorClass?: string;
|
2026-06-02 17:23:51 +02:00
|
|
|
errorDetail?: string;
|
2026-05-22 18:18:47 +02:00
|
|
|
flagsPresent: Record<string, boolean>;
|
|
|
|
|
hasProject: boolean;
|
|
|
|
|
projectDir?: string;
|
|
|
|
|
projectGroupAttached: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let activeCommandSpan: CommandSpan | undefined;
|
|
|
|
|
|
|
|
|
|
export function beginCommandSpan(input: CommandSpan): void {
|
|
|
|
|
activeCommandSpan = input;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function completeCommandSpan(input: {
|
|
|
|
|
completedAt: number;
|
|
|
|
|
outcome: CommandOutcome;
|
|
|
|
|
error?: unknown;
|
|
|
|
|
}): CompletedCommandSpan | undefined {
|
|
|
|
|
const span = activeCommandSpan;
|
|
|
|
|
activeCommandSpan = undefined;
|
|
|
|
|
if (!span) {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const errorClass = input.error ? scrubErrorClass(input.error) : undefined;
|
2026-06-02 17:23:51 +02:00
|
|
|
const errorDetail = input.error ? formatErrorDetail(input.error) : undefined;
|
2026-05-22 18:18:47 +02:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
commandPath: span.commandPath,
|
|
|
|
|
durationMs: Math.max(0, input.completedAt - span.startedAt),
|
|
|
|
|
outcome: input.outcome,
|
|
|
|
|
...(errorClass ? { errorClass } : {}),
|
2026-06-02 17:23:51 +02:00
|
|
|
...(errorDetail ? { errorDetail } : {}),
|
2026-05-22 18:18:47 +02:00
|
|
|
flagsPresent: span.flagsPresent,
|
|
|
|
|
hasProject: span.hasProject,
|
|
|
|
|
projectDir: span.projectDir,
|
|
|
|
|
projectGroupAttached: span.attachProjectGroup,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
|
export function resetCommandSpan(): void {
|
|
|
|
|
activeCommandSpan = undefined;
|
|
|
|
|
}
|