UNPKG

@grotto/logysia

Version:

Logging middleware for Bun's Elysia web framework

132 lines (100 loc) 3.72 kB
import Elysia from "elysia" import * as pc from "picocolors" import process from "process" interface Writer { write: (message: string) => void } const consoleWriter: Writer = { write(message: string) { console.log(message) } } interface Options { logIP?: boolean, writer?: Writer } export const logger = (options?: Options) => { const { write } = options?.writer || consoleWriter return new Elysia({ name: "@grotto/logysia" }) .onRequest((ctx) => { ctx.store = { ...ctx.store, beforeTime: process.hrtime.bigint() } }) .onBeforeHandle({ as: "global" }, (ctx) => { ctx.store = { ...ctx.store, beforeTime: process.hrtime.bigint() } }) .onAfterHandle({ as: "global" }, ({ request, store }) => { const logStr: string[] = [] if (options !== undefined && options.logIP) { if (request.headers.get("X-Forwarded-For")) { logStr.push(`[${pc.cyan(request.headers.get("X-Forwarded-For"))}]`) } } logStr.push(methodString(request.method)) logStr.push(new URL(request.url).pathname) const beforeTime: bigint = (store as any).beforeTime; logStr.push(durationString(beforeTime)) write(logStr.join(" ")) }) .onError({ as: "global" }, ({ request, error, store }) => { const logStr: string[] = [] logStr.push(pc.red(methodString(request.method))) logStr.push(new URL(request.url).pathname) logStr.push(pc.red("Error")) if ("status" in error) { logStr.push(String(error.status)) } logStr.push(error.message) const beforeTime: bigint = (store as any).beforeTime; logStr.push(durationString(beforeTime)) write(logStr.join(" ")) }) } function durationString(beforeTime: bigint): string { const now = process.hrtime.bigint(); const timeDifference = now - beforeTime; const nanoseconds = Number(timeDifference); const durationInMicroseconds = (nanoseconds / 1e3).toFixed(0); // Convert to microseconds const durationInMilliseconds = (nanoseconds / 1e6).toFixed(0); // Convert to milliseconds let timeMessage: string = ""; if (nanoseconds >= 1e9) { const seconds = (nanoseconds / 1e9).toFixed(2); timeMessage = `| ${seconds}s`; } else if (nanoseconds >= 1e6) { timeMessage = `| ${durationInMilliseconds}ms`; } else if (nanoseconds >= 1e3) { timeMessage = `| ${durationInMicroseconds}µs`; } else { timeMessage = `| ${nanoseconds}ns`; } return timeMessage; } function methodString(method: string): string { switch (method) { case "GET": // Handle GET request return pc.white("GET") case "POST": // Handle POST request return pc.yellow("POST") case "PUT": // Handle PUT request return pc.blue("PUT") case "DELETE": // Handle DELETE request return pc.red("DELETE") case "PATCH": // Handle PATCH request return pc.green("PATCH") case "OPTIONS": // Handle OPTIONS request return pc.gray("OPTIONS") case "HEAD": // Handle HEAD request return pc.magenta("HEAD") default: // Handle unknown request method return method } }