Files
illusory-mapp/packages/logger/index.ts

104 lines
3.0 KiB
TypeScript

import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport";
import { settings } from "@pkg/settings";
import type { Err } from "@pkg/result";
import winston from "winston";
import util from "util";
process.on("warning", (warning) => {
const msg = String(warning?.message || "");
const name = String((warning as any)?.name || "");
if (
name === "TimeoutNegativeWarning" ||
msg.includes("TimeoutNegativeWarning") ||
msg.includes("Timeout duration was set to 1")
) {
return;
}
console.warn(warning);
});
const levels = {
error: 0,
warn: 1,
info: 2,
http: 3,
debug: 4,
} as const;
const colors = {
error: "red",
warn: "yellow",
info: "green",
http: "magenta",
debug: "white",
};
const level = () => {
const envLevel = process.env.LOG_LEVEL?.toLowerCase();
if (envLevel && Object.prototype.hasOwnProperty.call(levels, envLevel)) {
return envLevel as keyof typeof levels;
}
return settings.isDevelopment ? "debug" : "warn";
};
const consoleFormat = winston.format.combine(
winston.format.errors({ stack: true }),
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }),
winston.format.colorize({ all: true }),
winston.format.printf((info) => {
const { level, message, timestamp } = info;
const extra = Object.fromEntries(
Object.entries(info).filter(
([key]) => key !== "level" && key !== "message" && key !== "timestamp",
),
);
const formattedMessage =
message instanceof Error
? message.stack || message.message
: typeof message === "object"
? util.inspect(message, { depth: null, colors: true })
: String(message);
const formattedExtra =
Object.keys(extra).length > 0
? `\n${util.inspect(extra, { depth: null, colors: true })}`
: "";
return `[${level}] ${timestamp}: ${formattedMessage}${formattedExtra}`;
}),
);
winston.addColors(colors);
const logger = winston.createLogger({
level: level(),
levels,
format: consoleFormat,
transports: [
new winston.transports.Console({ format: consoleFormat }),
new OpenTelemetryTransportV3(),
],
exceptionHandlers: [new winston.transports.Console({ format: consoleFormat })],
rejectionHandlers: [new winston.transports.Console({ format: consoleFormat })],
});
const stream = { write: (message: string) => logger.http(message.trim()) };
function getError(payload: Err, error?: any) {
logger.error(JSON.stringify({ payload, error }, null, 2));
return {
code: payload.code,
message: payload.message,
description: payload.description,
detail: payload.detail,
error: error instanceof Error ? error.message : error,
actionable: payload.actionable,
} as Err;
}
export { getError, logger, stream };