import type { MiddlewareHandler } from "hono"; import { createMiddleware } from "hono/factory"; import type { Logger } from "./types.js"; /** * Hono middleware that logs structured HTTP request/response data. * * Replaces Hono's built-in `logger()` middleware with OpenTelemetry-backed * structured logging. Each request gets a child logger with request context * that is available to downstream handlers via `c.get("logger")`. * * Log output: * - Incoming request: method, path (at debug level) * - Completed response: method, path, status, duration_ms * (info for 2xx, warn for 4xx, error for 5xx — including errors handled by onError) * * @example * ```ts * import { createLogger } from "@atbb/logger"; * import { requestLogger } from "@atbb/logger/middleware"; * * const logger = createLogger({ service: "atbb-appview" }); * app.use("*", requestLogger(logger)); * * // In route handlers: * app.get("/api/forum", (c) => { * const log = c.get("logger"); * log.info("Fetching forum metadata"); * // ... * }); * ``` */ export function requestLogger(logger: Logger): MiddlewareHandler { return createMiddleware(async (c, next) => { const start = performance.now(); const method = c.req.method; const path = c.req.path; // Create a child logger scoped to this request const reqLogger = logger.child({ method, path, }); // Make the logger available to downstream handlers c.set("logger", reqLogger); reqLogger.debug("Request received"); await next(); const duration = Math.round(performance.now() - start); const status = c.res.status; const level = status >= 500 ? "error" : status >= 400 ? "warn" : "info"; reqLogger[level]("Request completed", { status, duration_ms: duration, }); }); }