日志显示更新
This commit is contained in:
@@ -3,6 +3,33 @@
|
|||||||
*/
|
*/
|
||||||
const { defaultLogger } = require('../utils/logger');
|
const { defaultLogger } = require('../utils/logger');
|
||||||
|
|
||||||
|
// 颜色常量
|
||||||
|
const METHOD_COLORS = {
|
||||||
|
GET: '\x1b[32m', // 绿色
|
||||||
|
POST: '\x1b[34m', // 蓝色
|
||||||
|
PUT: '\x1b[33m', // 黄色
|
||||||
|
DELETE: '\x1b[31m', // 红色
|
||||||
|
PATCH: '\x1b[35m', // 紫色
|
||||||
|
DEFAULT: '\x1b[37m' // 白色
|
||||||
|
};
|
||||||
|
|
||||||
|
// 状态码颜色
|
||||||
|
const STATUS_COLORS = {
|
||||||
|
SUCCESS: '\x1b[32m', // 2xx - 绿色
|
||||||
|
REDIRECT: '\x1b[36m', // 3xx - 青色
|
||||||
|
CLIENT_ERROR: '\x1b[33m', // 4xx - 黄色
|
||||||
|
SERVER_ERROR: '\x1b[31m' // 5xx - 红色
|
||||||
|
};
|
||||||
|
|
||||||
|
// 响应时间颜色
|
||||||
|
const DURATION_COLORS = {
|
||||||
|
FAST: '\x1b[32m', // < 100ms - 绿色
|
||||||
|
MEDIUM: '\x1b[33m', // < 500ms - 黄色
|
||||||
|
SLOW: '\x1b[31m' // >= 500ms - 红色
|
||||||
|
};
|
||||||
|
|
||||||
|
const RESET_COLOR = '\x1b[0m';
|
||||||
|
|
||||||
// 创建logger实例
|
// 创建logger实例
|
||||||
const logger = defaultLogger.child('API');
|
const logger = defaultLogger.child('API');
|
||||||
|
|
||||||
@@ -58,42 +85,33 @@ function loggerMiddleware(req, res, next) {
|
|||||||
const method = req.method;
|
const method = req.method;
|
||||||
const url = req.originalUrl;
|
const url = req.originalUrl;
|
||||||
|
|
||||||
// 根据状态码选择图标
|
// 获取方法颜色
|
||||||
let statusIcon;
|
const methodColor = METHOD_COLORS[method] || METHOD_COLORS.DEFAULT;
|
||||||
|
|
||||||
|
// 获取状态码颜色
|
||||||
|
let statusColor;
|
||||||
if (statusCode >= 200 && statusCode < 300) {
|
if (statusCode >= 200 && statusCode < 300) {
|
||||||
statusIcon = '✅';
|
statusColor = STATUS_COLORS.SUCCESS;
|
||||||
} else if (statusCode >= 300 && statusCode < 400) {
|
} else if (statusCode >= 300 && statusCode < 400) {
|
||||||
statusIcon = '🔄';
|
statusColor = STATUS_COLORS.REDIRECT;
|
||||||
} else if (statusCode >= 400 && statusCode < 500) {
|
} else if (statusCode >= 400 && statusCode < 500) {
|
||||||
statusIcon = '⚠️';
|
statusColor = STATUS_COLORS.CLIENT_ERROR;
|
||||||
} else {
|
} else {
|
||||||
statusIcon = '❌';
|
statusColor = STATUS_COLORS.SERVER_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
// 根据请求类型选择图标
|
|
||||||
let methodIcon;
|
|
||||||
switch (method) {
|
|
||||||
case 'GET':
|
|
||||||
methodIcon = '📥';
|
|
||||||
break;
|
|
||||||
case 'POST':
|
|
||||||
methodIcon = '📤';
|
|
||||||
break;
|
|
||||||
case 'PUT':
|
|
||||||
methodIcon = '🔄';
|
|
||||||
break;
|
|
||||||
case 'DELETE':
|
|
||||||
methodIcon = '🗑️';
|
|
||||||
break;
|
|
||||||
case 'PATCH':
|
|
||||||
methodIcon = '🔧';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
methodIcon = '❓';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输出日志
|
// 获取响应时间颜色
|
||||||
logger.info(`${statusIcon} ${methodIcon} ${method} ${url} ${statusCode} ${duration}ms`);
|
let durationColor;
|
||||||
|
if (duration < 100) {
|
||||||
|
durationColor = DURATION_COLORS.FAST;
|
||||||
|
} else if (duration < 500) {
|
||||||
|
durationColor = DURATION_COLORS.MEDIUM;
|
||||||
|
} else {
|
||||||
|
durationColor = DURATION_COLORS.SLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出彩色日志
|
||||||
|
logger.info(`${methodColor}[${method}]${RESET_COLOR} ${url} ${statusColor}${statusCode}${RESET_COLOR} ${durationColor}${duration}ms${RESET_COLOR}`);
|
||||||
|
|
||||||
// 调用原始的end方法
|
// 调用原始的end方法
|
||||||
originalEnd.call(this, chunk, encoding);
|
originalEnd.call(this, chunk, encoding);
|
||||||
|
|||||||
+9
-9
@@ -34,7 +34,7 @@ class PixivServer {
|
|||||||
* 初始化服务器
|
* 初始化服务器
|
||||||
*/
|
*/
|
||||||
async init() {
|
async init() {
|
||||||
logger.info('🔧 正在初始化 Pixiv 后端服务器...');
|
logger.info('正在初始化 Pixiv 后端服务器...');
|
||||||
|
|
||||||
// 重新设置端口(从环境变量获取)
|
// 重新设置端口(从环境变量获取)
|
||||||
this.port = process.env.PORT || 3000;
|
this.port = process.env.PORT || 3000;
|
||||||
@@ -55,7 +55,7 @@ class PixivServer {
|
|||||||
// 配置错误处理
|
// 配置错误处理
|
||||||
this.setupErrorHandling();
|
this.setupErrorHandling();
|
||||||
|
|
||||||
logger.info('✅ 服务器初始化完成');
|
logger.info('服务器初始化完成');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,12 +99,12 @@ class PixivServer {
|
|||||||
*/
|
*/
|
||||||
start() {
|
start() {
|
||||||
this.app.listen(this.port, () => {
|
this.app.listen(this.port, () => {
|
||||||
logger.info('✅ Pixiv 后端服务器已启动');
|
logger.info('Pixiv 后端服务器已启动');
|
||||||
logger.info(`📍 服务地址: http://localhost:${this.port}`);
|
logger.info(`服务地址: http://localhost:${this.port}`);
|
||||||
logger.info(`🔗 健康检查: http://localhost:${this.port}/health`);
|
logger.info(`健康检查: http://localhost:${this.port}/health`);
|
||||||
logger.info(`📊 登录状态: ${this.backend.isLoggedIn ? '已登录' : '未登录'}`);
|
logger.info(`登录状态: ${this.backend.isLoggedIn ? '已登录' : '未登录'}`);
|
||||||
if (this.backend.isLoggedIn) {
|
if (this.backend.isLoggedIn) {
|
||||||
logger.info(`👤 用户: ${this.backend.config.user?.account}`);
|
logger.info(`用户: ${this.backend.config.user?.account}`);
|
||||||
}
|
}
|
||||||
logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||||
});
|
});
|
||||||
@@ -114,10 +114,10 @@ class PixivServer {
|
|||||||
* 优雅关闭
|
* 优雅关闭
|
||||||
*/
|
*/
|
||||||
async shutdown() {
|
async shutdown() {
|
||||||
logger.info('🔄 正在关闭服务器...');
|
logger.info('正在关闭服务器...');
|
||||||
// 清理代理环境变量
|
// 清理代理环境变量
|
||||||
proxyConfig.clearEnvironmentVariables();
|
proxyConfig.clearEnvironmentVariables();
|
||||||
logger.info('✅ 服务器已关闭');
|
logger.info('服务器已关闭');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class ImageCacheService {
|
|||||||
async ensureCacheDir() {
|
async ensureCacheDir() {
|
||||||
try {
|
try {
|
||||||
await fs.mkdir(this.cacheDir, { recursive: true });
|
await fs.mkdir(this.cacheDir, { recursive: true });
|
||||||
logger.info('图片缓存目录创建成功', { cacheDir: this.cacheDir });
|
logger.info('图片缓存目录创建成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('创建图片缓存目录失败', error);
|
logger.error('创建图片缓存目录失败', error);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -64,49 +64,49 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
|||||||
// 如果提供了代理端口,设置环境变量
|
// 如果提供了代理端口,设置环境变量
|
||||||
if (cliOptions.proxyPort) {
|
if (cliOptions.proxyPort) {
|
||||||
process.env.PROXY_PORT = cliOptions.proxyPort.toString();
|
process.env.PROXY_PORT = cliOptions.proxyPort.toString();
|
||||||
logger.info(`📡 代理端口已设置为: ${cliOptions.proxyPort}`);
|
logger.info(`代理端口已设置为: ${cliOptions.proxyPort}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果提供了服务器端口,设置环境变量
|
// 如果提供了服务器端口,设置环境变量
|
||||||
if (cliOptions.serverPort) {
|
if (cliOptions.serverPort) {
|
||||||
process.env.PORT = cliOptions.serverPort.toString();
|
process.env.PORT = cliOptions.serverPort.toString();
|
||||||
logger.info(`🌐 服务器端口已设置为: ${cliOptions.serverPort}`);
|
logger.info(`服务器端口已设置为: ${cliOptions.serverPort}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('🚀 启动 Pixiv 后端服务器...');
|
logger.info('启动 Pixiv 后端服务器...');
|
||||||
|
|
||||||
// 创建服务器实例
|
// 创建服务器实例
|
||||||
const server = new PixivServer();
|
const server = new PixivServer();
|
||||||
|
|
||||||
// 处理进程信号
|
// 处理进程信号
|
||||||
process.on('SIGINT', async () => {
|
process.on('SIGINT', async () => {
|
||||||
logger.info('🛑 收到 SIGINT 信号,正在关闭服务器...');
|
logger.info('收到 SIGINT 信号,正在关闭服务器...');
|
||||||
await server.shutdown();
|
await server.shutdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGTERM', async () => {
|
process.on('SIGTERM', async () => {
|
||||||
logger.info('🛑 收到 SIGTERM 信号,正在关闭服务器...');
|
logger.info('收到 SIGTERM 信号,正在关闭服务器...');
|
||||||
await server.shutdown();
|
await server.shutdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理未捕获的异常
|
// 处理未捕获的异常
|
||||||
process.on('uncaughtException', error => {
|
process.on('uncaughtException', error => {
|
||||||
logger.error('❌ 未捕获的异常', error);
|
logger.error('未捕获的异常', error);
|
||||||
logger.error('❌ 异常堆栈:', error.stack);
|
logger.error('异常堆栈:', error.stack);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('unhandledRejection', (reason, promise) => {
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
logger.error('❌ 未处理的 Promise 拒绝');
|
logger.error('未处理的 Promise 拒绝');
|
||||||
logger.error('❌ 拒绝原因:', reason);
|
logger.error('拒绝原因:', reason);
|
||||||
if (reason instanceof Error) {
|
if (reason instanceof Error) {
|
||||||
logger.error('❌ 错误堆栈:', reason.stack);
|
logger.error('错误堆栈:', reason.stack);
|
||||||
}
|
}
|
||||||
logger.error('❌ Promise:', promise);
|
logger.error('Promise:', promise);
|
||||||
|
|
||||||
// 不要立即退出进程,而是记录错误并继续运行
|
// 不要立即退出进程,而是记录错误并继续运行
|
||||||
// 这样可以避免因为自动恢复任务的小错误而停止整个服务
|
// 这样可以避免因为自动恢复任务的小错误而停止整个服务
|
||||||
logger.warn('⚠️ 继续运行服务器,但建议检查上述错误');
|
logger.warn('继续运行服务器,但建议检查上述错误');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 启动服务器
|
// 启动服务器
|
||||||
@@ -114,6 +114,6 @@ server
|
|||||||
.init()
|
.init()
|
||||||
.then(() => server.start())
|
.then(() => server.start())
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
logger.error('❌ 服务器启动失败', error);
|
logger.error('服务器启动失败', error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
+11
-12
@@ -39,6 +39,7 @@ const LogLevelColors = {
|
|||||||
*/
|
*/
|
||||||
const ModuleColors = {
|
const ModuleColors = {
|
||||||
'Server': '\x1b[32m', // 绿色
|
'Server': '\x1b[32m', // 绿色
|
||||||
|
'API': '\x1b[32m', // 绿色
|
||||||
'Start': '\x1b[34m', // 蓝色
|
'Start': '\x1b[34m', // 蓝色
|
||||||
'PixivBackend': '\x1b[35m', // 紫色
|
'PixivBackend': '\x1b[35m', // 紫色
|
||||||
'PixivAuth': '\x1b[36m', // 青色
|
'PixivAuth': '\x1b[36m', // 青色
|
||||||
@@ -51,7 +52,6 @@ const ModuleColors = {
|
|||||||
'Artist': '\x1b[92m', // 亮绿色
|
'Artist': '\x1b[92m', // 亮绿色
|
||||||
'Repository': '\x1b[94m', // 亮蓝色
|
'Repository': '\x1b[94m', // 亮蓝色
|
||||||
'ErrorHandler': '\x1b[91m', // 亮红色
|
'ErrorHandler': '\x1b[91m', // 亮红色
|
||||||
'API': '\x1b[97m', // 亮白色
|
|
||||||
'FileManager': '\x1b[98m', // 亮青色
|
'FileManager': '\x1b[98m', // 亮青色
|
||||||
'ProgressManager': '\x1b[99m', // 亮紫色
|
'ProgressManager': '\x1b[99m', // 亮紫色
|
||||||
'Default': '\x1b[39m' // 默认颜色
|
'Default': '\x1b[39m' // 默认颜色
|
||||||
@@ -63,14 +63,14 @@ const ModuleColors = {
|
|||||||
const RESET_COLOR = '\x1b[0m';
|
const RESET_COLOR = '\x1b[0m';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志图标映射
|
* 日志级别文本映射
|
||||||
*/
|
*/
|
||||||
const LogLevelIcons = {
|
const LogLevelTexts = {
|
||||||
[LogLevel.ERROR]: '❌',
|
[LogLevel.ERROR]: 'ERROR',
|
||||||
[LogLevel.WARN]: '⚠️',
|
[LogLevel.WARN]: 'WARN',
|
||||||
[LogLevel.INFO]: 'ℹ️',
|
[LogLevel.INFO]: 'INFO',
|
||||||
[LogLevel.DEBUG]: '🔧',
|
[LogLevel.DEBUG]: 'DEBUG',
|
||||||
[LogLevel.TRACE]: '🔍'
|
[LogLevel.TRACE]: 'TRACE'
|
||||||
};
|
};
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
@@ -143,10 +143,9 @@ class Logger {
|
|||||||
*/
|
*/
|
||||||
formatMessage(level, message, data = null) {
|
formatMessage(level, message, data = null) {
|
||||||
const timeStr = this.getTimeString();
|
const timeStr = this.getTimeString();
|
||||||
const levelName = LogLevelNames[level];
|
const levelName = LogLevelTexts[level];
|
||||||
const icon = LogLevelIcons[level];
|
|
||||||
|
|
||||||
let formattedMessage = `[${timeStr}] [${levelName}] [${this.module}] ${icon} ${message}`;
|
let formattedMessage = `[${timeStr}] [${levelName}] [${this.module}] ${message}`;
|
||||||
|
|
||||||
if (data !== null && data !== undefined) {
|
if (data !== null && data !== undefined) {
|
||||||
if (typeof data === 'object') {
|
if (typeof data === 'object') {
|
||||||
@@ -345,4 +344,4 @@ module.exports = {
|
|||||||
LogLevel,
|
LogLevel,
|
||||||
LogLevelNames,
|
LogLevelNames,
|
||||||
defaultLogger
|
defaultLogger
|
||||||
};
|
};
|
||||||
@@ -95,12 +95,12 @@ pause
|
|||||||
await fs.ensureDir(path.join(portableDir, 'data'));
|
await fs.ensureDir(path.join(portableDir, 'data'));
|
||||||
await fs.ensureDir(path.join(portableDir, 'downloads'));
|
await fs.ensureDir(path.join(portableDir, 'downloads'));
|
||||||
|
|
||||||
logger.info('✅ 便携版创建完成!');
|
logger.info('便携版创建完成!');
|
||||||
logger.info(`📁 位置: ${portableDir}`);
|
logger.info(`位置: ${portableDir}`);
|
||||||
logger.info('📦 可以将整个文件夹打包分发给用户');
|
logger.info('可以将整个文件夹打包分发给用户');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('❌ 创建便携版失败', error);
|
logger.error('创建便携版失败', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,20 +13,20 @@ set PROXY_PORT=
|
|||||||
set SERVER_PORT=3000
|
set SERVER_PORT=3000
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo 🚀 Pixiv Manager 启动中...
|
echo Pixiv Manager 启动中...
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
cd /d "%~dp0"
|
cd /d "%~dp0"
|
||||||
|
|
||||||
echo 📡 当前代理端口: %PROXY_PORT%
|
echo 当前代理端口: %PROXY_PORT%
|
||||||
echo 🌐 当前服务器端口: %SERVER_PORT%
|
echo 当前服务器端口: %SERVER_PORT%
|
||||||
echo 💡 如需修改端口,请用记事本打开此文件,修改对应的端口号
|
echo 如需修改端口,请用记事本打开此文件,修改对应的端口号
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
echo 📊 启动后端服务器...
|
echo 启动后端服务器...
|
||||||
echo 🌐 访问地址: http://localhost:%SERVER_PORT%
|
echo 访问地址: http://localhost:%SERVER_PORT%
|
||||||
echo.
|
echo.
|
||||||
echo 💡 提示: 按 Ctrl+C 停止服务器
|
echo 提示: 按 Ctrl+C 停止服务器
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: 启动服务器并传递代理端口和服务器端口
|
:: 启动服务器并传递代理端口和服务器端口
|
||||||
@@ -37,5 +37,5 @@ if "%PROXY_PORT%"=="" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ⏹️ 服务器已停止
|
echo 服务器已停止
|
||||||
pause
|
pause
|
||||||
Reference in New Issue
Block a user