UNPKG

elastic-apm-node

Version:

The official Elastic APM agent for Node.js

159 lines (125 loc) 4.49 kB
'use strict' var semver = require('semver') var sqlSummary = require('sql-summary') var shimmer = require('../shimmer') var symbols = require('../../symbols') module.exports = function (mysql, agent, { version, enabled }) { if (!semver.satisfies(version, '^2.0.0')) { agent.logger.debug('mysql version %s not supported - aborting...', version) return mysql } agent.logger.debug('shimming mysql.createPool') shimmer.wrap(mysql, 'createPool', wrapCreatePool) agent.logger.debug('shimming mysql.createPoolCluster') shimmer.wrap(mysql, 'createPoolCluster', wrapCreatePoolCluster) if (!enabled) return mysql agent.logger.debug('shimming mysql.createConnection') shimmer.wrap(mysql, 'createConnection', wrapCreateConnection) return mysql function wrapCreateConnection (original) { return function wrappedCreateConnection () { var connection = original.apply(this, arguments) wrapQueryable(connection, 'connection', agent) return connection } } function wrapCreatePool (original) { return function wrappedCreatePool () { var pool = original.apply(this, arguments) agent.logger.debug('shimming mysql pool.getConnection') shimmer.wrap(pool, 'getConnection', wrapGetConnection) return pool } } function wrapCreatePoolCluster (original) { return function wrappedCreatePoolCluster () { var cluster = original.apply(this, arguments) agent.logger.debug('shimming mysql cluster.of') shimmer.wrap(cluster, 'of', function wrapOf (original) { return function wrappedOf () { var ofCluster = original.apply(this, arguments) agent.logger.debug('shimming mysql cluster of.getConnection') shimmer.wrap(ofCluster, 'getConnection', wrapGetConnection) return ofCluster } }) return cluster } } function wrapGetConnection (original) { return function wrappedGetConnection () { var cb = arguments[0] if (typeof cb === 'function') { arguments[0] = agent._instrumentation.bindFunction(function wrapedCallback (err, connection) { // eslint-disable-line handle-callback-err if (connection && enabled) wrapQueryable(connection, 'getConnection() > connection', agent) return cb.apply(this, arguments) }) } return original.apply(this, arguments) } } } function wrapQueryable (obj, objType, agent) { agent.logger.debug('shimming mysql %s.query', objType) shimmer.wrap(obj, 'query', wrapQuery) function wrapQuery (original) { return function wrappedQuery (sql, values, cb) { var span = agent.startSpan(null, 'db.mysql.query') var id = span && span.transaction.id var hasCallback = false var sqlStr agent.logger.debug('intercepted call to mysql %s.query %o', objType, { id: id }) if (span) { if (this[symbols.knexStackObj]) { span.customStackTrace(this[symbols.knexStackObj]) this[symbols.knexStackObj] = null } switch (typeof sql) { case 'string': sqlStr = sql break case 'object': if (typeof sql._callback === 'function') { sql._callback = wrapCallback(sql._callback) } sqlStr = sql.sql break case 'function': arguments[0] = wrapCallback(sql) break } if (sqlStr) { agent.logger.debug('extracted sql from mysql query %o', { id: id, sql: sqlStr }) span.setDbContext({ statement: sqlStr, type: 'sql' }) span.name = sqlSummary(sqlStr) } if (typeof values === 'function') { arguments[1] = wrapCallback(values) } else if (typeof cb === 'function') { arguments[2] = wrapCallback(cb) } } var result = original.apply(this, arguments) if (span && result && !hasCallback) { shimmer.wrap(result, 'emit', function (original) { return function (event) { switch (event) { case 'error': case 'end': span.end() } return original.apply(this, arguments) } }) } return result function wrapCallback (cb) { hasCallback = true return function wrappedCallback () { span.end() return cb.apply(this, arguments) } } } } }