Created
April 23, 2024 09:38
-
-
Save joshhunt/3b21c18412ff72c5ad4e281cbf734125 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import readline from "node:readline"; | |
import chalk from "chalk"; | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
}); | |
rl.on("line", (line) => { | |
const parsed = maybeJSON(line); | |
if (!parsed) { | |
process.stdout.write(line + "\n"); | |
return; | |
} | |
const { level, logger, msg, t, ...rest } = parsed; | |
if (level === "info" && logger === "context" && msg === "Request Completed") { | |
process.stdout.write(formatHttpRequest(parsed) + "\n"); | |
return; | |
} | |
const simpleProps: [string, string][] = []; | |
const multiLineProps: [string, string][] = []; | |
for (const [key, value] of Object.entries(rest)) { | |
if (typeof value === "string" && value.includes("\n")) { | |
multiLineProps.push([key, value]); | |
} else { | |
simpleProps.push([key, value]); | |
} | |
} | |
const simplePropsMessage = simpleProps | |
.map(([key, value]) => formatKeyValue(key, value)) | |
.join(" "); | |
const fLevel = level ? formatLevel(level) : undefined; | |
const fLogger = logger ? formatLogger(logger) : undefined; | |
let rightFormattedLine = [msg, simplePropsMessage].filter(Boolean).join(" "); | |
if ( | |
level === "info" && | |
logger === "http.server" && | |
msg === "HTTP Server Listen" | |
) { | |
rightFormattedLine = chalk.black.bgGreen(rightFormattedLine); | |
} | |
let formattedLine = [fLevel, fLogger, rightFormattedLine] | |
.filter(Boolean) | |
.join(" "); | |
process.stdout.write(formattedLine + "\n"); | |
if (multiLineProps.length > 0) { | |
for (const [key, value] of multiLineProps) { | |
process.stdout.write(formatIndentedKeyValue(key, value) + "\n"); | |
} | |
} | |
}); | |
const maybeJSON = (line: string): Record<string, string> | undefined => { | |
try { | |
return JSON.parse(line); | |
} catch (e) { | |
return undefined; | |
} | |
}; | |
function formatHttpRequest(log: Record<string, string>) { | |
const { level, duration, path, method, status, handler, ...rest } = log; | |
const fLevel = formatLevel(level === "info" ? "http" : level); | |
const fMethod = formatLogger(method); | |
return [ | |
fLevel, | |
fMethod, | |
formatStatusCode(status), | |
path, | |
formatKeyValue("duration", duration), | |
formatKeyValue("handler", handler), | |
].join(" "); | |
} | |
function formatStatusCode(_status: string | number) { | |
const status = typeof _status === "string" ? parseInt(_status) : _status; | |
if (status >= 500) { | |
return chalk.red(status); | |
} else if (status >= 400) { | |
return chalk.yellow(status); | |
} else if (status >= 300) { | |
return chalk.cyan(status); | |
} else if (status >= 200) { | |
return chalk.green(status); | |
} else { | |
return status; | |
} | |
} | |
function formatLevel(level: string) { | |
const levelLower = level.toLowerCase(); | |
switch (levelLower) { | |
case "http": | |
return chalk.black.bgBlueBright(" HTTP "); | |
case "debug": | |
return chalk.black.bgBlue(" DBUG "); | |
case "info": | |
return chalk.black.bgGreen(" INFO "); | |
case "warn": | |
return chalk.black.bgYellow(" WARN "); | |
case "error": | |
return chalk.black.bgRed(" ERRR "); | |
default: | |
return level; | |
} | |
} | |
function formatKeyValue(key: string, value: string) { | |
const fKey = chalk.dim(`${key}`); | |
const fEqual = chalk.dim("="); | |
const fValue = chalk.dim(value); | |
return fKey + fEqual + fValue; | |
} | |
function formatIndentedKeyValue(key: string, value: string) { | |
const firstIndent = 6; | |
const subsequentIndents = firstIndent + key.length + 1; | |
const fKey = chalk.grey(`${key}`); | |
const fEqual = chalk.grey("="); | |
const [firstLine, ...lines] = value.split("\n"); | |
let output = | |
" ".repeat(firstIndent) + fKey + fEqual + chalk.dim(firstLine) + "\n"; | |
for (const line of lines) { | |
output += " ".repeat(subsequentIndents) + chalk.dim(line) + "\n"; | |
} | |
// process.stdout.write(` ${formatKeyValue(key, value)}\n`); | |
return output; | |
} | |
const LOGGER_COLORS = ["magenta", "cyan", "blue", "yellow"] as const; | |
function formatLogger(logger: string) { | |
const hash = hashCode(logger); | |
const index = hash % LOGGER_COLORS.length; | |
return chalk[LOGGER_COLORS[index]](`[${logger}]`); | |
} | |
function hashCode(str: string) { | |
let hash = 0; | |
for (var i = 0; i < str.length; i++) { | |
hash = str.charCodeAt(i) + ((hash << 5) - hash); | |
} | |
return Math.abs(hash); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment