fix(logs): the browser's copy of a polled read is quiet too
The server now logs polled reads at DEBUG, and the browser's copy of each request line promises the server's level: at INFO the unread-count polls filled My log within minutes and, at Detailed, the shipped log. The server marks a line it logged at DEBUG with X-Log-Quiet, so the polled-route list stays in one place.
This commit is contained in:
@@ -12,6 +12,9 @@ import { log, newRequestId, type Level } from "./log";
|
||||
* Grouping by it is what makes a client line comparable, and it is safe by construction: a token in
|
||||
* the path (`/api/public/watch/{token}`) arrives already replaced by its parameter name. */
|
||||
export const ROUTE_HEADER = "X-Route";
|
||||
/** Set when the server logged this request at DEBUG (a polled read, the log console's own reads): the
|
||||
* browser's copy of the line goes to DEBUG too, from the server's one list (`logs._POLLED_ROUTES`). */
|
||||
export const QUIET_HEADER = "X-Log-Quiet";
|
||||
export const REQUEST_ID_HEADER = "X-Request-Id";
|
||||
|
||||
// A static path word: kept. Anything else (an id, a channel id, a share token) becomes `{}`.
|
||||
@@ -29,9 +32,9 @@ export function pathTemplate(url: string): string {
|
||||
}
|
||||
|
||||
/** Level of a request line — the server's own rule (`logs.log_requests`), so both sides agree on
|
||||
* what a 404 is. */
|
||||
function statusLevel(status: number): Level {
|
||||
return status >= 500 ? "ERROR" : status >= 400 ? "WARNING" : "INFO";
|
||||
* what a 404 is, and on which successes are too routine for INFO (`quiet`, the server's say). */
|
||||
function statusLevel(status: number, quiet: boolean): Level {
|
||||
return status >= 500 ? "ERROR" : status >= 400 ? "WARNING" : quiet ? "DEBUG" : "INFO";
|
||||
}
|
||||
|
||||
/** Record one request's outcome. `route` is the server's template when it sent one. */
|
||||
@@ -40,7 +43,9 @@ export function logRequest(
|
||||
method: string,
|
||||
url: string,
|
||||
started: number,
|
||||
outcome: { status: number; route?: string | null } | { failed: "network" | "aborted" },
|
||||
outcome:
|
||||
| { status: number; route?: string | null; quiet?: boolean }
|
||||
| { failed: "network" | "aborted" },
|
||||
extra: Record<string, unknown> = {},
|
||||
): void {
|
||||
const duration_ms = Math.round((performance.now() - started) * 10) / 10;
|
||||
@@ -56,7 +61,7 @@ export function logRequest(
|
||||
}
|
||||
const path = outcome.route || pathTemplate(url);
|
||||
log.request(
|
||||
statusLevel(outcome.status),
|
||||
statusLevel(outcome.status, outcome.quiet === true),
|
||||
`${method} ${path} ${outcome.status}`,
|
||||
{ method, path, status: outcome.status, duration_ms, ...extra },
|
||||
requestId,
|
||||
@@ -92,7 +97,11 @@ export async function send(
|
||||
method,
|
||||
url,
|
||||
started,
|
||||
{ status: r.status, route: headerOf(r, ROUTE_HEADER) },
|
||||
{
|
||||
status: r.status,
|
||||
route: headerOf(r, ROUTE_HEADER),
|
||||
quiet: headerOf(r, QUIET_HEADER) === "1",
|
||||
},
|
||||
extra,
|
||||
);
|
||||
return r;
|
||||
|
||||
Reference in New Issue
Block a user