heroku-debug
Version:
debugging plugin for the CLI
155 lines (123 loc) • 4.22 kB
JavaScript
var semver = require('semver')
var sqlSummary = require('sql-summary')
var debug = require('debug')('opbeat')
var shimmer = require('../shimmer')
module.exports = function (mysql, opbeat, version) {
if (!semver.satisfies(version, '^2.0.0')) {
debug('mysql version %s not suppoted - aborting...', version)
return mysql
}
debug('shimming mysql.createConnection')
shimmer.wrap(mysql, 'createConnection', wrapCreateConnection)
debug('shimming mysql.createPool')
shimmer.wrap(mysql, 'createPool', wrapCreatePool)
debug('shimming mysql.createPoolCluster')
shimmer.wrap(mysql, 'createPoolCluster', wrapCreatePoolCluster)
return mysql
function wrapCreateConnection (original) {
return function wrappedCreateConnection () {
var connection = original.apply(this, arguments)
wrapQueryable(connection, 'connection', opbeat)
return connection
}
}
function wrapCreatePool (original) {
return function wrappedCreatePool () {
var pool = original.apply(this, arguments)
debug('shimming mysql pool.getConnection')
shimmer.wrap(pool, 'getConnection', wrapGetConnection)
return pool
}
}
function wrapCreatePoolCluster (original) {
return function wrappedCreatePoolCluster () {
var cluster = original.apply(this, arguments)
debug('shimming mysql cluster.of')
shimmer.wrap(cluster, 'of', function wrapOf (original) {
return function wrappedOf () {
var ofCluster = original.apply(this, arguments)
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] = opbeat._instrumentation.bindFunction(function wrapedCallback (err, connection) { // eslint-disable-line handle-callback-err
if (connection) wrapQueryable(connection, 'getConnection() > connection', opbeat)
return cb.apply(this, arguments)
})
}
return original.apply(this, arguments)
}
}
}
function wrapQueryable (obj, objType, opbeat) {
debug('shimming mysql %s.query', objType)
shimmer.wrap(obj, 'query', wrapQuery)
function wrapQuery (original) {
return function wrappedQuery (sql, values, cb) {
var trace = opbeat.buildTrace()
var uuid = trace && trace.transaction._uuid
var hasCallback = false
var sqlStr
debug('intercepted call to mysql %s.query %o', objType, { uuid: uuid })
if (trace) {
trace.type = 'db.mysql.query'
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) {
debug('extracted sql from mysql query %o', { uuid: uuid, sql: sqlStr })
trace.extra.sql = sqlStr
trace.signature = 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 (trace && result && !hasCallback) {
shimmer.wrap(result, 'emit', function (original) {
return function (event) {
trace.start()
switch (event) {
case 'error':
case 'end':
trace.end()
}
return original.apply(this, arguments)
}
})
}
return result
function wrapCallback (cb) {
hasCallback = true
trace.start()
return function wrappedCallback () {
trace.end()
return cb.apply(this, arguments)
}
}
}
}
}