AkurAI Build
Menu

popagent

public

Latest change 0ea30ecfc0b99682425d7170ee77bf5bcf8ace06 - Add range, filter, and paging controls to the Observability page by AkurAI Build

import { expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import type { ObservabilityLog, ObservabilityTraceSpan, ObservabilityTraceSummary } from "../api-types";
import {
  filterLogs,
  filterTraces,
  formatDuration,
  groupTraces,
  observabilityRangeQuery,
  ObservabilitySummary,
  relativeTime,
  spanTimeline,
} from "./ObservabilityPage";

test("renders current process memory in MiB", () => {
  const html = renderToStaticMarkup(<ObservabilitySummary overview={{
    from: "2026-08-14T00:00:00.000Z",
    to: "2026-08-15T00:00:00.000Z",
    runs: 12,
    errors: 1,
    errorRate: 1 / 12,
    p95LatencyMs: 420,
    inputTokens: 1_200,
    outputTokens: 340,
    processRssBytes: 73_400_320,
    processHeapUsedBytes: 31_457_280,
  }} />);

  expect(html).toContain("Process RSS");
  expect(html).toContain("70.0 MiB");
  expect(html).toContain("Heap used");
  expect(html).toContain("30.0 MiB");
});

test("builds a bounded query window for each selectable range", () => {
  const now = new Date("2026-08-16T12:00:00.000Z");
  expect(observabilityRangeQuery("1h", now)).toBe("from=2026-08-16T11:00:00.000Z&to=2026-08-16T12:00:00.000Z");
  expect(observabilityRangeQuery("30d", now)).toBe("from=2026-07-17T12:00:00.000Z&to=2026-08-16T12:00:00.000Z");
});

test("formats durations and relative times for operators", () => {
  expect(formatDuration(null)).toBe("running");
  expect(formatDuration(412)).toBe("412 ms");
  expect(formatDuration(12_600)).toBe("12.6 s");
  expect(formatDuration(205_020)).toBe("3m 25s");
  const now = new Date("2026-08-16T12:00:00.000Z");
  expect(relativeTime("2026-08-16T11:59:30.000Z", now)).toBe("30s ago");
  expect(relativeTime("2026-08-16T09:00:00.000Z", now)).toBe("3h ago");
});

const trace = (overrides: Partial<ObservabilityTraceSummary>): ObservabilityTraceSummary => ({
  traceId: "a".repeat(32),
  name: "agent run",
  entityName: "Orchistrator",
  status: "success",
  startedAt: "2026-08-16T11:00:00.000Z",
  endedAt: "2026-08-16T11:00:10.000Z",
  durationMs: 10_000,
  tags: [],
  metadata: {},
  ...overrides,
});

test("collapses repeated root spans into one row per trace", () => {
  const groups = groupTraces([
    trace({}),
    trace({ startedAt: "2026-08-16T10:59:00.000Z", durationMs: 61_000, status: "error" }),
    trace({ traceId: "b".repeat(32), entityName: "Implementer" }),
  ]);

  expect(groups).toHaveLength(2);
  expect(groups[0]).toMatchObject({ status: "error", rootCount: 2, durationMs: 61_000, startedAt: "2026-08-16T10:59:00.000Z" });
  expect(filterTraces(groups, "error", "")).toHaveLength(1);
  expect(filterTraces(groups, "all", "implementer")).toHaveLength(1);
  expect(filterTraces(groups, "all", "nothing")).toHaveLength(0);
});

test("filters logs by level and message text", () => {
  const logs: ObservabilityLog[] = [
    { id: "1", timestamp: "2026-08-16T11:00:00.000Z", level: "warn", message: "task retry", traceId: null, spanId: null, entityName: null, data: {} },
    { id: "2", timestamp: "2026-08-16T11:01:00.000Z", level: "error", message: "connection timeout", traceId: "c".repeat(32), spanId: null, entityName: null, data: {} },
  ];

  expect(filterLogs(logs, [], "")).toHaveLength(2);
  expect(filterLogs(logs, ["error"], "")).toHaveLength(1);
  expect(filterLogs(logs, [], "timeout")[0]?.id).toBe("2");
});

test("lays spans out as a waterfall relative to the trace window", () => {
  const span = (overrides: Partial<ObservabilityTraceSpan>): ObservabilityTraceSpan => ({
    ...trace({}),
    spanId: "s1",
    parentSpanId: null,
    spanType: "agent_run",
    input: null,
    output: null,
    error: null,
    ...overrides,
  });
  const bars = spanTimeline([
    span({ spanId: "root", startedAt: "2026-08-16T11:00:00.000Z", endedAt: "2026-08-16T11:00:10.000Z" }),
    span({ spanId: "child", parentSpanId: "root", startedAt: "2026-08-16T11:00:05.000Z", endedAt: "2026-08-16T11:00:10.000Z" }),
  ]);

  expect(bars.map((bar) => bar.span.spanId)).toEqual(["root", "child"]);
  expect(bars[0]).toMatchObject({ depth: 0, offset: 0, width: 100 });
  expect(bars[1]).toMatchObject({ depth: 1, offset: 50, width: 50 });
});