






















@@ -70,6 +70,13 @@ export type ActiveDiagnosticsTimelineSpan = {
7070attributes?: DiagnosticsTimelineAttributes;
7171};
727273+type StartedDiagnosticsTimelineSpan = ActiveDiagnosticsTimelineSpan & {
74+config?: OpenClawConfig;
75+env: NodeJS.ProcessEnv;
76+startedAt: number;
77+omitErrorMessage?: boolean;
78+};
79+7380let warnedAboutTimelineWrite = false;
7481const createdTimelineDirs = new Set<string>();
7582const activeDiagnosticsTimelineSpan = new AsyncLocalStorage<ActiveDiagnosticsTimelineSpan>();
@@ -192,72 +199,107 @@ export function getActiveDiagnosticsTimelineSpan(): ActiveDiagnosticsTimelineSpa
192199return activeDiagnosticsTimelineSpan.getStore();
193200}
194201195-export async function measureDiagnosticsTimelineSpan<T>(
202+function startDiagnosticsTimelineSpan(
196203name: string,
197-run: () => Promise<T> | T,
198-options: DiagnosticsTimelineSpanOptions = {},
199-): Promise<T> {
204+options: DiagnosticsTimelineSpanOptions,
205+): StartedDiagnosticsTimelineSpan | undefined {
200206const env = options.env ?? process.env;
201207if (!isDiagnosticsTimelineEnabled({ config: options.config, env })) {
202-return await run();
208+return undefined;
203209}
204210const activeSpan = getActiveDiagnosticsTimelineSpan();
205-const spanId = randomUUID();
206211const phase = options.phase ?? activeSpan?.phase;
207212const parentSpanId = options.parentSpanId ?? activeSpan?.spanId;
208-const startedAt = performance.now();
213+const span: StartedDiagnosticsTimelineSpan = {
214+ name,
215+ env,
216+ ...(options.config ? { config: options.config } : {}),
217+spanId: randomUUID(),
218+startedAt: performance.now(),
219+ ...(phase ? { phase } : {}),
220+ ...(parentSpanId ? { parentSpanId } : {}),
221+ ...(options.attributes ? { attributes: options.attributes } : {}),
222+ ...(options.omitErrorMessage ? { omitErrorMessage: true } : {}),
223+};
209224emitDiagnosticsTimelineEvent(
210225{
211226type: "span.start",
212- name,
213- phase,
214- spanId,
215- parentSpanId,
216-attributes: options.attributes,
227+name: span.name,
228+phase: span.phase,
229+spanId: span.spanId,
230+parentSpanId: span.parentSpanId,
231+attributes: span.attributes,
217232},
218-{ config: options.config, env },
233+{ config: span.config, env: span.env },
219234);
235+return span;
236+}
237+238+function runInDiagnosticsTimelineSpan<T>(span: StartedDiagnosticsTimelineSpan, run: () => T): T {
239+return activeDiagnosticsTimelineSpan.run(
240+{
241+name: span.name,
242+ ...(span.phase ? { phase: span.phase } : {}),
243+spanId: span.spanId,
244+ ...(span.parentSpanId ? { parentSpanId: span.parentSpanId } : {}),
245+ ...(span.attributes ? { attributes: span.attributes } : {}),
246+},
247+run,
248+);
249+}
250+251+function emitFinishedDiagnosticsTimelineSpan(span: StartedDiagnosticsTimelineSpan): void {
252+emitDiagnosticsTimelineEvent(
253+{
254+type: "span.end",
255+name: span.name,
256+phase: span.phase,
257+spanId: span.spanId,
258+parentSpanId: span.parentSpanId,
259+durationMs: performance.now() - span.startedAt,
260+attributes: span.attributes,
261+},
262+{ config: span.config, env: span.env },
263+);
264+}
265+266+function emitFailedDiagnosticsTimelineSpan(
267+span: StartedDiagnosticsTimelineSpan,
268+error: unknown,
269+): void {
270+emitDiagnosticsTimelineEvent(
271+{
272+type: "span.error",
273+name: span.name,
274+phase: span.phase,
275+spanId: span.spanId,
276+parentSpanId: span.parentSpanId,
277+durationMs: performance.now() - span.startedAt,
278+attributes: span.attributes,
279+errorName: error instanceof Error ? error.name : typeof error,
280+ ...(span.omitErrorMessage
281+ ? {}
282+ : { errorMessage: error instanceof Error ? error.message : String(error) }),
283+},
284+{ config: span.config, env: span.env },
285+);
286+}
287+288+export async function measureDiagnosticsTimelineSpan<T>(
289+name: string,
290+run: () => Promise<T> | T,
291+options: DiagnosticsTimelineSpanOptions = {},
292+): Promise<T> {
293+const span = startDiagnosticsTimelineSpan(name, options);
294+if (!span) {
295+return await run();
296+}
220297try {
221-const result = await activeDiagnosticsTimelineSpan.run(
222-{
223- name,
224- ...(phase ? { phase } : {}),
225- spanId,
226- ...(parentSpanId ? { parentSpanId } : {}),
227- ...(options.attributes ? { attributes: options.attributes } : {}),
228-},
229-() => run(),
230-);
231-emitDiagnosticsTimelineEvent(
232-{
233-type: "span.end",
234- name,
235- phase,
236- spanId,
237- parentSpanId,
238-durationMs: performance.now() - startedAt,
239-attributes: options.attributes,
240-},
241-{ config: options.config, env },
242-);
298+const result = await runInDiagnosticsTimelineSpan(span, () => run());
299+emitFinishedDiagnosticsTimelineSpan(span);
243300return result;
244301} catch (error) {
245-emitDiagnosticsTimelineEvent(
246-{
247-type: "span.error",
248- name,
249- phase,
250- spanId,
251- parentSpanId,
252-durationMs: performance.now() - startedAt,
253-attributes: options.attributes,
254-errorName: error instanceof Error ? error.name : typeof error,
255- ...(options.omitErrorMessage
256- ? {}
257- : { errorMessage: error instanceof Error ? error.message : String(error) }),
258-},
259-{ config: options.config, env },
260-);
302+emitFailedDiagnosticsTimelineSpan(span, error);
261303throw error;
262304}
263305}
@@ -267,67 +309,16 @@ export function measureDiagnosticsTimelineSpanSync<T>(
267309run: () => T,
268310options: DiagnosticsTimelineSpanOptions = {},
269311): T {
270-const env = options.env ?? process.env;
271-if (!isDiagnosticsTimelineEnabled({ config: options.config, env })) {
312+const span = startDiagnosticsTimelineSpan(name, options);
313+if (!span) {
272314return run();
273315}
274-const activeSpan = getActiveDiagnosticsTimelineSpan();
275-const spanId = randomUUID();
276-const phase = options.phase ?? activeSpan?.phase;
277-const parentSpanId = options.parentSpanId ?? activeSpan?.spanId;
278-const startedAt = performance.now();
279-emitDiagnosticsTimelineEvent(
280-{
281-type: "span.start",
282- name,
283- phase,
284- spanId,
285- parentSpanId,
286-attributes: options.attributes,
287-},
288-{ config: options.config, env },
289-);
290316try {
291-const result = activeDiagnosticsTimelineSpan.run(
292-{
293- name,
294- ...(phase ? { phase } : {}),
295- spanId,
296- ...(parentSpanId ? { parentSpanId } : {}),
297- ...(options.attributes ? { attributes: options.attributes } : {}),
298-},
299-run,
300-);
301-emitDiagnosticsTimelineEvent(
302-{
303-type: "span.end",
304- name,
305- phase,
306- spanId,
307- parentSpanId,
308-durationMs: performance.now() - startedAt,
309-attributes: options.attributes,
310-},
311-{ config: options.config, env },
312-);
317+const result = runInDiagnosticsTimelineSpan(span, run);
318+emitFinishedDiagnosticsTimelineSpan(span);
313319return result;
314320} catch (error) {
315-emitDiagnosticsTimelineEvent(
316-{
317-type: "span.error",
318- name,
319- phase,
320- spanId,
321- parentSpanId,
322-durationMs: performance.now() - startedAt,
323-attributes: options.attributes,
324-errorName: error instanceof Error ? error.name : typeof error,
325- ...(options.omitErrorMessage
326- ? {}
327- : { errorMessage: error instanceof Error ? error.message : String(error) }),
328-},
329-{ config: options.config, env },
330-);
321+emitFailedDiagnosticsTimelineSpan(span, error);
331322throw error;
332323}
333324}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。