overleaf/libraries/metrics/statsd/mongodb.coffee
Henry Oswald bf18c6e513 MVP for running both statsd and prom side by side
statsd code is from v1.8.1
2019-01-30 11:11:37 +00:00

100 lines
3.4 KiB
CoffeeScript

module.exports =
monitor: (mongodb_require_path, logger) ->
try
# for the v1 driver the methods to wrap are in the mongodb
# module in lib/mongodb/db.js
mongodb = require("#{mongodb_require_path}")
try
# for the v2 driver the relevant methods are in the mongodb-core
# module in lib/topologies/{server,replset,mongos}.js
v2_path = mongodb_require_path.replace(/\/mongodb$/, '/mongodb-core')
mongodbCore = require(v2_path)
Metrics = require("./metrics")
monitorMethod = (base, method, type) ->
return unless base?
return unless (_method = base[method])?
arglen = _method.length
mongo_driver_v1_wrapper = (db_command, options, callback) ->
if (typeof callback == 'undefined')
callback = options
options = {}
collection = db_command.collectionName
if collection.match(/\$cmd$/)
# Ignore noisy command methods like authenticating, ismaster and ping
return _method.call this, db_command, options, callback
key = "mongo-requests.#{collection}.#{type}"
if db_command.query?
query = Object.keys(db_command.query).sort().join("_")
key += "." + query
timer = new Metrics.Timer(key)
start = new Date()
_method.call this, db_command, options, () ->
timer.done()
time = new Date() - start
logger.log
query: db_command.query
query_type: type
collection: collection
"response-time": new Date() - start
"mongo request"
callback.apply this, arguments
mongo_driver_v2_wrapper = (ns, ops, options, callback) ->
if (typeof callback == 'undefined')
callback = options
options = {}
if ns.match(/\$cmd$/)
# Ignore noisy command methods like authenticating, ismaster and ping
return _method.call this, ns, ops, options, callback
key = "mongo-requests.#{ns}.#{type}"
if ops[0].q? # ops[0].q
query = Object.keys(ops[0].q).sort().join("_")
key += "." + query
timer = new Metrics.Timer(key)
start = new Date()
_method.call this, ns, ops, options, () ->
timer.done()
time = new Date() - start
logger.log
query: ops[0].q
query_type: type
collection: ns
"response-time": new Date() - start
"mongo request"
callback.apply this, arguments
if arglen == 3
base[method] = mongo_driver_v1_wrapper
else if arglen == 4
base[method] = mongo_driver_v2_wrapper
monitorMethod(mongodb?.Db.prototype, "_executeQueryCommand", "query")
monitorMethod(mongodb?.Db.prototype, "_executeRemoveCommand", "remove")
monitorMethod(mongodb?.Db.prototype, "_executeInsertCommand", "insert")
monitorMethod(mongodb?.Db.prototype, "_executeUpdateCommand", "update")
monitorMethod(mongodbCore?.Server.prototype, "command", "command")
monitorMethod(mongodbCore?.Server.prototype, "remove", "remove")
monitorMethod(mongodbCore?.Server.prototype, "insert", "insert")
monitorMethod(mongodbCore?.Server.prototype, "update", "update")
monitorMethod(mongodbCore?.ReplSet.prototype, "command", "command")
monitorMethod(mongodbCore?.ReplSet.prototype, "remove", "remove")
monitorMethod(mongodbCore?.ReplSet.prototype, "insert", "insert")
monitorMethod(mongodbCore?.ReplSet.prototype, "update", "update")
monitorMethod(mongodbCore?.Mongos.prototype, "command", "command")
monitorMethod(mongodbCore?.Mongos.prototype, "remove", "remove")
monitorMethod(mongodbCore?.Mongos.prototype, "insert", "insert")
monitorMethod(mongodbCore?.Mongos.prototype, "update", "update")