112 lines
2.4 KiB
TypeScript
112 lines
2.4 KiB
TypeScript
import type {
|
|
LogContext,
|
|
LogEntry,
|
|
LogLevel,
|
|
LoggerConfig,
|
|
} from "@/types/logger";
|
|
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
|
|
|
|
const LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
debug: 10,
|
|
info: 20,
|
|
warn: 30,
|
|
error: 40,
|
|
};
|
|
|
|
const LEVEL_LABELS: Record<LogLevel, string> = {
|
|
debug: "DEBUG",
|
|
info: "INFO",
|
|
warn: "WARN",
|
|
error: "ERROR",
|
|
};
|
|
|
|
const LEVEL_STYLES: Record<LogLevel, string> = {
|
|
debug: "color: #94a3b8; font-weight: 600;",
|
|
info: "color: #60a5fa; font-weight: 600;",
|
|
warn: "color: #f59e0b; font-weight: 600;",
|
|
error: "color: #f87171; font-weight: 600;",
|
|
};
|
|
|
|
const SCOPE_STYLE = "color: #e5e7eb; font-weight: 600;";
|
|
const MESSAGE_STYLE = "color: inherit;";
|
|
|
|
class Logger {
|
|
private readonly config: LoggerConfig;
|
|
|
|
constructor(config: LoggerConfig) {
|
|
this.config = config;
|
|
}
|
|
|
|
debug(scope: string, message: string, context?: LogContext): void {
|
|
this.log("debug", scope, message, context);
|
|
}
|
|
|
|
info(scope: string, message: string, context?: LogContext): void {
|
|
this.log("info", scope, message, context);
|
|
}
|
|
|
|
warn(scope: string, message: string, context?: LogContext): void {
|
|
this.log("warn", scope, message, context);
|
|
}
|
|
|
|
error(scope: string, message: string, context?: LogContext): void {
|
|
this.log("error", scope, message, context);
|
|
}
|
|
|
|
private log(
|
|
level: LogLevel,
|
|
scope: string,
|
|
message: string,
|
|
context?: LogContext,
|
|
): void {
|
|
if (!this.shouldLog(level)) return;
|
|
|
|
const entry: LogEntry = {
|
|
timestamp: new Date().toISOString(),
|
|
level,
|
|
scope,
|
|
message,
|
|
...(context ? { context } : {}),
|
|
};
|
|
|
|
const formattedMessage = `%c[${LEVEL_LABELS[level]}]%c [${scope}]%c ${message}`;
|
|
const args = [
|
|
formattedMessage,
|
|
LEVEL_STYLES[level],
|
|
SCOPE_STYLE,
|
|
MESSAGE_STYLE,
|
|
entry,
|
|
] as const;
|
|
|
|
switch (level) {
|
|
case "debug":
|
|
console.debug(...args);
|
|
return;
|
|
case "info":
|
|
console.info(...args);
|
|
return;
|
|
case "warn":
|
|
console.warn(...args);
|
|
return;
|
|
case "error":
|
|
console.error(...args);
|
|
}
|
|
}
|
|
|
|
private shouldLog(level: LogLevel): boolean {
|
|
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.config.minLevel];
|
|
}
|
|
}
|
|
|
|
function resolveMinLevel(): LogLevel {
|
|
if (typeof window === "undefined") {
|
|
return "info";
|
|
}
|
|
|
|
return isDebugEnabled() ? "debug" : "info";
|
|
}
|
|
|
|
export const logger = new Logger({
|
|
minLevel: resolveMinLevel(),
|
|
});
|