UNPKG

datadog-mongodb

Version:

MongoDB query performance monitoring with DataDog

106 lines (85 loc) 2.66 kB
"use strict"; var traceback = require("traceback"); var DD = require("node-dogstatsd").StatsD; module.exports = function (mongodb, options) { options = options || {}; var datadog = options.dogstatsd || new DD(); var stat = options.stat || "node.mongodb"; var wrapFunction = function (object, fnName) { var fn = object[fnName]; object[fnName] = function () { var args = Array.prototype.slice.call(arguments); var tags = []; tags.push("collection:" + this.collectionName); tags.push("operation:" + fnName); var stack; try { stack = traceback(); } catch (err) { // traceback failed... just continue without it stack = []; } // look for first file that is not in `node_modules` and not this module var stackLength = stack.length; for (var i = 0; i < stackLength; i++) { var path = stack[i].path; if ( path.indexOf("node_modules") == -1 && path.substr(0, 1) == "/" && path.indexOf(__dirname) == -1 ) { var calledBy = stack[i]; tags.push("caller:" + calledBy.path + ":" + calledBy.line); break; } } // look for query fields if (fnName != "insert" && typeof(args[0]) == "object") { // sort and comma delimit var fields = Object.keys(args[0]).sort().join(","); // only add the tag if we found fields if (fields !== "") { tags.push("fields:" + fields); } } // callback is always last so grab it var cb = args[args.length - 1]; if (typeof(cb) == "function") { // hold on to start time var start = new Date(); args[args.length - 1] = function (err) { // calc time to run operation var time = (new Date() - start); if (err) { tags.push("error:" + err.message); } // if update or remove grab the count argument if (arguments[1] && ( fnName == "update" || fnName == "remove" )) { tags.push("count:" + arguments[1]); } // if insert grab the length of the docs argument if (arguments[1] && fnName == "insert") { tags.push("count:" + arguments[1].length); } // send histogram data datadog.histogram(stat, time, 1, tags); datadog.set(stat + ".count", fnName, tags); // return and call callback return cb.apply(this, arguments); }; } else { // no callback just send the data datadog.set(stat + ".count", fnName, tags); } // return and call the function we are wrapping return fn.apply(this, args); }; }; // wrapp mongodb functions ["find", "update", "insert", "remove"].forEach(function (fnName) { wrapFunction(mongodb.Collection.prototype, fnName); }); };