refactor: 改进后端工具类 - 增强日志功能和工具函数

This commit is contained in:
Tianpao
2026-02-01 12:22:13 +08:00
parent 0a47d14627
commit 475d028ed9
2 changed files with 88 additions and 6 deletions

View File

@@ -1,9 +1,73 @@
import * as fs from 'fs';
import * as path from 'path';
const env = process.env.DEBUG; const env = process.env.DEBUG;
const isDebug = env === "true"; const isDebug = env === "true";
// 日志级别枚举 // 日志级别枚举
type LogLevel = "debug" | "info" | "warn" | "error"; type LogLevel = "debug" | "info" | "warn" | "error";
// 日志文件路径
const logsDir = path.join(process.cwd(), 'logs');
let logFilePath: string | null = null;
/**
* 获取Asia/Shanghai时区的格式化时间
*/
function getShanghaiTime(): Date {
const now = new Date();
const utc = now.getTime() + (now.getTimezoneOffset() * 60000);
const shanghaiOffset = 8;
return new Date(utc + (3600000 * shanghaiOffset));
}
/**
* 格式化时间为字符串
*/
function formatTimestamp(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
/**
* 生成日志文件名,处理同一天多次打开的情况
*/
function generateLogFileName(): string {
const now = getShanghaiTime();
const dateStr = now.toISOString().split('T')[0];
const timeStr = String(now.getHours()).padStart(2, '0') +
String(now.getMinutes()).padStart(2, '0') +
String(now.getSeconds()).padStart(2, '0');
return `${dateStr}_${timeStr}.log`;
}
/**
* 初始化日志文件
*/
function initLogFile() {
if (!fs.existsSync(logsDir)) {
fs.mkdirSync(logsDir, { recursive: true });
}
logFilePath = path.join(logsDir, generateLogFileName());
}
/**
* 写入日志到文件
*/
function writeToFile(logMessage: string) {
if (!logFilePath) {
initLogFile();
}
if (logFilePath) {
fs.appendFileSync(logFilePath, logMessage + '\n', 'utf-8');
}
}
/** /**
* 日志记录器 * 日志记录器
* @param level 日志级别 * @param level 日志级别
@@ -11,24 +75,42 @@ type LogLevel = "debug" | "info" | "warn" | "error";
* @param data 附加数据(可选) * @param data 附加数据(可选)
*/ */
function log(level: LogLevel, msg: string | Error, data?: any) { function log(level: LogLevel, msg: string | Error, data?: any) {
const timestamp = new Date().toLocaleString(); const shanghaiTime = getShanghaiTime();
const timestamp = formatTimestamp(shanghaiTime);
const prefix = `[${level.toUpperCase()}] [${timestamp}]`; const prefix = `[${level.toUpperCase()}] [${timestamp}]`;
// 确保只在调试模式下输出debug日志 // 确保只在调试模式下输出debug日志
if (level === "debug" && !isDebug) return; if (level === "debug" && !isDebug) return;
let logMessage = '';
if (msg instanceof Error) { if (msg instanceof Error) {
console.error(`${prefix} ${msg.message}`); const errorMsg = `${prefix} ${msg.message}`;
console.error(msg.stack); const stackMsg = msg.stack || '';
const dataMsg = data ? `${prefix} Data: ${JSON.stringify(data, null, 2)}` : '';
console.error(errorMsg);
console.error(stackMsg);
if (data) console.error(`${prefix} Data:`, data); if (data) console.error(`${prefix} Data:`, data);
logMessage = errorMsg + '\n' + stackMsg;
if (data) logMessage += '\n' + dataMsg;
} else { } else {
const logFunc = level === "error" ? console.error : const logFunc = level === "error" ? console.error :
level === "warn" ? console.warn : level === "warn" ? console.warn :
console.log; console.log;
logFunc(`${prefix} ${msg}`); const outputMsg = `${prefix} ${msg}`;
const dataMsg = data ? `${prefix} Data: ${JSON.stringify(data, null, 2)}` : '';
logFunc(outputMsg);
if (data) logFunc(`${prefix} Data:`, data); if (data) logFunc(`${prefix} Data:`, data);
logMessage = outputMsg;
if (data) logMessage += '\n' + dataMsg;
} }
writeToFile(logMessage);
} }
export const logger = { export const logger = {

View File

@@ -193,7 +193,7 @@ export async function fastdownload(data: [string, string]|string[][]) {
export async function Wfastdownload(data: string[][], ws: MessageWS) { export async function Wfastdownload(data: string[][], ws: MessageWS) {
logger.info(`Starting web download of ${data.length} files`); logger.info(`Starting web download of ${data.length} files`);
let index = 0;
return await pMap( return await pMap(
data, data,
async (item: string[], idx: number) => { async (item: string[], idx: number) => {
@@ -214,7 +214,7 @@ export async function Wfastdownload(data: string[][], ws: MessageWS) {
} }
// 更新下载进度 // 更新下载进度
ws.download(data.length, idx + 1, filePath); ws.download(data.length, ++index, filePath);
}, },
{ retries: 3, onFailedAttempt: (error) => { { retries: 3, onFailedAttempt: (error) => {
logger.warn(`Download attempt failed for ${url}, retrying (${error.attemptNumber}/3)`); logger.warn(`Download attempt failed for ${url}, retrying (${error.attemptNumber}/3)`);