feat: jitter_ms tracking — scheduled_at stamped at dispatch, jitter computed on ingest
This commit is contained in:
+14
-8
@@ -33,17 +33,23 @@ export async function migrate() {
|
||||
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS pings (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
||||
checked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
status_code INTEGER,
|
||||
latency_ms INTEGER,
|
||||
up BOOLEAN NOT NULL,
|
||||
error TEXT,
|
||||
meta JSONB
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
||||
checked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
scheduled_at TIMESTAMPTZ,
|
||||
jitter_ms INTEGER,
|
||||
status_code INTEGER,
|
||||
latency_ms INTEGER,
|
||||
up BOOLEAN NOT NULL,
|
||||
error TEXT,
|
||||
meta JSONB
|
||||
)
|
||||
`;
|
||||
|
||||
// Migrations for existing deployments
|
||||
await sql`ALTER TABLE pings ADD COLUMN IF NOT EXISTS scheduled_at TIMESTAMPTZ`;
|
||||
await sql`ALTER TABLE pings ADD COLUMN IF NOT EXISTS jitter_ms INTEGER`;
|
||||
|
||||
await sql`CREATE INDEX IF NOT EXISTS idx_pings_monitor ON pings(monitor_id, checked_at DESC)`;
|
||||
await sql`CREATE INDEX IF NOT EXISTS idx_pings_checked_at ON pings(checked_at)`;
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
|
||||
return {};
|
||||
})
|
||||
|
||||
// Returns monitors that are due for a check
|
||||
// Returns monitors that are due for a check, with scheduled_at = now()
|
||||
.get("/due", async () => {
|
||||
|
||||
return sql`
|
||||
const scheduled_at = new Date().toISOString();
|
||||
const monitors = await sql`
|
||||
SELECT m.id, m.url, m.method, m.request_headers, m.request_body, m.timeout_ms, m.interval_s, m.query
|
||||
FROM monitors m
|
||||
LEFT JOIN LATERAL (
|
||||
@@ -37,6 +37,8 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
|
||||
AND (last.checked_at IS NULL
|
||||
OR last.checked_at < now() - (m.interval_s || ' seconds')::interval)
|
||||
`;
|
||||
// Attach scheduled_at to each monitor so the runner can report jitter
|
||||
return monitors.map((m: any) => ({ ...m, scheduled_at }));
|
||||
})
|
||||
|
||||
// Manual retention cleanup trigger
|
||||
|
||||
@@ -56,10 +56,15 @@ export const ingest = new Elysia()
|
||||
const meta = body.meta ? { ...body.meta } : {};
|
||||
if (body.cert_expiry_days != null) meta.cert_expiry_days = body.cert_expiry_days;
|
||||
|
||||
const scheduledAt = body.scheduled_at ? new Date(body.scheduled_at) : null;
|
||||
const jitterMs = scheduledAt ? Math.max(0, Date.now() - scheduledAt.getTime()) : null;
|
||||
|
||||
const [ping] = await sql`
|
||||
INSERT INTO pings (monitor_id, status_code, latency_ms, up, error, meta)
|
||||
INSERT INTO pings (monitor_id, scheduled_at, jitter_ms, status_code, latency_ms, up, error, meta)
|
||||
VALUES (
|
||||
${body.monitor_id},
|
||||
${scheduledAt},
|
||||
${jitterMs},
|
||||
${body.status_code ?? null},
|
||||
${body.latency_ms ?? null},
|
||||
${body.up},
|
||||
@@ -77,6 +82,7 @@ export const ingest = new Elysia()
|
||||
}, {
|
||||
body: t.Object({
|
||||
monitor_id: t.String(),
|
||||
scheduled_at: t.Optional(t.Nullable(t.String())),
|
||||
status_code: t.Optional(t.Number()),
|
||||
latency_ms: t.Optional(t.Number()),
|
||||
up: t.Boolean(),
|
||||
|
||||
Reference in New Issue
Block a user