调试与日志记录技巧
调试与日志记录技巧
调试和日志记录是开发过程中不可或缺的部分,尤其是在使用 Mongoose 进行 MongoDB 操作时。合理的调试和日志记录能帮助快速定位问题,提高开发效率。以下是一些实用的技巧和示例。
启用 Mongoose 调试模式
Mongoose 内置了调试功能,可以通过设置 debug
选项来启用。启用后,Mongoose 会输出所有执行的查询和操作到控制台。
const mongoose = require('mongoose');
mongoose.set('debug', true);
// 连接数据库
mongoose.connect('mongodb://localhost:27017/test', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
启用调试模式后,控制台会输出类似以下内容:
Mongoose: users.insertOne({ name: 'John', age: 30, _id: ObjectId("..."), __v: 0 })
自定义日志输出
如果默认的调试输出不够详细,可以通过监听 Mongoose 的 debug
事件来自定义日志输出。
mongoose.set('debug', function(collectionName, method, query, doc) {
console.log(`Mongoose: ${collectionName}.${method}`, JSON.stringify(query), doc);
});
这样可以根据需要格式化日志,例如添加时间戳或过滤特定操作。
使用中间件记录操作日志
Mongoose 的中间件(pre/post hooks)可以用来记录模型的操作日志。例如,在保存文档前后记录日志:
const userSchema = new mongoose.Schema({
name: String,
age: Number,
});
userSchema.pre('save', function(next) {
console.log(`About to save user: ${this.name}`);
next();
});
userSchema.post('save', function(doc) {
console.log(`User saved: ${doc.name}`);
});
const User = mongoose.model('User', userSchema);
记录查询执行时间
对于性能敏感的查询,可以记录查询的执行时间,帮助优化性能。
const start = Date.now();
User.find({ age: { $gt: 25 } })
.then(users => {
const duration = Date.now() - start;
console.log(`Query took ${duration}ms`);
console.log(users);
})
.catch(err => console.error(err));
使用 Winston 或 Morgan 记录日志
对于生产环境,可以使用专业的日志库如 Winston 或 Morgan 来记录 Mongoose 的操作日志。
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'mongoose.log' }),
],
});
mongoose.set('debug', function(collectionName, method, query, doc) {
logger.info(`Mongoose: ${collectionName}.${method}`, { query, doc });
});
错误日志记录
Mongoose 操作中的错误需要妥善记录,以便后续排查。可以在 Promise 的 catch 块或 try-catch 中记录错误。
User.findById('someId')
.then(user => {
if (!user) {
throw new Error('User not found');
}
console.log(user);
})
.catch(err => {
logger.error('Error fetching user', { error: err.message });
});
使用 Mongoose 的日志级别
Mongoose 的 debug
选项支持传入一个函数,可以根据操作类型(如 query、update、delete)设置不同的日志级别。
mongoose.set('debug', function(collectionName, method, query, doc, options) {
const level = method === 'delete' ? 'warn' : 'info';
logger.log(level, `Mongoose: ${collectionName}.${method}`, { query, doc });
});
记录慢查询
可以通过中间件或全局设置记录执行时间过长的查询。
const slowQueryThreshold = 100; // 100ms
mongoose.set('debug', function(collectionName, method, query, doc, options) {
const start = Date.now();
return function() {
const duration = Date.now() - start;
if (duration > slowQueryThreshold) {
logger.warn(`Slow query: ${collectionName}.${method} took ${duration}ms`, { query });
}
};
});
结合 Sentry 或类似工具
对于生产环境,可以将 Mongoose 的错误日志集成到 Sentry 等错误监控工具中。
const Sentry = require('@sentry/node');
User.findById('invalidId')
.then(user => console.log(user))
.catch(err => {
Sentry.captureException(err);
logger.error('Error in User.findById', { error: err.message });
});
日志过滤与脱敏
记录日志时需要注意敏感信息(如密码)的脱敏处理。
mongoose.set('debug', function(collectionName, method, query, doc) {
const sanitizedQuery = JSON.parse(JSON.stringify(query));
if (sanitizedQuery.password) {
sanitizedQuery.password = '***';
}
logger.info(`Mongoose: ${collectionName}.${method}`, { query: sanitizedQuery });
});
使用环境变量控制日志级别
根据环境(开发、测试、生产)动态调整日志级别。
const isProduction = process.env.NODE_ENV === 'production';
mongoose.set('debug', isProduction ? false : true);
记录连接状态
Mongoose 的连接事件(如 connected、disconnected)也可以记录到日志中。
mongoose.connection.on('connected', () => {
logger.info('Mongoose connected to MongoDB');
});
mongoose.connection.on('error', err => {
logger.error('Mongoose connection error', { error: err.message });
});
mongoose.connection.on('disconnected', () => {
logger.warn('Mongoose disconnected from MongoDB');
});
使用 Mongoose 的 lean()
调试查询
lean()
可以跳过 Mongoose 的文档转换,直接返回纯 JavaScript 对象。这在调试查询性能时很有用。
User.find({ age: { $gt: 25 } })
.lean()
.then(users => {
console.log('Lean query result:', users);
})
.catch(err => console.error(err));
记录批量操作
对于批量操作(如 insertMany、updateMany),可以记录操作影响的文档数量。
User.insertMany([{ name: 'Alice' }, { name: 'Bob' }])
.then(docs => {
logger.info(`Inserted ${docs.length} users`);
})
.catch(err => logger.error('Error in insertMany', { error: err.message }));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:版本兼容性问题
下一篇:Mongoose社区与资源