Koa 应用的错误处理与日志记录方案
发布时间:2025-04-28 | 分类:最佳实践
统一错误捕获中间件
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || err.statusCode || 500;
ctx.body = {
success: false,
message: err.message || '服务器内部错误'
};
ctx.app.emit('error', err, ctx);
}
});
日志记录实现
const fs = require('fs');
const path = require('path');
const logDir = path.join(__dirname, 'logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
function log(message) {
const date = new Date().toISOString();
const logFile = path.join(logDir, `${new Date().toDateString()}.log`);
fs.appendFileSync(logFile, `[${date}] ${message}\n`);
}
app.on('error', (err, ctx) => {
log(`Error: ${err.message} | URL: ${ctx.url} | IP: ${ctx.ip}`);
});
请求日志中间件
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
log(`${ctx.method} ${ctx.url} ${ctx.status} ${ms}ms`);
});
自定义错误类
class AppError extends Error {
constructor(message, status = 500) {
super(message);
this.status = status;
}
}
class NotFoundError extends AppError {
constructor(message = '资源不存在') {
super(message, 404);
}
}
class ValidationError extends AppError {
constructor(message = '参数验证失败') {
super(message, 400);
}
}
生产环境错误处理
app.on('error', (err, ctx) => {
if (process.env.NODE_ENV === 'production') {
// 发送告警通知
sendAlert(err);
} else {
console.error(err);
}
});