149 lines
3.3 KiB
TypeScript
149 lines
3.3 KiB
TypeScript
import { config } from "../config";
|
|
|
|
export enum LogLevel {
|
|
DEBUG = 0,
|
|
INFO = 1,
|
|
WARN = 2,
|
|
ERROR = 3,
|
|
}
|
|
|
|
export interface LogEntry {
|
|
timestamp: string;
|
|
level: LogLevel;
|
|
message: string;
|
|
context?: Record<string, unknown>;
|
|
error?: Error;
|
|
}
|
|
|
|
class Logger {
|
|
private logLevel: LogLevel;
|
|
|
|
constructor() {
|
|
this.logLevel =
|
|
process.env.NODE_ENV === "development" ? LogLevel.DEBUG : LogLevel.INFO;
|
|
}
|
|
|
|
private formatMessage(entry: LogEntry): string {
|
|
const { timestamp, level, message, context, error } = entry;
|
|
const levelName = LogLevel[level];
|
|
const contextStr = context ? ` ${JSON.stringify(context)}` : "";
|
|
const errorStr = error ? `\n${error.stack}` : "";
|
|
|
|
return `[${timestamp}] ${levelName}: ${message}${contextStr}${errorStr}`;
|
|
}
|
|
|
|
private shouldLog(level: LogLevel): boolean {
|
|
return level >= this.logLevel;
|
|
}
|
|
|
|
private log(
|
|
level: LogLevel,
|
|
message: string,
|
|
context?: Record<string, unknown>,
|
|
error?: Error
|
|
): void {
|
|
if (!this.shouldLog(level)) return;
|
|
|
|
const entry: LogEntry = {
|
|
timestamp: new Date().toISOString(),
|
|
level,
|
|
message,
|
|
context,
|
|
error,
|
|
};
|
|
|
|
const formattedMessage = this.formatMessage(entry);
|
|
|
|
switch (level) {
|
|
case LogLevel.DEBUG:
|
|
console.debug(formattedMessage);
|
|
break;
|
|
case LogLevel.INFO:
|
|
console.info(formattedMessage);
|
|
break;
|
|
case LogLevel.WARN:
|
|
console.warn(formattedMessage);
|
|
break;
|
|
case LogLevel.ERROR:
|
|
console.error(formattedMessage);
|
|
break;
|
|
}
|
|
|
|
// 在生产环境中,可以发送到外部日志服务
|
|
if (process.env.NODE_ENV === "production" && level >= LogLevel.ERROR) {
|
|
this.sendToExternalService(entry);
|
|
}
|
|
}
|
|
|
|
private sendToExternalService(entry: LogEntry): void {
|
|
// 这里可以集成 Sentry, LogRocket 等外部日志服务
|
|
// 示例:发送到 Sentry
|
|
if (process.env.SENTRY_DSN) {
|
|
// Sentry.captureException(entry.error || new Error(entry.message))
|
|
}
|
|
}
|
|
|
|
debug(message: string, context?: Record<string, unknown>): void {
|
|
this.log(LogLevel.DEBUG, message, context);
|
|
}
|
|
|
|
info(message: string, context?: Record<string, unknown>): void {
|
|
this.log(LogLevel.INFO, message, context);
|
|
}
|
|
|
|
warn(
|
|
message: string,
|
|
context?: Record<string, unknown>,
|
|
error?: Error
|
|
): void {
|
|
this.log(LogLevel.WARN, message, context, error);
|
|
}
|
|
|
|
error(
|
|
message: string,
|
|
context?: Record<string, unknown>,
|
|
error?: Error
|
|
): void {
|
|
this.log(LogLevel.ERROR, message, context, error);
|
|
}
|
|
|
|
// 记录 API 请求
|
|
logApiRequest(
|
|
method: string,
|
|
url: string,
|
|
statusCode: number,
|
|
duration: number
|
|
): void {
|
|
this.info("API Request", {
|
|
method,
|
|
url,
|
|
statusCode,
|
|
duration: `${duration}ms`,
|
|
});
|
|
}
|
|
|
|
// 记录数据库操作
|
|
logDbOperation(operation: string, table: string, duration: number): void {
|
|
this.debug("Database Operation", {
|
|
operation,
|
|
table,
|
|
duration: `${duration}ms`,
|
|
});
|
|
}
|
|
|
|
// 记录用户操作
|
|
logUserAction(
|
|
userId: string,
|
|
action: string,
|
|
details?: Record<string, unknown>
|
|
): void {
|
|
this.info("User Action", {
|
|
userId,
|
|
action,
|
|
...details,
|
|
});
|
|
}
|
|
}
|
|
|
|
export const logger = new Logger();
|