UNPKG

elastic-apm-node

Version:

The official Elastic APM agent for Node.js

131 lines (107 loc) 4.12 kB
'use strict' var semver = require('semver') var shimmer = require('../shimmer') var SERVER_FNS = ['insert', 'update', 'remove', 'auth'] var CURSOR_FNS_FIRST = ['next', '_getmore'] const firstSpan = Symbol('first-span') module.exports = function (mongodb, agent, { version, enabled }) { if (!enabled) return mongodb if (!semver.satisfies(version, '>=1.2.19 <4')) { agent.logger.debug('mongodb-core version %s not supported - aborting...', version) return mongodb } if (mongodb.Server) { agent.logger.debug('shimming mongodb-core.Server.prototype.command') shimmer.wrap(mongodb.Server.prototype, 'command', wrapCommand) agent.logger.debug('shimming mongodb-core.Server.prototype functions:', SERVER_FNS) shimmer.massWrap(mongodb.Server.prototype, SERVER_FNS, wrapQuery) } if (mongodb.Cursor) { agent.logger.debug('shimming mongodb-core.Cursor.prototype functions:', CURSOR_FNS_FIRST) shimmer.massWrap(mongodb.Cursor.prototype, CURSOR_FNS_FIRST, wrapCursor) } return mongodb function wrapCommand (orig) { return function wrappedFunction (ns, cmd) { var trans = agent._instrumentation.currentTransaction var id = trans && trans.id var span agent.logger.debug('intercepted call to mongodb-core.Server.prototype.command %o', { id: id, ns: ns }) if (trans && arguments.length > 0) { var index = arguments.length - 1 var cb = arguments[index] if (typeof cb === 'function') { var type if (cmd.findAndModify) type = 'findAndModify' else if (cmd.createIndexes) type = 'createIndexes' else if (cmd.ismaster) type = 'ismaster' else if (cmd.count) type = 'count' else type = 'command' span = agent.startSpan(ns + '.' + type, 'db.mongodb.query') if (span) { arguments[index] = wrappedCallback } } } return orig.apply(this, arguments) function wrappedCallback () { agent.logger.debug('intercepted mongodb-core.Server.prototype.command callback %o', { id: id }) span.end() return cb.apply(this, arguments) } } } function wrapQuery (orig, name) { return function wrappedFunction (ns) { var trans = agent._instrumentation.currentTransaction var id = trans && trans.id var span agent.logger.debug('intercepted call to mongodb-core.Server.prototype.%s %o', name, { id: id, ns: ns }) if (trans && arguments.length > 0) { var index = arguments.length - 1 var cb = arguments[index] if (typeof cb === 'function') { span = agent.startSpan(ns + '.' + name, 'db.mongodb.query') if (span) { arguments[index] = wrappedCallback } } } return orig.apply(this, arguments) function wrappedCallback () { agent.logger.debug('intercepted mongodb-core.Server.prototype.%s callback %o', name, { id: id }) span.end() return cb.apply(this, arguments) } } } function wrapCursor (orig, name) { return function wrappedFunction () { var trans = agent._instrumentation.currentTransaction var id = trans && trans.id var span agent.logger.debug('intercepted call to mongodb-core.Cursor.prototype.%s %o', name, { id: id }) if (trans && arguments.length > 0) { var cb = arguments[0] if (typeof cb === 'function') { if (name !== 'next' || !this[firstSpan]) { var spanName = `${this.ns}.${this.cmd.find ? 'find' : name}` span = agent.startSpan(spanName, 'db.mongodb.query') } if (span) { arguments[0] = wrappedCallback if (name === 'next') { this[firstSpan] = true } } } } return orig.apply(this, arguments) function wrappedCallback () { agent.logger.debug('intercepted mongodb-core.Cursor.prototype.%s callback %o', name, { id: id }) span.end() return cb.apply(this, arguments) } } } }