

























@@ -35,6 +35,19 @@ async function readTimeline(path: string) {
3535.map((line) => JSON.parse(line) as Record<string, unknown>);
3636}
373738+function eventRecord(events: Record<string, unknown>[], index: number): Record<string, unknown> {
39+const event = events[index];
40+expect(event).toBeTruthy();
41+return event;
42+}
43+44+function attributesRecord(event: Record<string, unknown>): Record<string, unknown> {
45+expect(event.attributes).toBeTruthy();
46+expect(typeof event.attributes).toBe("object");
47+expect(Array.isArray(event.attributes)).toBe(false);
48+return event.attributes as Record<string, unknown>;
49+}
50+3851afterEach(async () => {
3952await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
4053});
@@ -122,21 +135,18 @@ describe("diagnostics timeline", () => {
122135);
123136124137const [event] = await readTimeline(path);
125-expect(event).toMatchObject({
126-schemaVersion: "openclaw.diagnostics.v1",
127-type: "mark",
128-name: "gateway.ready",
129-runId: "run-1",
130-envName: "env-1",
131-phase: "startup",
132-attributes: {
133-ok: true,
134-count: 2,
135-},
136-});
138+expect(event?.schemaVersion).toBe("openclaw.diagnostics.v1");
139+expect(event?.type).toBe("mark");
140+expect(event?.name).toBe("gateway.ready");
141+expect(event?.runId).toBe("run-1");
142+expect(event?.envName).toBe("env-1");
143+expect(event?.phase).toBe("startup");
144+const attributes = attributesRecord(event ?? {});
145+expect(attributes.ok).toBe(true);
146+expect(attributes.count).toBe(2);
137147expect(event?.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u);
138148expect(event?.pid).toBe(process.pid);
139-expect((event?.attributes as Record<string, unknown>).ignored).toBeUndefined();
149+expect(attributes.ignored).toBeUndefined();
140150});
141151142152it("records span start and end events around successful work", async () => {
@@ -155,20 +165,18 @@ describe("diagnostics timeline", () => {
155165156166const events = await readTimeline(path);
157167expect(events).toHaveLength(2);
158-expect(events[0]).toMatchObject({
159-type: "span.start",
160-name: "runtimeDeps.stage",
161-phase: "startup",
162-attributes: { pluginCount: 3 },
163-});
164-expect(events[1]).toMatchObject({
165-type: "span.end",
166-name: "runtimeDeps.stage",
167-phase: "startup",
168-attributes: { pluginCount: 3 },
169-});
170-expect(events[1]?.spanId).toBe(events[0]?.spanId);
171-expect(events[1]?.durationMs).toBeGreaterThanOrEqual(0);
168+const start = eventRecord(events, 0);
169+const end = eventRecord(events, 1);
170+expect(start.type).toBe("span.start");
171+expect(start.name).toBe("runtimeDeps.stage");
172+expect(start.phase).toBe("startup");
173+expect(attributesRecord(start).pluginCount).toBe(3);
174+expect(end.type).toBe("span.end");
175+expect(end.name).toBe("runtimeDeps.stage");
176+expect(end.phase).toBe("startup");
177+expect(attributesRecord(end).pluginCount).toBe(3);
178+expect(end.spanId).toBe(start.spanId);
179+expect(end.durationMs).toBeGreaterThanOrEqual(0);
172180});
173181174182it("records span error events and rethrows failures", async () => {
@@ -186,13 +194,12 @@ describe("diagnostics timeline", () => {
186194187195const events = await readTimeline(path);
188196expect(events).toHaveLength(2);
189-expect(events[1]).toMatchObject({
190-type: "span.error",
191-name: "plugins.load",
192-phase: "startup",
193-errorName: "TypeError",
194-errorMessage: "bad plugin",
195-});
197+const errorEvent = eventRecord(events, 1);
198+expect(errorEvent.type).toBe("span.error");
199+expect(errorEvent.name).toBe("plugins.load");
200+expect(errorEvent.phase).toBe("startup");
201+expect(errorEvent.errorName).toBe("TypeError");
202+expect(errorEvent.errorMessage).toBe("bad plugin");
196203});
197204198205it("records synchronous spans", async () => {
@@ -206,14 +213,12 @@ describe("diagnostics timeline", () => {
206213expect(result).toBe(42);
207214const events = await readTimeline(path);
208215expect(events).toHaveLength(2);
209-expect(events[0]).toMatchObject({
210-type: "span.start",
211-name: "plugins.metadata.scan",
212-});
213-expect(events[1]).toMatchObject({
214-type: "span.end",
215-name: "plugins.metadata.scan",
216-});
216+const start = eventRecord(events, 0);
217+const end = eventRecord(events, 1);
218+expect(start.type).toBe("span.start");
219+expect(start.name).toBe("plugins.metadata.scan");
220+expect(end.type).toBe("span.end");
221+expect(end.name).toBe("plugins.metadata.scan");
217222});
218223219224it("lets nested spans inherit the active timeline phase and parent span", async () => {
@@ -235,27 +240,19 @@ describe("diagnostics timeline", () => {
235240const events = await readTimeline(path);
236241expect(events).toHaveLength(4);
237242const [parentStart, childStart, childEnd, parentEnd] = events;
238-expect(parentStart).toMatchObject({
239-type: "span.start",
240-name: "reply.run_agent_turn",
241-phase: "agent-turn",
242-});
243-expect(childStart).toMatchObject({
244-type: "span.start",
245-name: "plugins.metadata.scan",
246-phase: "agent-turn",
247-parentSpanId: parentStart?.spanId,
248-});
249-expect(childEnd).toMatchObject({
250-type: "span.end",
251-name: "plugins.metadata.scan",
252-phase: "agent-turn",
253-parentSpanId: parentStart?.spanId,
254-});
255-expect(parentEnd).toMatchObject({
256-type: "span.end",
257-name: "reply.run_agent_turn",
258-phase: "agent-turn",
259-});
243+expect(parentStart?.type).toBe("span.start");
244+expect(parentStart?.name).toBe("reply.run_agent_turn");
245+expect(parentStart?.phase).toBe("agent-turn");
246+expect(childStart?.type).toBe("span.start");
247+expect(childStart?.name).toBe("plugins.metadata.scan");
248+expect(childStart?.phase).toBe("agent-turn");
249+expect(childStart?.parentSpanId).toBe(parentStart?.spanId);
250+expect(childEnd?.type).toBe("span.end");
251+expect(childEnd?.name).toBe("plugins.metadata.scan");
252+expect(childEnd?.phase).toBe("agent-turn");
253+expect(childEnd?.parentSpanId).toBe(parentStart?.spanId);
254+expect(parentEnd?.type).toBe("span.end");
255+expect(parentEnd?.name).toBe("reply.run_agent_turn");
256+expect(parentEnd?.phase).toBe("agent-turn");
260257});
261258});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。