必须先在 mongodb 服务端执行 db.setprofilinglevel(),node.js 层的监听才可能拿到慢查询数据;只改 node.js 代码、不配数据库,监控永远为空。

必须先在 MongoDB 服务端执行 db.setProfilingLevel(),Node.js 层的监听才可能拿到慢查询数据;只改 Node.js 代码、不配数据库,监控永远为空。
为什么 db.setProfilingLevel(1, { slowms: 100 }) 是前置硬性条件
Node.js 驱动本身不生成慢查询日志,它只是读取 MongoDB 已记录的内容。MongoDB 的 profiling 是服务端开关,关着时连 system.profile 集合都不会自动创建。
常见错误是:在应用里监听 slowQuery 事件或轮询 system.profile,但忘了进 shell 执行:use your_db_namedb.setProfilingLevel(1, { slowms: 200 })
生产环境建议从 slowms: 500 起步,避免日志写爆磁盘或拖慢主库。
system.profile 不支持 changeStream,轮询必须带 ts 索引和时间游标
直接对 system.profile 调用 watch() 会报 NamespaceNotFound 或 CommandNotSupported —— 这个集合是 capped 类型,changeStream 明确不支持。
可行方案只有轮询,且必须满足三个条件:
- 每次查完记录最新
ts值(ISODate类型),下次查询用{ ts: { $gt: lastTs } } - 手动建索引:
db.system.profile.createIndex({ ts: 1 }),否则轮询全表扫描极慢 - 轮询间隔 ≥1s,太密会导致
system.profile查询本身变成慢操作
Node.js 驱动层监听 commandStarted/commandSucceeded 事件更轻量
Driver 4.0+ 提供命令生命周期钩子,适合做客户端耗时统计,不依赖服务端 profiling,但无法替代服务端日志(比如没发到 Driver 的网络超时、连接中断等场景就捕获不到):
示例关键逻辑:
根据 package.json 中的 engines 字段自动检测 Node.js 版本需求,未安装 nvm 时自动安装并切换至对应版本。支持 Windows、macOS、Linux。适用于 Node.js 项目开发、版本切换和环境配置。
const client = new MongoClient(uri);
client.on('commandStarted', (event) => {
event.durationStart = process.hrtime();
});
client.on('commandSucceeded', (event) => {
const [sec, ns] = process.hrtime(event.durationStart);
const ms = sec * 1000 + Math.floor(ns / 1e6);
if (ms > 200) {
console.warn('Slow MongoDB cmd:', event.commandName, 'in', ms, 'ms');
}
});
注意:commandStarted 和 commandSucceeded 是 client 级别事件,不是 db 或 collection 实例上的方法;若用 Mongoose,需从 mongoose.connection.client 获取底层 client 实例。
Mongoose 的 slowms 设置仅影响自身日志,不触发服务端 profiling
很多人以为 mongoose.set('slowms', 100) 就能开启慢查询监控,其实它只控制 Mongoose 自己对 exec() 或 find() 的耗时打点,并不会让 MongoDB 记录到 system.profile,也不会触发 slowQuery 事件(该事件在新版 Mongoose 中已弃用)。
真实可用的组合是:
- 服务端开 profiling → 写入
system.profile - Node.js 层轮询该集合,或用 driver 监听命令事件
- Mongoose 可额外启用
set('debug', true)查看每条查询语句,辅助定位问题,但它不提供耗时阈值过滤
最易被忽略的是:system.profile 默认只存在于当前 DB,切换 use other_db 后要重新执行 setProfilingLevel;多租户架构下,每个业务库都得单独配,漏一个就监控断档。










