feat: Add request logging and traffic metrics for API performance monitoring

This commit is contained in:
2026-10-20 23:31:08 +03:00
parent e28d65310d
commit de72d003b8
6 changed files with 304 additions and 2 deletions

View File

@@ -13,6 +13,7 @@ import { catalogDiagnostics } from "./diagnostics.js";
import { securityHeaders, requestTimeout } from "./protect.js";
import { startWatch, watchOnce, watchStatus } from "./watch.js";
import { telegram } from "./alerts.js";
import { requestLog, trafficStatus } from "./metrics.js";
import {
getIndex,
indexStatus,
@@ -40,6 +41,9 @@ app.disable("x-powered-by");
app.set("trust proxy", "loopback, linklocal, uniquelocal");
const dist = fileURLToPath(new URL("../dist/", import.meta.url));
app.use(securityHeaders(dist + "index.html"));
// One JSON line per API request and the counters of /api/health; first, so limited and timed
// out requests are in them too.
app.use("/api", requestLog());
// gzip or brotli: a semester of lessons is about 200 KB of JSON and shrinks tenfold.
app.use(compression());
// A generous limit per address: students behind one dormitory or university NAT share it, so
@@ -70,8 +74,9 @@ app.use("/api", (_req, res, next) => {
// 8 — /api/ready, and `ready` in /api/health;
// 9 — a request limit on /api (429 too_many_requests), a 30 s time limit (504 timeout), security headers;
// 10 — parserVersion in /api/catalog;
// 11 — the catalog is checked by ETag every 5 minutes; `watch`, `telegram` and `catalog.lastCrawl` in /api/health.
const API_VERSION = 11;
// 11 — the catalog is checked by ETag every 5 minutes; `watch`, `telegram` and `catalog.lastCrawl` in /api/health;
// 12 — a JSON log line per request and `traffic` in /api/health.
const API_VERSION = 12;
/**
* What the server still waits for before it answers from memory: the catalog, the week table
@@ -94,6 +99,8 @@ app.get("/api/health", async (req, res) => {
directory: indexStatus(),
// The server's own checks of the catalog and its messages to the owner.
watch: watchStatus,
// What the API was asked in the last hour and since the start (server/metrics.js).
traffic: trafficStatus(),
telegram: { enabled: telegram.enabled, sent: telegram.sent, lastSentAt: telegram.lastSentAt, lastError: telegram.lastError },
});
});