Socket
Socket
Sign inDemoInstall

dd-trace

Package Overview
Dependencies
19
Maintainers
3
Versions
558
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.0 to 0.3.1

src/plugins/index.js

2

lib/version.js

@@ -1,1 +0,1 @@

module.exports = '0.3.0'
module.exports = '0.3.1'
{
"name": "dd-trace",
"version": "0.3.0",
"version": "0.3.1",
"description": "Datadog APM tracing client for JavaScript (experimental)",

@@ -41,2 +41,3 @@ "main": "index.js",

"lodash.kebabcase": "^4.1.1",
"lodash.uniq": "^4.5.0",
"methods": "^1.1.2",

@@ -49,3 +50,2 @@ "msgpack-lite": "^0.1.26",

"read-pkg-up": "^3.0.0",
"require-dir": "^1.0.0",
"require-in-the-middle": "^2.2.2",

@@ -52,0 +52,0 @@ "safe-buffer": "^5.1.1",

@@ -8,8 +8,11 @@ 'use strict'

const pkg = require('../package.json')
exec('npm whoami')
exec('git checkout master')
exec('git pull')
const pkg = require('../package.json')
exec(`git tag v${pkg.version}`)
exec(`git push origin refs/tags/v${pkg.version}`)
exec('npm publish')
exec(`node scripts/publish_docs.js "v${pkg.version}"`)
'use strict'
const requireDir = require('require-dir')
const path = require('path')
const semver = require('semver')
const hook = require('require-in-the-middle')
const shimmer = require('shimmer')
const uniq = require('lodash.uniq')
const log = require('./log')
// TODO: lazy load built-in plugins
shimmer({ logger: () => {} })

@@ -14,3 +14,3 @@ class Instrumenter {

this._tracer = tracer
this._integrations = loadIntegrations()
this._names = []
this._plugins = new Map()

@@ -21,9 +21,8 @@ this._instrumented = new Map()

use (name, config) {
if (typeof name === 'string') {
this._integrations
.filter(plugin => plugin.name === name)
.forEach(plugin => this._set(plugin, config))
} else if (name) {
[].concat(name)
.forEach(plugin => this._set(plugin, config))
config = config || {}
try {
this._set(require(`./plugins/${name}`), { name, config })
} catch (e) {
log.debug(`Could not find a plugin named "${name}".`)
}

@@ -38,5 +37,8 @@

if (config.plugins !== false) {
this._integrations.forEach(integration => {
this._plugins.has(integration) || this._set(integration, {})
})
const plugins = require('./plugins')
Object.keys(plugins)
.forEach(name => {
this._plugins.has(plugins[name]) || this._set(plugins[name], { name, config: {} })
})
}

@@ -48,29 +50,69 @@

unpatch () {
this._instrumented.forEach((instrumentation, moduleExports) => {
instrumentation.unpatch(moduleExports)
this._instrumented.forEach((moduleExports, instrumentation) => {
this._unpatch(instrumentation)
})
this._plugins.clear()
}
reload () {
try {
const instrumentedModules = Array.from(this._plugins.keys()).map(plugin => plugin.name)
hook(instrumentedModules, this.hookModule.bind(this))
} catch (e) {
log.error(e)
const instrumentations = Array.from(this._plugins.keys())
.reduce((prev, current) => prev.concat(current), [])
const instrumentedModules = uniq(instrumentations
.map(instrumentation => instrumentation.name))
this._names = instrumentations
.map(instrumentation => filename(instrumentation))
hook(instrumentedModules, { internals: true }, this.hookModule.bind(this))
}
wrap (nodule, name) {
if (typeof nodule[name] !== 'function') {
throw new Error(`Expected object ${nodule} to contain method ${name}.`)
}
return shimmer.wrap.apply(this, arguments)
}
unwrap () {
return shimmer.unwrap.apply(this, arguments)
}
hookModule (moduleExports, moduleName, moduleBaseDir) {
if (this._names.indexOf(moduleName) === -1) {
return moduleExports
}
const moduleVersion = getVersion(moduleBaseDir)
Array.from(this._plugins.keys())
.filter(plugin => plugin.name === moduleName)
.filter(plugin => matchVersion(moduleVersion, plugin.versions))
.forEach(plugin => {
let moduleToPatch = moduleExports
if (plugin.file) {
moduleToPatch = require(path.join(moduleBaseDir, plugin.file))
.filter(plugin => [].concat(plugin).some(instrumentation => filename(instrumentation) === moduleName))
.forEach(plugin => this._validate(plugin, moduleBaseDir))
this._plugins
.forEach((meta, plugin) => {
try {
[].concat(plugin)
.filter(instrumentation => moduleName === filename(instrumentation))
.filter(instrumentation => matchVersion(moduleVersion, instrumentation.versions))
.forEach(instrumentation => {
const modulePath = [moduleBaseDir, instrumentation.file].filter(val => val).join('/')
if (require.cache[modulePath]) {
log.debug([
`Instrumented module "${moduleName}" was imported before calling tracer.init().`,
`Please make sure to initialize the tracer before importing any instrumented module.`
].join(' '))
}
this._instrumented.set(instrumentation, moduleExports)
instrumentation.patch.call(this, moduleExports, this._tracer._tracer, this._plugins.get(plugin).config)
})
} catch (e) {
log.error(e)
this._fail(plugin)
log.debug(`Error while trying to patch ${meta.name}. The plugin has been disabled.`)
}
plugin.patch(moduleToPatch, this._tracer._tracer, this._plugins.get(plugin))
this._instrumented.set(moduleToPatch, plugin)
})

@@ -81,22 +123,39 @@

_set (plugin, config) {
config = config || {}
_set (plugin, meta) {
this._plugins.set(plugin, Object.assign({ config: {} }, meta))
}
this._plugins.set(plugin, config)
_validate (plugin, moduleBaseDir) {
const meta = this._plugins.get(plugin)
const instrumentations = [].concat(plugin)
if (require.cache[plugin.name]) {
log.debug([
`Instrumented module "${plugin.name}" was imported before calling tracer.init().`,
`Please make sure to initialize the tracer before importing any instrumented module.`
].join(' '))
for (let i = 0; i < instrumentations.length; i++) {
if (instrumentations[i].file && !exists(moduleBaseDir, instrumentations[i].file)) {
this._fail(plugin)
log.debug([
`Plugin "${meta.name}" requires "${instrumentations[i].file}" which was not found.`,
`The plugin was disabled.`
].join(' '))
break
}
}
}
}
function loadIntegrations () {
const integrations = requireDir(path.join(__dirname, './plugins'))
_fail (plugin) {
[].concat(plugin)
.forEach(instrumentation => {
this._unpatch(instrumentation)
this._instrumented.delete(instrumentation)
})
return Object.keys(integrations)
.map(key => integrations[key])
.reduce((previous, current) => previous.concat(current), [])
this._plugins.delete(plugin)
}
_unpatch (instrumentation) {
try {
instrumentation.unpatch.call(this, this._instrumented.get(instrumentation))
} catch (e) {
log.error(e)
}
}
}

@@ -110,3 +169,3 @@

if (moduleBaseDir) {
const packageJSON = path.join(moduleBaseDir, 'package.json')
const packageJSON = `${moduleBaseDir}/package.json`
return require(packageJSON).version

@@ -116,2 +175,15 @@ }

function filename (plugin) {
return [plugin.name, plugin.file].filter(val => val).join('/')
}
function exists (basedir, file) {
try {
require.resolve(`${basedir}/${file}`)
return true
} catch (e) {
return false
}
}
module.exports = Instrumenter
'use strict'
const shimmer = require('shimmer')
const kebabCase = require('lodash.kebabcase')

@@ -113,7 +112,12 @@

'resource.name': getResourceName(method, fields),
'span.type': 'worker',
'out.host': channel.connection.stream._host,
'out.port': channel.connection.stream.remotePort
'span.type': 'worker'
})
if (channel.connection && channel.connection.stream) {
span.addTags({
'out.host': channel.connection.stream._host,
'out.port': channel.connection.stream.remotePort
})
}
switch (method) {

@@ -155,14 +159,14 @@ case 'basic.publish':

patch (channel, tracer, config) {
shimmer.wrap(channel.Channel.prototype, 'sendOrEnqueue', createWrapSendOrEnqueue(tracer, config))
shimmer.wrap(channel.Channel.prototype, 'sendImmediately', createWrapSendImmediately(tracer, config))
shimmer.wrap(channel.Channel.prototype, 'sendMessage', createWrapSendMessage(tracer, config))
shimmer.wrap(channel.BaseChannel.prototype, 'dispatchMessage', createWrapDispatchMessage(tracer, config))
this.wrap(channel.Channel.prototype, 'sendOrEnqueue', createWrapSendOrEnqueue(tracer, config))
this.wrap(channel.Channel.prototype, 'sendImmediately', createWrapSendImmediately(tracer, config))
this.wrap(channel.Channel.prototype, 'sendMessage', createWrapSendMessage(tracer, config))
this.wrap(channel.BaseChannel.prototype, 'dispatchMessage', createWrapDispatchMessage(tracer, config))
},
unpatch (channel) {
shimmer.unwrap(channel.Channel.prototype, 'sendOrEnqueue')
shimmer.unwrap(channel.Channel.prototype, 'sendImmediately')
shimmer.unwrap(channel.Channel.prototype, 'sendMessage')
shimmer.unwrap(channel.BaseChannel.prototype, 'dispatchMessage')
this.unwrap(channel.Channel.prototype, 'sendOrEnqueue')
this.unwrap(channel.Channel.prototype, 'sendImmediately')
this.unwrap(channel.Channel.prototype, 'sendMessage')
this.unwrap(channel.BaseChannel.prototype, 'dispatchMessage')
}
}
]
'use strict'
const Tags = require('opentracing').Tags
const shimmer = require('shimmer')

@@ -113,6 +112,6 @@ function createWrapRequest (tracer, config) {

patch (ConnectionPool, tracer, config) {
shimmer.wrap(ConnectionPool.prototype, 'select', createWrapSelect(tracer, config))
this.wrap(ConnectionPool.prototype, 'select', createWrapSelect(tracer, config))
},
unpatch (ConnectionPool) {
shimmer.unwrap(ConnectionPool.prototype, 'select')
this.unwrap(ConnectionPool.prototype, 'select')
}

@@ -125,8 +124,8 @@ },

patch (Transport, tracer, config) {
shimmer.wrap(Transport.prototype, 'request', createWrapRequest(tracer, config))
this.wrap(Transport.prototype, 'request', createWrapRequest(tracer, config))
},
unpatch (Transport) {
shimmer.unwrap(Transport.prototype, 'request')
this.unwrap(Transport.prototype, 'request')
}
}
]

@@ -6,3 +6,2 @@ 'use strict'

const FORMAT_HTTP_HEADERS = opentracing.FORMAT_HTTP_HEADERS
const shimmer = require('shimmer')
const METHODS = require('methods').concat('use', 'route', 'param', 'all')

@@ -153,14 +152,14 @@ const pathToRegExp = require('path-to-regexp')

METHODS.forEach(method => {
shimmer.wrap(express.application, method, createWrapMethod(tracer, config))
this.wrap(express.application, method, createWrapMethod(tracer, config))
})
shimmer.wrap(express.Router, 'process_params', createWrapProcessParams(tracer, config))
shimmer.wrap(express.Router, 'use', createWrapRouterMethod(tracer, config))
shimmer.wrap(express.Router, 'route', createWrapRouterMethod(tracer, config))
this.wrap(express.Router, 'process_params', createWrapProcessParams(tracer, config))
this.wrap(express.Router, 'use', createWrapRouterMethod(tracer, config))
this.wrap(express.Router, 'route', createWrapRouterMethod(tracer, config))
}
function unpatch (express) {
METHODS.forEach(method => shimmer.unwrap(express.application, method))
shimmer.unwrap(express.Router, 'process_params')
shimmer.unwrap(express.Router, 'use')
shimmer.unwrap(express.Router, 'route')
METHODS.forEach(method => this.unwrap(express.application, method))
this.unwrap(express.Router, 'process_params')
this.unwrap(express.Router, 'use')
this.unwrap(express.Router, 'route')
}

@@ -167,0 +166,0 @@

'use strict'
const shimmer = require('shimmer')
const platform = require('../platform')
function createWrapGraphql (tracer, config, defaultFieldResolver) {
return function wrapGraphql (graphql) {
return function graphqlWithTrace () {
const source = arguments[1] || arguments[0].source
const contextValue = arguments[3] || arguments[0].contextValue || {}
function createWrapExecute (tracer, config, defaultFieldResolver) {
return function wrapExecute (execute) {
return function executeWithTrace () {
const args = normalizeArgs(arguments)
const schema = args.schema
const document = args.document
const contextValue = args.contextValue || {}
const fieldResolver = args.fieldResolver || defaultFieldResolver
if (arguments.length === 1) {
arguments[0].contextValue = contextValue
} else {
arguments[3] = contextValue
arguments.length = Math.max(arguments.length, 4)
if (!schema || !document || typeof fieldResolver !== 'function') {
return execute.apply(this, arguments)
}
args.fieldResolver = wrapResolve(fieldResolver, tracer, config)
args.contextValue = contextValue
Object.defineProperties(contextValue, {
_datadog_operation: { value: {} },
_datadog_fields: { value: {} },
_datadog_source: { value: source }
_datadog_source: { value: document._datadog_source }
})
return graphql.apply(this, arguments)
if (!schema._datadog_patched) {
wrapFields(schema._queryType._fields, tracer, config, [])
schema._datadog_patched = true
}
return call(execute, this, [args], defer(tracer), () => finishOperation(contextValue))
}

@@ -30,18 +37,12 @@ }

function createWrapExecute (tracer, config, defaultFieldResolver) {
return function wrapExecute (execute) {
return function executeWithTrace () {
const schema = arguments[0]
const contextValue = arguments[3]
const fieldResolver = arguments[6] || defaultFieldResolver
function createWrapParse () {
return function wrapParse (parse) {
return function parseWithTrace (source) {
const document = parse.apply(this, arguments)
arguments[6] = wrapResolve(fieldResolver, tracer, config)
arguments[3] = contextValue
Object.defineProperties(document, {
_datadog_source: { value: source }
})
if (!schema._datadog_patched) {
wrapFields(schema._queryType._fields, tracer, config, [])
schema._datadog_patched = true
}
return call(execute, this, arguments, defer(tracer), () => finishOperation(contextValue))
return document
}

@@ -139,2 +140,18 @@ }

function normalizeArgs (args) {
if (args.length === 1) {
return args
}
return {
schema: args[0],
document: args[1],
rootValue: args[2],
contextValue: args[3],
variableValues: args[4],
operationName: args[5],
fieldResolver: args[6]
}
}
function createOperationSpan (tracer, config, contextValue, info) {

@@ -223,9 +240,9 @@ const type = info.operation.operation

name: 'graphql',
file: 'graphql.js',
file: 'execution/execute.js',
versions: ['0.13.x'],
patch (graphql, tracer, config) {
shimmer.wrap(graphql, 'graphql', createWrapGraphql(tracer, config))
patch (execute, tracer, config) {
this.wrap(execute, 'execute', createWrapExecute(tracer, config, execute.defaultFieldResolver))
},
unpatch (graphql) {
shimmer.unwrap(graphql, 'graphql')
unpatch (execute) {
this.unwrap(execute, 'execute')
}

@@ -235,11 +252,11 @@ },

name: 'graphql',
file: 'execution/execute.js',
file: 'language/parser.js',
versions: ['0.13.x'],
patch (execute, tracer, config) {
shimmer.wrap(execute, 'execute', createWrapExecute(tracer, config, execute.defaultFieldResolver))
patch (parser, tracer, config) {
this.wrap(parser, 'parse', createWrapParse(tracer, config))
},
unpatch (execute) {
shimmer.unwrap(execute, 'execute')
unpatch (parser) {
this.unwrap(parser, 'parse')
}
}
]

@@ -5,3 +5,2 @@ 'use strict'

const opentracing = require('opentracing')
const shimmer = require('shimmer')

@@ -12,4 +11,4 @@ const Tags = opentracing.Tags

function patch (http, tracer, config) {
shimmer.wrap(http, 'request', request => makeRequestTrace(request))
shimmer.wrap(http, 'get', get => makeRequestTrace(get))
this.wrap(http, 'request', request => makeRequestTrace(request))
this.wrap(http, 'get', get => makeRequestTrace(get))

@@ -94,4 +93,4 @@ function makeRequestTrace (request) {

function unpatch (http) {
shimmer.unwrap(http, 'request')
shimmer.unwrap(http, 'get')
this.unwrap(http, 'request')
this.unwrap(http, 'get')
}

@@ -98,0 +97,0 @@

@@ -5,4 +5,2 @@ 'use strict'

const shimmer = require('shimmer')
// Reference https://docs.mongodb.com/v3.6/reference/command/

@@ -198,10 +196,4 @@ const DATABASE_COMMANDS = [

span = child
span.addTags({
'service.name': config.service || 'mongodb',
'resource.name': resource,
'span.type': 'db',
'db.name': ns,
'out.host': this.s.options.host,
'out.port': this.s.options.port
})
addTags(span, config, resource, ns, this)
})

@@ -227,11 +219,10 @@

span = child
span.addTags({
'service.name': config.service || 'mongodb',
'resource.name': resource,
'span.type': 'db',
'db.name': this.ns,
'out.host': this.topology.s.options.host,
'out.port': this.topology.s.options.port,
'mongodb.cursor.index': this.cursorState.cursorIndex
})
addTags(span, config, resource, this.ns, this.topology)
if (this.cursorState) {
span.addTags({
'mongodb.cursor.index': this.cursorState.cursorIndex
})
}
})

@@ -244,2 +235,18 @@

function addTags (span, config, resource, ns, topology) {
span.addTags({
'service.name': config.service || 'mongodb',
'resource.name': resource,
'span.type': 'db',
'db.name': ns
})
if (topology.s && topology.s.options) {
span.addTags({
'out.host': topology.s.options.host,
'out.port': topology.s.options.port
})
}
}
function wrapCallback (tracer, span, done) {

@@ -300,16 +307,16 @@ return tracer.bind((err, res) => {

patch (mongo, tracer, config) {
shimmer.wrap(mongo.Server.prototype, 'command', createWrapOperation(tracer, config))
shimmer.wrap(mongo.Server.prototype, 'insert', createWrapOperation(tracer, config, 'insert'))
shimmer.wrap(mongo.Server.prototype, 'update', createWrapOperation(tracer, config, 'update'))
shimmer.wrap(mongo.Server.prototype, 'remove', createWrapOperation(tracer, config, 'remove'))
shimmer.wrap(mongo.Cursor.prototype, 'next', createWrapNext(tracer, config))
this.wrap(mongo.Server.prototype, 'command', createWrapOperation(tracer, config))
this.wrap(mongo.Server.prototype, 'insert', createWrapOperation(tracer, config, 'insert'))
this.wrap(mongo.Server.prototype, 'update', createWrapOperation(tracer, config, 'update'))
this.wrap(mongo.Server.prototype, 'remove', createWrapOperation(tracer, config, 'remove'))
this.wrap(mongo.Cursor.prototype, 'next', createWrapNext(tracer, config))
},
unpatch (mongo) {
shimmer.unwrap(mongo.Server.prototype, 'command')
shimmer.unwrap(mongo.Server.prototype, 'insert')
shimmer.unwrap(mongo.Server.prototype, 'update')
shimmer.unwrap(mongo.Server.prototype, 'remove')
shimmer.unwrap(mongo.Cursor.prototype, 'next')
this.unwrap(mongo.Server.prototype, 'command')
this.unwrap(mongo.Server.prototype, 'insert')
this.unwrap(mongo.Server.prototype, 'update')
this.unwrap(mongo.Server.prototype, 'remove')
this.unwrap(mongo.Cursor.prototype, 'next')
}
}
]
'use strict'
const Tags = require('opentracing').Tags
const shimmer = require('shimmer')

@@ -65,7 +64,7 @@ function createWrapQuery (tracer, config) {

function patchConnection (Connection, tracer, config) {
shimmer.wrap(Connection.prototype, 'query', createWrapQuery(tracer, config))
this.wrap(Connection.prototype, 'query', createWrapQuery(tracer, config))
}
function unpatchConnection (Connection) {
shimmer.unwrap(Connection.prototype, 'query')
this.unwrap(Connection.prototype, 'query')
}

@@ -72,0 +71,0 @@

'use strict'
const Tags = require('opentracing').Tags
const shimmer = require('shimmer')

@@ -65,7 +64,7 @@ function createWrapQuery (tracer, config) {

function patchConnection (Connection, tracer, config) {
shimmer.wrap(Connection.prototype, 'query', createWrapQuery(tracer, config))
this.wrap(Connection.prototype, 'query', createWrapQuery(tracer, config))
}
function unpatchConnection (Connection) {
shimmer.unwrap(Connection.prototype, 'query')
this.unwrap(Connection.prototype, 'query')
}

@@ -72,0 +71,0 @@

'use strict'
const Tags = require('opentracing').Tags
const shimmer = require('shimmer')

@@ -25,8 +24,11 @@ const OPERATION_NAME = 'pg.query'

span.setTag('resource.name', statement)
span.setTag('db.name', params.database)
span.setTag('db.user', params.user)
span.setTag('out.host', params.host)
span.setTag('out.port', String(params.port))
span.setTag('span.type', 'db')
if (params) {
span.setTag('db.name', params.database)
span.setTag('db.user', params.user)
span.setTag('out.host', params.host)
span.setTag('out.port', String(params.port))
}
if (err) {

@@ -52,7 +54,7 @@ span.addTags({

shimmer.wrap(pg.Client.prototype, 'query', queryWrap)
this.wrap(pg.Client.prototype, 'query', queryWrap)
}
function unpatch (pg) {
shimmer.unwrap(pg.Client.prototype, 'query')
this.unwrap(pg.Client.prototype, 'query')
}

@@ -59,0 +61,0 @@

'use strict'
const Tags = require('opentracing').Tags
const shimmer = require('shimmer')

@@ -19,4 +18,5 @@ function createWrapCreateClient (tracer) {

return function createStreamWithTrace () {
createStream.apply(this, arguments)
const returnValue = createStream.apply(this, arguments)
tracer.bindEmitter(this.stream)
return returnValue
}

@@ -42,6 +42,11 @@ }

'span.type': 'db',
'db.name': this.selected_db || '0',
'out.host': String(this.connection_options.host),
'out.port': String(this.connection_options.port)
'db.name': this.selected_db || '0'
})
if (this.connection_options) {
span.addTags({
'out.host': String(this.connection_options.host),
'out.port': String(this.connection_options.port)
})
}
})

@@ -75,11 +80,11 @@

function patch (redis, tracer, config) {
shimmer.wrap(redis.RedisClient.prototype, 'internal_send_command', createWrapInternalSendCommand(tracer, config))
shimmer.wrap(redis, 'createClient', createWrapCreateClient(tracer, config))
shimmer.wrap(redis.RedisClient.prototype, 'create_stream', createWrapCreateStream(tracer, config))
this.wrap(redis.RedisClient.prototype, 'internal_send_command', createWrapInternalSendCommand(tracer, config))
this.wrap(redis, 'createClient', createWrapCreateClient(tracer, config))
this.wrap(redis.RedisClient.prototype, 'create_stream', createWrapCreateStream(tracer, config))
}
function unpatch (redis) {
shimmer.unwrap(redis.RedisClient.prototype, 'internal_send_command')
shimmer.unwrap(redis, 'createClient')
shimmer.unwrap(redis.RedisClient.prototype, 'create_stream')
this.unwrap(redis.RedisClient.prototype, 'internal_send_command')
this.unwrap(redis, 'createClient')
this.unwrap(redis.RedisClient.prototype, 'create_stream')
}

@@ -86,0 +91,0 @@

'use strict'
const path = require('path')
const proxyquire = require('proxyquire').noCallThru()

@@ -11,6 +10,3 @@

let tracer
let requireDir
let Connection
let Pool
let plugins
let shimmer

@@ -38,3 +34,3 @@ beforeEach(() => {

versions: ['2.x'],
file: 'lib/Connection.js',
file: 'lib/connection.js',
patch: sinon.spy(),

@@ -46,3 +42,3 @@ unpatch: sinon.spy()

versions: ['2.x'],
file: 'lib/Pool.js',
file: 'lib/pool.js',
patch: sinon.spy(),

@@ -54,25 +50,16 @@ unpatch: sinon.spy()

plugins = {
other: {
name: 'other',
versions: ['1.x'],
patch: sinon.spy(),
unpatch: sinon.spy()
}
}
shimmer = sinon.spy()
shimmer.wrap = sinon.spy()
shimmer.unwrap = sinon.spy()
const mysqlDir = path.normalize(path.join(__dirname, 'node_modules', 'mysql-mock'))
const connectionPath = path.join(mysqlDir, 'lib', 'Connection.js')
const poolPath = path.join(mysqlDir, 'lib', 'Pool.js')
Connection = 'Connection'
Pool = 'Pool'
requireDir = sinon.stub()
requireDir.withArgs(path.join(__dirname, '../src/plugins')).returns(integrations)
Instrumenter = proxyquire('../src/instrumenter', {
'require-dir': requireDir,
[connectionPath]: Connection,
[poolPath]: Pool
'shimmer': shimmer,
'./plugins': {
'http': integrations.http,
'express-mock': integrations.express,
'mysql-mock': integrations.mysql
},
'./plugins/http': integrations.http,
'./plugins/express-mock': integrations.express,
'./plugins/mysql-mock': integrations.mysql
})

@@ -83,2 +70,6 @@

afterEach(() => {
delete require.cache[require.resolve('mysql-mock')]
})
describe('with integrations enabled', () => {

@@ -97,6 +88,4 @@ describe('use', () => {

it('should allow configuring a plugin by instance', () => {
const config = { foo: 'bar' }
instrumenter.use(integrations.express, config)
it('should default to an empty plugin configuration', () => {
instrumenter.use('express-mock')
instrumenter.patch()

@@ -106,46 +95,50 @@

expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', config)
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {})
})
it('should default to an empty plugin configuration', () => {
it('should reapply the require hook when called multiple times', () => {
instrumenter.use('mysql-mock')
instrumenter.use('express-mock')
instrumenter.patch()
const express = require('express-mock')
require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {})
expect(integrations.express.patch).to.have.been.called
})
it('should support a plugin instance', () => {
const express = require('express-mock')
it('should handle errors', () => {
expect(() => instrumenter.use()).not.to.throw()
})
instrumenter.use(express)
instrumenter.patch()
it('should not patch modules with the wrong API', () => {
integrations.express.patch = sinon.stub().throws(new Error())
require('express-mock')
instrumenter.use('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {})
const express = require('express-mock')
expect(integrations.express.unpatch).to.have.been.calledWith(express)
})
it('should reapply the require hook when called multiple times', () => {
it('should not patch modules with invalid files', () => {
integrations.mysql[0].file = 'invalid.js'
instrumenter.use('mysql-mock')
instrumenter.use('express-mock')
instrumenter.patch()
require('express-mock')
require('mysql-mock')
expect(integrations.express.patch).to.have.been.called
expect(integrations.mysql[0].patch).to.not.have.been.called
expect(integrations.mysql[1].patch).to.not.have.been.called
})
it('should support third party plugins', () => {
instrumenter.use(plugins.other)
instrumenter.patch()
it('should handle errors when unpatching', () => {
integrations.mysql[1].unpatch = sinon.stub().throws(new Error())
integrations.mysql[1].file = 'invalid.js'
const other = require('other')
instrumenter.use('mysql-mock')
expect(plugins.other.patch).to.have.been.calledWith(other, 'tracer', {})
})
require('mysql-mock')
it('should handle errors', () => {
expect(() => instrumenter.use()).not.to.throw()
expect(integrations.mysql[0].patch).to.not.have.been.called
expect(integrations.mysql[1].patch).to.not.have.been.called
})

@@ -182,2 +175,5 @@ })

it('should support patching multiple files', () => {
const Connection = require('mysql-mock/lib/connection')
const Pool = require('mysql-mock/lib/pool')
instrumenter.patch()

@@ -187,3 +183,4 @@

expect(mysql).to.deep.equal({ foo: 'bar' })
expect(mysql).to.deep.equal({ name: 'mysql' })
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer', {})

@@ -204,3 +201,50 @@ expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer', {})

})
it('should remove the require hooks', () => {
instrumenter.patch()
instrumenter.unpatch()
require('express-mock')
expect(integrations.express.patch).to.not.have.been.called
})
it('should handle errors', () => {
integrations.mysql[0].unpatch = sinon.stub().throws(new Error())
instrumenter.patch()
require('mysql-mock')
expect(() => instrumenter.unpatch()).to.not.throw()
expect(integrations.mysql[1].unpatch).to.have.been.called
})
})
describe('wrap', () => {
it('should wrap the method on the object', () => {
const obj = { method: () => {} }
const wrapper = () => {}
instrumenter.wrap(obj, 'method', wrapper)
expect(shimmer.wrap).to.have.been.calledWith(obj, 'method', wrapper)
})
it('should throw if the method does not exist', () => {
const obj = {}
const wrapper = () => {}
expect(() => instrumenter.wrap(obj, 'method', wrapper)).to.throw()
})
})
describe('unwrap', () => {
it('should wrap the method on the object', () => {
const obj = { method: () => {} }
instrumenter.unwrap(obj, 'method')
expect(shimmer.unwrap).to.have.been.calledWith(obj, 'method')
})
})
})

@@ -220,12 +264,2 @@

it('should support an array of plugins', () => {
instrumenter.use(integrations.mysql)
instrumenter.patch({ plugins: false })
require('mysql-mock')
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer', {})
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer', {})
})
describe('patch', () => {

@@ -232,0 +266,0 @@ it('should not patch any module', () => {

@@ -0,3 +1,6 @@

require('./lib/connection')
require('./lib/pool')
module.exports = {
foo: 'bar'
name: 'mysql'
}

@@ -9,2 +9,3 @@ 'use strict'

const express = require('express')
const path = require('path')

@@ -19,3 +20,7 @@ let agent = null

module.exports = {
load (plugin, moduleToPatch, config) {
load (plugin, pluginName, config) {
[].concat(plugin).forEach(instrumentation => {
this.wipe(instrumentation.name)
})
tracer = require('../..')

@@ -59,5 +64,3 @@ agent = express()

tracer.use(plugin, config)
require(moduleToPatch)
tracer.use(pluginName, config)
})

@@ -119,3 +122,13 @@ })

})
},
wipe (moduleName) {
const basedir = path.join(__dirname, '..', '..', 'node_modules', moduleName)
Object.keys(require.cache)
.filter(name => name.indexOf(basedir) !== -1)
.forEach(name => {
delete require.cache[name]
})
}
}

@@ -14,3 +14,2 @@ 'use strict'

beforeEach(() => {
elasticsearch = require('elasticsearch')
plugin = require('../../src/plugins/elasticsearch')

@@ -28,7 +27,9 @@ tracer = require('../..')

beforeEach(() => {
client = new elasticsearch.Client({
host: 'localhost:9200'
})
return agent.load(plugin, 'elasticsearch')
.then(() => {
elasticsearch = require('elasticsearch')
client = new elasticsearch.Client({
host: 'localhost:9200'
})
})
})

@@ -235,7 +236,9 @@

beforeEach(() => {
client = new elasticsearch.Client({
host: 'localhost:9200'
})
return agent.load(plugin, 'elasticsearch', { service: 'test' })
.then(() => {
elasticsearch = require('elasticsearch')
client = new elasticsearch.Client({
host: 'localhost:9200'
})
})
})

@@ -242,0 +245,0 @@

@@ -18,3 +18,2 @@ 'use strict'

plugin = require('../../src/plugins/express')
express = require('express')
context = require('../../src/platform').context()

@@ -31,2 +30,5 @@ })

return agent.load(plugin, 'express')
.then(() => {
express = require('express')
})
})

@@ -436,2 +438,5 @@

return agent.load(plugin, 'express', config)
.then(() => {
express = require('express')
})
})

@@ -438,0 +443,0 @@

@@ -14,43 +14,44 @@ 'use strict'

describe('graphql', () => {
beforeEach(() => {
plugin = require('../../src/plugins/graphql')
graphql = require('graphql')
context = require('../../src/platform').context()
schema = new graphql.GraphQLSchema({
query: new graphql.GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {
type: graphql.GraphQLString,
args: {
name: {
type: graphql.GraphQLString
}
},
resolve (obj, args) {
return args.name
function buildSchema () {
schema = new graphql.GraphQLSchema({
query: new graphql.GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {
type: graphql.GraphQLString,
args: {
name: {
type: graphql.GraphQLString
}
},
human: {
type: new graphql.GraphQLObjectType({
name: 'Human',
fields: {
name: {
type: graphql.GraphQLString,
resolve (obj, args) {
return obj
}
resolve (obj, args) {
return args.name
}
},
human: {
type: new graphql.GraphQLObjectType({
name: 'Human',
fields: {
name: {
type: graphql.GraphQLString,
resolve (obj, args) {
return obj
}
}
}),
resolve (obj, args) {
return Promise.resolve('test')
}
}),
resolve (obj, args) {
return Promise.resolve('test')
}
}
})
}
})
})
}
describe('graphql', () => {
beforeEach(() => {
plugin = require('../../src/plugins/graphql')
context = require('../../src/platform').context()
sort = spans => spans.sort((a, b) => a.start.toString() > b.start.toString() ? 1 : -1)

@@ -66,2 +67,6 @@ })

return agent.load(plugin, 'graphql')
.then(() => {
graphql = require('graphql')
buildSchema()
})
})

@@ -294,2 +299,22 @@

it('should handle calling low level APIs directly', done => {
const source = `query MyQuery { hello(name: "world") }`
const document = graphql.parse(source)
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(3)
expect(spans[0]).to.have.property('service', 'test-graphql')
expect(spans[0]).to.have.property('name', 'graphql.query')
expect(spans[0]).to.have.property('resource', 'query MyQuery')
expect(spans[0].meta).to.have.property('graphql.document', source)
})
.then(done)
.catch(done)
graphql.execute(schema, document)
})
it('should handle exceptions', done => {

@@ -361,2 +386,6 @@ const error = new Error('test')

return agent.load(plugin, 'graphql', { service: 'test' })
.then(() => {
graphql = require('graphql')
buildSchema()
})
})

@@ -363,0 +392,0 @@

@@ -18,4 +18,2 @@ 'use strict'

plugin = require('../../src/plugins/http')
express = require('express')
http = require('http')
context = require('../../src/platform').context({ experimental: {} })

@@ -32,2 +30,6 @@ })

return agent.load(plugin, 'http')
.then(() => {
http = require('http')
express = require('express')
})
})

@@ -246,2 +248,6 @@

return agent.load(plugin, 'http', config)
.then(() => {
http = require('http')
express = require('express')
})
})

@@ -248,0 +254,0 @@

@@ -15,34 +15,4 @@ 'use strict'

function setupMongo () {
return new Promise((resolve, reject) => {
server = new mongo.Server({
host: 'localhost',
port: 27017,
reconnect: false
})
server.on('connect', server => {
server.command('test', {
create: collection
}, {}, (err, result) => {
server.destroy()
server = null
if (err) {
reject(err)
} else {
resolve()
}
})
})
server.on('error', reject)
server.connect()
})
}
describe('mongodb-core', () => {
beforeEach(() => {
mongo = require('mongodb-core')
plugin = require('../../src/plugins/mongodb-core')

@@ -53,4 +23,2 @@ platform = require('../../src/platform')

collection = platform.id().toString()
return setupMongo()
})

@@ -67,2 +35,4 @@

.then(() => {
mongo = require('mongodb-core')
server = new mongo.Server({

@@ -335,2 +305,4 @@ host: 'localhost',

.then(() => {
mongo = require('mongodb-core')
server = new mongo.Server({

@@ -337,0 +309,0 @@ host: 'localhost',

@@ -14,3 +14,2 @@ 'use strict'

beforeEach(() => {
mysql = require('mysql')
plugin = require('../../src/plugins/mysql')

@@ -17,0 +16,0 @@ context = require('../../src/platform').context()

@@ -15,4 +15,3 @@ 'use strict'

beforeEach(() => {
pg = require('pg')
plugin = proxyquire('../src/plugins/pg', { 'pg': pg })
plugin = require('../../src/plugins/pg')
context = require('../../src/platform').context({ experimental: { asyncHooks: false } })

@@ -29,2 +28,4 @@ })

.then(() => {
pg = require('pg')
client = new pg.Client({

@@ -115,2 +116,4 @@ user: 'postgres',

.then(() => {
pg = require('pg')
client = new pg.Client({

@@ -117,0 +120,0 @@ user: 'postgres',

@@ -15,3 +15,2 @@ 'use strict'

beforeEach(() => {
redis = require('redis')
plugin = require('../../src/plugins/redis')

@@ -30,2 +29,3 @@ context = require('../../src/platform').context()

.then(() => {
redis = require('redis')
client = redis.createClient()

@@ -160,2 +160,3 @@ })

.then(() => {
redis = require('redis')
client = redis.createClient()

@@ -162,0 +163,0 @@ })

@@ -192,2 +192,6 @@ 'use strict'

global.it = function (title, fn) {
if (!fn) {
return it.apply(this, arguments)
}
if (fn.length > 0) {

@@ -194,0 +198,0 @@ return it.call(this, title, function (done) {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc