mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 16:44:05 +00:00
refactor: share diagnostics timeline span helpers
This commit is contained in:
@@ -70,6 +70,13 @@ export type ActiveDiagnosticsTimelineSpan = {
|
||||
attributes?: DiagnosticsTimelineAttributes;
|
||||
};
|
||||
|
||||
type StartedDiagnosticsTimelineSpan = ActiveDiagnosticsTimelineSpan & {
|
||||
config?: OpenClawConfig;
|
||||
env: NodeJS.ProcessEnv;
|
||||
startedAt: number;
|
||||
omitErrorMessage?: boolean;
|
||||
};
|
||||
|
||||
let warnedAboutTimelineWrite = false;
|
||||
const createdTimelineDirs = new Set<string>();
|
||||
const activeDiagnosticsTimelineSpan = new AsyncLocalStorage<ActiveDiagnosticsTimelineSpan>();
|
||||
@@ -192,72 +199,107 @@ export function getActiveDiagnosticsTimelineSpan(): ActiveDiagnosticsTimelineSpa
|
||||
return activeDiagnosticsTimelineSpan.getStore();
|
||||
}
|
||||
|
||||
function startDiagnosticsTimelineSpan(
|
||||
name: string,
|
||||
options: DiagnosticsTimelineSpanOptions,
|
||||
): StartedDiagnosticsTimelineSpan | undefined {
|
||||
const env = options.env ?? process.env;
|
||||
if (!isDiagnosticsTimelineEnabled({ config: options.config, env })) {
|
||||
return undefined;
|
||||
}
|
||||
const activeSpan = getActiveDiagnosticsTimelineSpan();
|
||||
const phase = options.phase ?? activeSpan?.phase;
|
||||
const parentSpanId = options.parentSpanId ?? activeSpan?.spanId;
|
||||
const span: StartedDiagnosticsTimelineSpan = {
|
||||
name,
|
||||
env,
|
||||
...(options.config ? { config: options.config } : {}),
|
||||
spanId: randomUUID(),
|
||||
startedAt: performance.now(),
|
||||
...(phase ? { phase } : {}),
|
||||
...(parentSpanId ? { parentSpanId } : {}),
|
||||
...(options.attributes ? { attributes: options.attributes } : {}),
|
||||
...(options.omitErrorMessage ? { omitErrorMessage: true } : {}),
|
||||
};
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.start",
|
||||
name: span.name,
|
||||
phase: span.phase,
|
||||
spanId: span.spanId,
|
||||
parentSpanId: span.parentSpanId,
|
||||
attributes: span.attributes,
|
||||
},
|
||||
{ config: span.config, env: span.env },
|
||||
);
|
||||
return span;
|
||||
}
|
||||
|
||||
function runInDiagnosticsTimelineSpan<T>(span: StartedDiagnosticsTimelineSpan, run: () => T): T {
|
||||
return activeDiagnosticsTimelineSpan.run(
|
||||
{
|
||||
name: span.name,
|
||||
...(span.phase ? { phase: span.phase } : {}),
|
||||
spanId: span.spanId,
|
||||
...(span.parentSpanId ? { parentSpanId: span.parentSpanId } : {}),
|
||||
...(span.attributes ? { attributes: span.attributes } : {}),
|
||||
},
|
||||
run,
|
||||
);
|
||||
}
|
||||
|
||||
function emitFinishedDiagnosticsTimelineSpan(span: StartedDiagnosticsTimelineSpan): void {
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.end",
|
||||
name: span.name,
|
||||
phase: span.phase,
|
||||
spanId: span.spanId,
|
||||
parentSpanId: span.parentSpanId,
|
||||
durationMs: performance.now() - span.startedAt,
|
||||
attributes: span.attributes,
|
||||
},
|
||||
{ config: span.config, env: span.env },
|
||||
);
|
||||
}
|
||||
|
||||
function emitFailedDiagnosticsTimelineSpan(
|
||||
span: StartedDiagnosticsTimelineSpan,
|
||||
error: unknown,
|
||||
): void {
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.error",
|
||||
name: span.name,
|
||||
phase: span.phase,
|
||||
spanId: span.spanId,
|
||||
parentSpanId: span.parentSpanId,
|
||||
durationMs: performance.now() - span.startedAt,
|
||||
attributes: span.attributes,
|
||||
errorName: error instanceof Error ? error.name : typeof error,
|
||||
...(span.omitErrorMessage
|
||||
? {}
|
||||
: { errorMessage: error instanceof Error ? error.message : String(error) }),
|
||||
},
|
||||
{ config: span.config, env: span.env },
|
||||
);
|
||||
}
|
||||
|
||||
export async function measureDiagnosticsTimelineSpan<T>(
|
||||
name: string,
|
||||
run: () => Promise<T> | T,
|
||||
options: DiagnosticsTimelineSpanOptions = {},
|
||||
): Promise<T> {
|
||||
const env = options.env ?? process.env;
|
||||
if (!isDiagnosticsTimelineEnabled({ config: options.config, env })) {
|
||||
const span = startDiagnosticsTimelineSpan(name, options);
|
||||
if (!span) {
|
||||
return await run();
|
||||
}
|
||||
const activeSpan = getActiveDiagnosticsTimelineSpan();
|
||||
const spanId = randomUUID();
|
||||
const phase = options.phase ?? activeSpan?.phase;
|
||||
const parentSpanId = options.parentSpanId ?? activeSpan?.spanId;
|
||||
const startedAt = performance.now();
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.start",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
attributes: options.attributes,
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
try {
|
||||
const result = await activeDiagnosticsTimelineSpan.run(
|
||||
{
|
||||
name,
|
||||
...(phase ? { phase } : {}),
|
||||
spanId,
|
||||
...(parentSpanId ? { parentSpanId } : {}),
|
||||
...(options.attributes ? { attributes: options.attributes } : {}),
|
||||
},
|
||||
() => run(),
|
||||
);
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.end",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
durationMs: performance.now() - startedAt,
|
||||
attributes: options.attributes,
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
const result = await runInDiagnosticsTimelineSpan(span, () => run());
|
||||
emitFinishedDiagnosticsTimelineSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.error",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
durationMs: performance.now() - startedAt,
|
||||
attributes: options.attributes,
|
||||
errorName: error instanceof Error ? error.name : typeof error,
|
||||
...(options.omitErrorMessage
|
||||
? {}
|
||||
: { errorMessage: error instanceof Error ? error.message : String(error) }),
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
emitFailedDiagnosticsTimelineSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -267,67 +309,16 @@ export function measureDiagnosticsTimelineSpanSync<T>(
|
||||
run: () => T,
|
||||
options: DiagnosticsTimelineSpanOptions = {},
|
||||
): T {
|
||||
const env = options.env ?? process.env;
|
||||
if (!isDiagnosticsTimelineEnabled({ config: options.config, env })) {
|
||||
const span = startDiagnosticsTimelineSpan(name, options);
|
||||
if (!span) {
|
||||
return run();
|
||||
}
|
||||
const activeSpan = getActiveDiagnosticsTimelineSpan();
|
||||
const spanId = randomUUID();
|
||||
const phase = options.phase ?? activeSpan?.phase;
|
||||
const parentSpanId = options.parentSpanId ?? activeSpan?.spanId;
|
||||
const startedAt = performance.now();
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.start",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
attributes: options.attributes,
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
try {
|
||||
const result = activeDiagnosticsTimelineSpan.run(
|
||||
{
|
||||
name,
|
||||
...(phase ? { phase } : {}),
|
||||
spanId,
|
||||
...(parentSpanId ? { parentSpanId } : {}),
|
||||
...(options.attributes ? { attributes: options.attributes } : {}),
|
||||
},
|
||||
run,
|
||||
);
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.end",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
durationMs: performance.now() - startedAt,
|
||||
attributes: options.attributes,
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
const result = runInDiagnosticsTimelineSpan(span, run);
|
||||
emitFinishedDiagnosticsTimelineSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
emitDiagnosticsTimelineEvent(
|
||||
{
|
||||
type: "span.error",
|
||||
name,
|
||||
phase,
|
||||
spanId,
|
||||
parentSpanId,
|
||||
durationMs: performance.now() - startedAt,
|
||||
attributes: options.attributes,
|
||||
errorName: error instanceof Error ? error.name : typeof error,
|
||||
...(options.omitErrorMessage
|
||||
? {}
|
||||
: { errorMessage: error instanceof Error ? error.message : String(error) }),
|
||||
},
|
||||
{ config: options.config, env },
|
||||
);
|
||||
emitFailedDiagnosticsTimelineSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user