71 lines
2.6 KiB
TypeScript
71 lines
2.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { RecordingTracer } from "@/instrumentation/recording-tracer";
|
|
|
|
describe("RecordingTracer", () => {
|
|
it("records every startSpan call with name, op, attributes, status, durationMs", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await tracer.startSpan(
|
|
{ name: "blog.getArticles", op: "use-case", attributes: { limit: 10 } },
|
|
async (span) => {
|
|
span.setAttribute("count", 3);
|
|
span.setStatus("ok");
|
|
return undefined;
|
|
},
|
|
);
|
|
expect(tracer.spans).toHaveLength(1);
|
|
const s = tracer.spans[0]!;
|
|
expect(s.name).toBe("blog.getArticles");
|
|
expect(s.op).toBe("use-case");
|
|
expect(s.attributes).toMatchObject({ limit: 10, count: 3 });
|
|
expect(s.status).toBe("ok");
|
|
expect(typeof s.durationMs).toBe("number");
|
|
expect(s.durationMs).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
it("records error status when fn throws", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await expect(
|
|
tracer.startSpan({ name: "x" }, async () => {
|
|
throw new Error("boom");
|
|
}),
|
|
).rejects.toThrow("boom");
|
|
expect(tracer.spans).toHaveLength(1);
|
|
expect(tracer.spans[0]!.status).toBe("error");
|
|
expect(tracer.spans[0]!.statusMessage).toBe("boom");
|
|
});
|
|
|
|
it("records error status when set explicitly via span.setStatus", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await tracer.startSpan({ name: "x" }, async (span) => {
|
|
span.setStatus("error", "validation failed");
|
|
return undefined;
|
|
});
|
|
expect(tracer.spans[0]!.status).toBe("error");
|
|
expect(tracer.spans[0]!.statusMessage).toBe("validation failed");
|
|
});
|
|
|
|
it("reset() clears recorded spans", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await tracer.startSpan({ name: "x" }, async () => undefined);
|
|
expect(tracer.spans).toHaveLength(1);
|
|
tracer.reset();
|
|
expect(tracer.spans).toHaveLength(0);
|
|
});
|
|
|
|
it("findSpan returns first matching span by name", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await tracer.startSpan({ name: "a" }, async () => undefined);
|
|
await tracer.startSpan({ name: "b" }, async () => undefined);
|
|
expect(tracer.findSpan("b")).toBeDefined();
|
|
expect(tracer.findSpan("missing")).toBeUndefined();
|
|
});
|
|
|
|
it("nested spans are recorded in order (children appear after parent end)", async () => {
|
|
const tracer = new RecordingTracer();
|
|
await tracer.startSpan({ name: "parent" }, async () => {
|
|
await tracer.startSpan({ name: "child" }, async () => undefined);
|
|
});
|
|
expect(tracer.spans.map((s) => s.name)).toEqual(["child", "parent"]);
|
|
});
|
|
});
|