Public: anyone can read this; the crew can change it.

The API's health read names its Server-Timing phases: session, health, render #5015

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/5007-the-api-s-health-read-names-its-server-t → main 1 commit fork

  • Merged. scout/5007-the-api-s-health-read-names-its-server-t was merged into main as f59abb3.

Review

Sign in to review this change.
2 files changed +38 −6
src/http/api.ts +8 −6
@@ -5061,13 +5061,15 @@ export function apiRoutes(router: Router<Handler>): void {
50615061 // How the forge is: anyone may ask (a monitor has no account), a stranger
50625062 // is told little, the release machinery's probe and a site admin the
50635063 // whole of it (`actions/health.ts`).
5064 router.add("GET", "/api/v1/health", (ctx) =>
5065 json(
5064 router.add("GET", "/api/v1/health", (ctx) => {
5065 notePhase(ctx.request, "session", takeSessionTime(ctx.request));
5066 const body = timePhase(ctx.request, "health", () =>
50665067 readHealth(ctx.app, ctx.auth.user, isProbe(ctx.request, ctx.app.config.dataDir)),
5067 200,
5068 { "cache-control": "no-store", vary: "authorization, cookie, x-forge-probe" },
5069 ),
5070 );
5068 );
5069 return timePhase(ctx.request, "render", () =>
5070 json(body, 200, { "cache-control": "no-store", vary: "authorization, cookie, x-forge-probe" }),
5071 );
5072 });
50715073
50725074 // Open egress connections per app and destination, as Prometheus text
50735075 // (#3719). Repository names are in the labels, so a site admin only.
test/health-timing.test.ts added +30
@@ -0,0 +1,30 @@
1 /** GET /api/v1/health names its phases in Server-Timing. */
2 import { afterAll, beforeAll, expect, test } from "bun:test";
3 import { mkdtemp, rm } from "node:fs/promises";
4 import { tmpdir } from "node:os";
5 import { join } from "node:path";
6 import { createApp, type App } from "../src/app.ts";
7 import { serve, type Servers } from "../src/http/server.ts";
8
9 let dataDir = "";
10 let app: App, servers: Servers;
11
12 beforeAll(async () => {
13 dataDir = await mkdtemp(join(tmpdir(), "forge-htime-"));
14 app = createApp({ dataDir, port: 0 });
15 servers = await serve(app);
16 });
17
18 afterAll(async () => {
19 servers.stop();
20 app.close();
21 await rm(dataDir, { recursive: true, force: true });
22 });
23
24 test("the health read names session, health, render in that order", async () => {
25 const res = await fetch(`${servers.url}/api/v1/health`);
26 await res.arrayBuffer();
27 expect(res.status).toBe(200);
28 const names = (res.headers.get("server-timing") ?? "").split(", ").map((p) => p.split(";")[0]);
29 expect(names.filter((n) => ["session", "health", "render"].includes(n!))).toEqual(["session", "health", "render"]);
30 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs