Socket
Socket
Sign inDemoInstall

dd-trace

Package Overview
Dependencies
Maintainers
3
Versions
574
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dd-trace - npm Package Compare versions

Comparing version 0.5.5 to 0.5.6

scripts/install_plugin_modules.js

2

lib/version.js

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

module.exports = '0.5.5'
module.exports = '0.5.6'
{
"name": "dd-trace",
"version": "0.5.5",
"version": "0.5.6",
"description": "Datadog APM tracing client for JavaScript",

@@ -11,4 +11,4 @@ "main": "index.js",

"lint": "eslint . && node scripts/check_licenses.js",
"tdd": "mocha --watch",
"test": "nyc --reporter text --reporter lcov mocha 'test/**/*.spec.js'",
"tdd": "node ./scripts/install_plugin_modules && mocha --watch",
"test": "node ./scripts/install_plugin_modules && nyc --reporter text --reporter lcov mocha 'test/**/*.spec.js'",
"leak": "node --no-warnings ./node_modules/.bin/tape 'test/leak/**/*.js'"

@@ -86,2 +86,3 @@ },

"redis": "^2.8.0",
"require-dir": "^1.0.0",
"retry": "^0.10.1",

@@ -88,0 +89,0 @@ "sinon": "^4.2.1",

@@ -27,6 +27,8 @@ # dd-trace-js

To get started once you have a Node version installed, run:
We use [yarn](https://yarnpkg.com/) for its workspace functionality, so make sure to install that as well.
To get started once you have Node and yarn installed, run:
```sh
$ npm install
$ yarn
```

@@ -49,3 +51,3 @@

```sh
$ npm test
$ yarn test
```

@@ -56,3 +58,3 @@

```sh
$ npm run tdd
$ yarn tdd
```

@@ -65,3 +67,3 @@

```sh
$ npm run leak
$ yarn leak
```

@@ -79,3 +81,3 @@

```sh
$ npm run lint
$ yarn lint
```

@@ -107,3 +109,3 @@

```sh
$ npm run bench
$ yarn bench
```
'use strict'
const fs = require('fs')
const exec = require('./helpers/exec')

@@ -15,13 +14,8 @@ const title = require('./helpers/title')

if (fs.existsSync('yarn.lock')) {
exec('yarn')
} else {
exec('npm install')
}
exec('yarn install')
exec('rm -rf ./out')
exec('git clone -b gh-pages --single-branch git@github.com:DataDog/dd-trace-js.git out')
exec('npm run jsdoc')
exec('yarn jsdoc')
exec('git add -A', { cwd: './out' })
exec(`git commit -m "${msg}"`, { cwd: './out' })
exec('git push', { cwd: './out' })

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

exec('npm whoami')
exec('git checkout master')

@@ -17,3 +16,3 @@ exec('git pull')

exec(`git push origin refs/tags/v${pkg.version}`)
exec('npm publish')
exec('yarn publish')
exec(`node scripts/publish_docs.js "v${pkg.version}"`)

@@ -16,3 +16,3 @@ 'use strict'

function middleware (req, res, next) {
function ddTrace (req, res, next) {
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`

@@ -53,9 +53,3 @@ const childOf = tracer.extract(FORMAT_HTTP_HEADERS, req.headers)

Object.defineProperty(req, '_datadog', {
value: {
span,
paths: [],
scope: null
}
})
req._datadog.span = span

@@ -69,3 +63,3 @@ next()

this._datadog_trace_patched = true
this.use(middleware)
this.use(ddTrace)
}

@@ -77,2 +71,16 @@ return original.apply(this, arguments)

function createWrapHandle (tracer, config) {
return function wrapHandle (handle) {
return function handleWithTracer (req) {
if (!req._datadog) {
Object.defineProperty(req, '_datadog', {
value: { paths: [] }
})
}
return handle.apply(this, arguments)
}
}
}
function createWrapProcessParams (tracer, config) {

@@ -83,2 +91,4 @@ return function wrapProcessParams (processParams) {

req = done ? req : called
if (matchers) {

@@ -108,13 +118,14 @@ // Try to guess which path actually matched

this.stack.slice(offset).forEach(layer => {
const handleRequest = layer.handle_request
const handleError = layer.handle_error
const handle = layer.handle
layer.handle_request = (req, res, next) => {
return handleRequest.call(layer, req, res, wrapNext(tracer, layer, req, next))
if (handle.length === 4) {
layer.handle = (error, req, res, next) => {
return handle.call(layer, error, req, res, wrapNext(tracer, layer, req, next))
}
} else {
layer.handle = (req, res, next) => {
return handle.call(layer, req, res, wrapNext(tracer, layer, req, next))
}
}
layer.handle_error = (error, req, res, next) => {
return handleError.call(layer, error, req, res, wrapNext(tracer, layer, req, next))
}
layer._datadog_matchers = matchers

@@ -129,3 +140,3 @@ })

function wrapNext (tracer, layer, req, next) {
if (!req._datadog) {
if (!req._datadog.span) {
return next

@@ -139,4 +150,4 @@ }

return function () {
if (layer.path && !layer.regexp.fast_star) {
return function (error) {
if (!error && layer.path && !isFastStar(layer)) {
req._datadog.paths.pop()

@@ -164,2 +175,10 @@ }

function isFastStar (layer) {
if (layer.regexp.fast_star !== undefined) {
return layer.regexp.fast_star
}
return layer._datadog_matchers.some(matcher => matcher.path === '*')
}
function flatten (arr) {

@@ -173,2 +192,3 @@ return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), [])

})
this.wrap(express.Router, 'handle', createWrapHandle(tracer, config))
this.wrap(express.Router, 'process_params', createWrapProcessParams(tracer, config))

@@ -181,2 +201,3 @@ this.wrap(express.Router, 'use', createWrapRouterMethod(tracer, config))

METHODS.forEach(method => this.unwrap(express.application, method))
this.unwrap(express.Router, 'handle')
this.unwrap(express.Router, 'process_params')

@@ -183,0 +204,0 @@ this.unwrap(express.Router, 'use')

@@ -29,10 +29,12 @@ 'use strict'

Object.defineProperties(contextValue, {
_datadog_operation: {
value: {
span: createOperationSpan(tracer, config, operation, document._datadog_source)
}
},
_datadog_fields: { value: {} }
})
if (!contextValue._datadog_operation) {
Object.defineProperties(contextValue, {
_datadog_operation: {
value: {
span: createOperationSpan(tracer, config, operation, document._datadog_source)
}
},
_datadog_fields: { value: {} }
})
}

@@ -39,0 +41,0 @@ return call(execute, this, [args], err => finishOperation(contextValue, err))

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

req.on('socket', () => {
// empty the data stream when no other listener exists to consume it
if (req.listenerCount('response') === 1) {
req.on('response', res => res.resume())
}
})
req.on('response', res => {

@@ -50,7 +57,2 @@ span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode)

res.on('end', () => span.finish())
// empty the data stream when no other listener exists to consume it
if (req.listenerCount('response') === 1) {
res.resume()
}
})

@@ -57,0 +59,0 @@

'use strict'
const Buffer = require('safe-buffer').Buffer
// TODO: remove sanitization when implemented by the agent

@@ -282,3 +284,3 @@

for (const key in input) {
if (isObject(input[key])) {
if (isObject(input[key]) && !Buffer.isBuffer(input[key])) {
output[key] = sanitize(input[key])

@@ -285,0 +287,0 @@ } else {

@@ -13,3 +13,4 @@ {

"nock": true,
"wrapIt": true
"wrapIt": true,
"withVersions": true
},

@@ -16,0 +17,0 @@ "rules": {

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

host: 'localhost',
user: 'user',
password: 'userpass',
user: 'root',
database: 'db'

@@ -18,0 +17,0 @@ })

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

host: 'localhost',
user: 'user',
password: 'userpass',
user: 'root',
database: 'db'

@@ -18,0 +17,0 @@ })

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

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

@@ -123,4 +119,4 @@ agent = express()

wipe (moduleName) {
const basedir = path.join(__dirname, '..', '..', 'node_modules', moduleName)
wipe () {
const basedir = path.join(__dirname, 'versions')

@@ -127,0 +123,0 @@ Object.keys(require.cache)

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/amqplib')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let tracer

@@ -15,195 +15,216 @@ let connection

describe('amqplib', () => {
beforeEach(() => {
plugin = require('../../src/plugins/amqplib')
tracer = require('../..')
})
withVersions(plugin, 'amqplib', version => {
beforeEach(() => {
tracer = require('../..')
})
afterEach(() => {
agent.close()
connection.close()
})
afterEach(() => {
connection.close()
agent.close()
agent.wipe()
})
describe('without configuration', () => {
describe('when using a callback', () => {
beforeEach(done => {
agent.load(plugin, 'amqplib')
.then(() => {
require('amqplib/callback_api')
.connect((err, conn) => {
connection = conn
describe('without configuration', () => {
describe('when using a callback', () => {
beforeEach(done => {
agent.load(plugin, 'amqplib')
.then(() => {
require(`./versions/amqplib@${version}`).get('amqplib/callback_api')
.connect((err, conn) => {
connection = conn
if (err != null) {
return done(err)
}
if (err != null) {
return done(err)
}
conn.createChannel((err, ch) => {
channel = ch
done(err)
conn.createChannel((err, ch) => {
channel = ch
done(err)
})
})
})
})
.catch(done)
})
})
.catch(done)
})
describe('when sending commands', () => {
it('should do automatic instrumentation for immediate commands', done => {
agent
.use(traces => {
const span = traces[0][0]
describe('when sending commands', () => {
it('should do automatic instrumentation for immediate commands', done => {
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.declare test')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
}, 2)
.then(done)
.catch(done)
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.declare test')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
}, 2)
.then(done)
.catch(done)
channel.assertQueue('test', {}, () => {})
})
channel.assertQueue('test', {}, () => {})
})
it('should do automatic instrumentation for queued commands', done => {
agent
.use(traces => {
const span = traces[0][0]
it('should do automatic instrumentation for queued commands', done => {
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.delete test')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
}, 3)
.then(done)
.catch(done)
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.delete test')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
}, 3)
.then(done)
.catch(done)
channel.assertQueue('test', {}, () => {})
channel.deleteQueue('test', () => {})
})
channel.assertQueue('test', {}, () => {})
channel.deleteQueue('test', () => {})
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent
.use(traces => {
const span = traces[0][0]
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('error', 1)
expect(span.meta).to.have.property('error.type', error.name)
expect(span.meta).to.have.property('error.msg', error.message)
expect(span.meta).to.have.property('error.stack', error.stack)
}, 2)
.then(done)
.catch(done)
expect(span).to.have.property('error', 1)
expect(span.meta).to.have.property('error.type', error.name)
expect(span.meta).to.have.property('error.msg', error.message)
expect(span.meta).to.have.property('error.stack', error.stack)
}, 2)
.then(done)
.catch(done)
try {
channel.deleteQueue(null, () => {})
} catch (e) {
error = e
}
try {
channel.deleteQueue(null, () => {})
} catch (e) {
error = e
}
})
})
})
describe('when publishing messages', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
describe('when publishing messages', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'basic.publish exchange routingKey')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
expect(span.meta).to.have.property('span.kind', 'producer')
expect(span.meta).to.have.property('amqp.routingKey', 'routingKey')
}, 3)
.then(done)
.catch(done)
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'basic.publish exchange routingKey')
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
expect(span.meta).to.have.property('span.kind', 'producer')
expect(span.meta).to.have.property('amqp.routingKey', 'routingKey')
}, 3)
.then(done)
.catch(done)
channel.assertExchange('exchange', 'direct', {}, () => {})
channel.publish('exchange', 'routingKey', Buffer.from('content'))
})
channel.assertExchange('exchange', 'direct', {}, () => {})
channel.publish('exchange', 'routingKey', Buffer.from('content'))
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent
.use(traces => {
const span = traces[0][0]
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('error', 1)
expect(span.meta).to.have.property('error.type', error.name)
expect(span.meta).to.have.property('error.msg', error.message)
expect(span.meta).to.have.property('error.stack', error.stack)
}, 2)
.then(done)
.catch(done)
expect(span).to.have.property('error', 1)
expect(span.meta).to.have.property('error.type', error.name)
expect(span.meta).to.have.property('error.msg', error.message)
expect(span.meta).to.have.property('error.stack', error.stack)
}, 2)
.then(done)
.catch(done)
try {
channel.sendToQueue('test', 'invalid')
} catch (e) {
error = e
}
try {
channel.sendToQueue('test', 'invalid')
} catch (e) {
error = e
}
})
})
})
describe('when consuming messages', () => {
it('should do automatic instrumentation', done => {
let consumerTag
let queue
describe('when consuming messages', () => {
it('should do automatic instrumentation', done => {
let consumerTag
let queue
agent
.use(traces => {
const span = traces[0][0]
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', `basic.deliver ${queue}`)
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
expect(span.meta).to.have.property('span.kind', 'consumer')
expect(span.meta).to.have.property('amqp.consumerTag', consumerTag)
}, 5)
.then(done)
.catch(done)
expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', `basic.deliver ${queue}`)
expect(span).to.have.property('type', 'worker')
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '5672')
expect(span.meta).to.have.property('span.kind', 'consumer')
expect(span.meta).to.have.property('amqp.consumerTag', consumerTag)
}, 5)
.then(done)
.catch(done)
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
queue = ok.queue
queue = ok.queue
channel.sendToQueue(ok.queue, Buffer.from('content'))
channel.consume(ok.queue, () => {}, {}, (err, ok) => {
channel.sendToQueue(ok.queue, Buffer.from('content'))
channel.consume(ok.queue, () => {}, {}, (err, ok) => {
if (err) return done(err)
consumerTag = ok.consumerTag
})
})
})
it('should run the command callback in the parent context', done => {
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
consumerTag = ok.consumerTag
channel.consume(ok.queue, () => {}, {}, () => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
})
})
it('should run the command callback in the parent context', done => {
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
it('should run the delivery callback in the current context', done => {
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
channel.consume(ok.queue, () => {}, {}, () => {
expect(tracer.scopeManager().active()).to.be.null
done()
channel.sendToQueue(ok.queue, Buffer.from('content'))
channel.consume(ok.queue, () => {
expect(tracer.scopeManager().active()).to.not.be.null
done()
}, {}, err => err && done(err))
})
})
})
})
it('should run the delivery callback in the current context', done => {
channel.assertQueue('', {}, (err, ok) => {
if (err) return done(err)
describe('when using a promise', () => {
beforeEach(() => {
return agent.load(plugin, 'amqplib')
.then(() => require(`./versions/amqplib@${version}`).get().connect())
.then(conn => (connection = conn))
.then(conn => conn.createChannel())
.then(ch => (channel = ch))
})
channel.sendToQueue(ok.queue, Buffer.from('content'))
channel.consume(ok.queue, () => {
expect(tracer.scopeManager().active()).to.not.be.null
it('should run the callback in the parent context', done => {
channel.assertQueue('test', {})
.then(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
}, {}, err => err && done(err))
})
})
.catch(done)
})

@@ -213,56 +234,37 @@ })

describe('when using a promise', () => {
beforeEach(() => {
return agent.load(plugin, 'amqplib')
.then(() => require('amqplib').connect())
.then(conn => (connection = conn))
.then(conn => conn.createChannel())
.then(ch => (channel = ch))
})
describe('with configuration', () => {
beforeEach(done => {
agent.load(plugin, 'amqplib', { service: 'test' })
.then(() => {
require(`./versions/amqplib@${version}`).get('amqplib/callback_api')
.connect((err, conn) => {
connection = conn
it('should run the callback in the parent context', done => {
channel.assertQueue('test', {})
.then(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
if (err !== null) {
return done(err)
}
conn.createChannel((err, ch) => {
channel = ch
done(err)
})
})
})
.catch(done)
})
})
})
describe('with configuration', () => {
beforeEach(done => {
agent.load(plugin, 'amqplib', { service: 'test' })
.then(() => {
require('amqplib/callback_api')
.connect((err, conn) => {
connection = conn
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('resource', 'queue.declare test')
}, 2)
.then(done)
.catch(done)
if (err !== null) {
return done(err)
}
conn.createChannel((err, ch) => {
channel = ch
done(err)
})
})
})
.catch(done)
channel.assertQueue('test', {}, () => {})
})
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('resource', 'queue.declare test')
}, 2)
.then(done)
.catch(done)
channel.assertQueue('test', {}, () => {})
})
})
})
})
'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/elasticsearch')

@@ -8,83 +9,33 @@ wrapIt()

describe('Plugin', () => {
let plugin
let elasticsearch
let tracer
describe('elasticsearch', () => {
beforeEach(() => {
plugin = require('../../src/plugins/elasticsearch')
tracer = require('../..')
})
afterEach(() => {
agent.close()
})
describe('without configuration', () => {
let client
withVersions(plugin, 'elasticsearch', version => {
describe('elasticsearch', () => {
beforeEach(() => {
return agent.load(plugin, 'elasticsearch')
.then(() => {
elasticsearch = require('elasticsearch')
client = new elasticsearch.Client({
host: 'localhost:9200'
})
})
tracer = require('../..')
})
it('should sanitize the resource name', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'POST /logstash-?.?.?/_search')
})
.then(done)
.catch(done)
client.search({ index: 'logstash-2000.01.01' }, () => {})
afterEach(() => {
agent.close()
agent.wipe()
})
it('should set the correct tags', done => {
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('db.type', 'elasticsearch')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
expect(traces[0][0].meta).to.have.property('elasticsearch.method', 'POST')
expect(traces[0][0].meta).to.have.property('elasticsearch.url', '/docs/_search')
expect(traces[0][0].meta).to.have.property('elasticsearch.body', '{"query":{"match_all":{}}}')
expect(traces[0][0].meta).to.have.property('elasticsearch.params', '{"sort":"name","size":100}')
})
.then(done)
.catch(done)
describe('without configuration', () => {
let client
client.search({
index: 'docs',
sort: 'name',
size: 100,
body: {
query: {
match_all: {}
}
}
}, () => {})
})
beforeEach(() => {
return agent.load(plugin, 'elasticsearch')
.then(() => {
elasticsearch = require(`./versions/elasticsearch@${version}`).get()
client = new elasticsearch.Client({
host: 'localhost:9200'
})
})
})
it('should skip tags for unavailable fields', done => {
agent
.use(traces => {
expect(traces[0][0].meta).to.not.have.property('elasticsearch.body')
})
.then(done)
.catch(done)
client.ping(err => err && done(err))
})
describe('when using a callback', () => {
it('should do automatic instrumentation', done => {
it('should sanitize the resource name', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-elasticsearch')
expect(traces[0][0]).to.have.property('resource', 'HEAD /')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
expect(traces[0][0]).to.have.property('resource', 'POST /logstash-?.?.?/_search')
})

@@ -94,10 +45,14 @@ .then(done)

client.ping(err => err && done(err))
client.search({ index: 'logstash-2000.01.01' }, () => {})
})
it('should propagate context', done => {
it('should set the correct tags', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('parent_id')
expect(traces[0][0].parent_id).to.not.be.null
expect(traces[0][0].meta).to.have.property('db.type', 'elasticsearch')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
expect(traces[0][0].meta).to.have.property('elasticsearch.method', 'POST')
expect(traces[0][0].meta).to.have.property('elasticsearch.url', '/docs/_search')
expect(traces[0][0].meta).to.have.property('elasticsearch.body', '{"query":{"match_all":{}}}')
expect(traces[0][0].meta).to.have.property('elasticsearch.params', '{"sort":"name","size":100}')
})

@@ -107,22 +62,18 @@ .then(done)

tracer.trace('test', span => {
client.ping(() => span.finish())
})
client.search({
index: 'docs',
sort: 'name',
size: 100,
body: {
query: {
match_all: {}
}
}
}, () => {})
})
it('should run the callback in the parent context', done => {
client.ping(error => {
expect(tracer.scopeManager().active()).to.be.null
done(error)
})
})
it('should handle errors', done => {
let error
it('should skip tags for unavailable fields', done => {
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
expect(traces[0][0].meta).to.not.have.property('elasticsearch.body')
})

@@ -132,106 +83,157 @@ .then(done)

client.search({ index: 'invalid' }, err => {
error = err
})
client.ping(err => err && done(err))
})
it('should support aborting the query', () => {
expect(() => {
client.ping(() => {}).abort()
}).not.to.throw()
})
})
describe('when using a callback', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-elasticsearch')
expect(traces[0][0]).to.have.property('resource', 'HEAD /')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
})
.then(done)
.catch(done)
describe('when using a promise', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-elasticsearch')
expect(traces[0][0]).to.have.property('resource', 'HEAD /')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
})
.then(done)
.catch(done)
client.ping(err => err && done(err))
})
client.ping().catch(done)
})
it('should propagate context', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('parent_id')
expect(traces[0][0].parent_id).to.not.be.null
})
.then(done)
.catch(done)
it('should propagate context', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('parent_id')
expect(traces[0][0].parent_id).to.not.be.null
tracer.trace('test', span => {
client.ping(() => span.finish())
})
.then(done)
.catch(done)
tracer.trace('test', span => {
client.ping()
.then(() => span.finish())
.catch(done)
})
})
it('should run resolved promises in the parent context', () => {
return client.ping()
.then(() => {
it('should run the callback in the parent context', done => {
client.ping(error => {
expect(tracer.scopeManager().active()).to.be.null
done(error)
})
})
})
it('should run rejected promises in the parent context', done => {
client.search({ index: 'invalid' })
.catch(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
it('should handle errors', done => {
let error
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
client.search({ index: 'invalid' }, err => {
error = err
})
})
it('should support aborting the query', () => {
expect(() => {
client.ping(() => {}).abort()
}).not.to.throw()
})
})
it('should handle errors', done => {
let error
describe('when using a promise', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-elasticsearch')
expect(traces[0][0]).to.have.property('resource', 'HEAD /')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
})
.then(done)
.catch(done)
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
client.ping().catch(done)
})
.then(done)
.catch(done)
client.search({ index: 'invalid' })
.catch(err => {
error = err
it('should propagate context', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('parent_id')
expect(traces[0][0].parent_id).to.not.be.null
})
.then(done)
.catch(done)
tracer.trace('test', span => {
client.ping()
.then(() => span.finish())
.catch(done)
})
})
})
it('should support aborting the query', () => {
expect(() => {
client.ping().abort()
}).not.to.throw()
})
})
})
it('should run resolved promises in the parent context', () => {
return client.ping()
.then(() => {
expect(tracer.scopeManager().active()).to.be.null
})
})
describe('with configuration', () => {
let client
it('should run rejected promises in the parent context', done => {
client.search({ index: 'invalid' })
.catch(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
beforeEach(() => {
return agent.load(plugin, 'elasticsearch', { service: 'test' })
.then(() => {
elasticsearch = require('elasticsearch')
client = new elasticsearch.Client({
host: 'localhost:9200'
it('should handle errors', done => {
let error
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
client.search({ index: 'invalid' })
.catch(err => {
error = err
})
})
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
it('should support aborting the query', () => {
expect(() => {
client.ping().abort()
}).not.to.throw()
})
.then(done)
.catch(done)
})
})
client.ping(err => err && done(err))
describe('with configuration', () => {
let client
beforeEach(() => {
return agent.load(plugin, 'elasticsearch', { service: 'test' })
.then(() => {
elasticsearch = require(`./versions/elasticsearch@${version}`).get()
client = new elasticsearch.Client({
host: 'localhost:9200'
})
})
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
})
.then(done)
.catch(done)
client.ping(err => err && done(err))
})
})

@@ -238,0 +240,0 @@ })

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

const agent = require('./agent')
const plugin = require('../../src/plugins/express')

@@ -11,3 +12,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let tracer

@@ -18,534 +18,589 @@ let express

describe('express', () => {
beforeEach(() => {
plugin = require('../../src/plugins/express')
tracer = require('../..')
})
afterEach(() => {
agent.close()
appListener.close()
})
describe('without configuration', () => {
withVersions(plugin, 'express', version => {
beforeEach(() => {
return agent.load(plugin, 'express')
.then(() => {
express = require('express')
})
tracer = require('../..')
})
it('should do automatic instrumentation on app routes', done => {
const app = express()
afterEach(() => {
agent.close()
appListener.close()
})
app.get('/user', (req, res) => {
res.status(200).send()
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'express')
.then(() => {
express = require(`./versions/express@${version}`).get()
})
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /user')
expect(traces[0][0].meta).to.have.property('span.kind', 'server')
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/user`)
expect(traces[0][0].meta).to.have.property('http.method', 'GET')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
})
.then(done)
.catch(done)
it('should do automatic instrumentation on app routes', done => {
const app = express()
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
app.get('/user', (req, res) => {
res.status(200).send()
})
})
})
it('should do automatic instrumentation on routers', done => {
const app = express()
const router = express.Router()
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /user')
expect(traces[0][0].meta).to.have.property('span.kind', 'server')
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/user`)
expect(traces[0][0].meta).to.have.property('http.method', 'GET')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
})
.then(done)
.catch(done)
router.get('/user/:id', (req, res) => {
res.status(200).send()
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
})
})
})
app.use('/app', router)
it('should do automatic instrumentation on routers', done => {
const app = express()
const router = express.Router()
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
expect(traces[0][0].meta).to.have.property('span.kind', 'server')
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/app/user/1`)
expect(traces[0][0].meta).to.have.property('http.method', 'GET')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
})
})
it('should surround matchers based on regular expressions', done => {
const app = express()
const router = express.Router()
app.use('/app', router)
router.get(/^\/user\/(\d)$/, (req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
expect(traces[0][0].meta).to.have.property('span.kind', 'server')
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/app/user/1`)
expect(traces[0][0].meta).to.have.property('http.method', 'GET')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
})
.then(done)
.catch(done)
app.use('/app', router)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app(/^\\/user\\/(\\d)$/)')
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
})
})
it('should support a nested array of paths on the router', done => {
const app = express()
const router = express.Router()
it('should surround matchers based on regular expressions', done => {
const app = express()
const router = express.Router()
router.get([['/user/:id'], '/users/:id'], (req, res, next) => {
res.status(200).send()
})
router.get(/^\/user\/(\d)$/, (req, res) => {
res.status(200).send()
})
app.use('/app', router)
app.use('/app', router)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app(/^\\/user\\/(\\d)$/)')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
})
})
it('should only keep the last matching path of a middleware stack', done => {
const app = express()
const router = express.Router()
it('should support a nested array of paths on the router', done => {
const app = express()
const router = express.Router()
router.use('/', (req, res, next) => next())
router.use('*', (req, res, next) => next())
router.use('/bar', (req, res, next) => next())
router.use('/bar', (req, res, next) => {
res.status(200).send()
})
router.get([['/user/:id'], '/users/:id'], (req, res, next) => {
res.status(200).send()
})
app.use('/', (req, res, next) => next())
app.use('*', (req, res, next) => next())
app.use('/foo/bar', (req, res, next) => next())
app.use('/foo', router)
app.use('/app', router)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /foo/bar')
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/foo/bar`)
.catch(done)
})
})
})
it('should support asynchronous routers', done => {
const app = express()
const router = express.Router()
it('should only keep the last matching path of a middleware stack', done => {
const app = express()
const router = express.Router()
router.get('/user/:id', (req, res) => {
setTimeout(() => res.status(200).send())
})
router.use('/', (req, res, next) => next())
router.use('*', (req, res, next) => next())
router.use('/bar', (req, res, next) => next())
router.use('/bar', (req, res, next) => {
res.status(200).send()
})
app.use('/app', router)
app.use('/', (req, res, next) => next())
app.use('*', (req, res, next) => next())
app.use('/foo/bar', (req, res, next) => next())
app.use('/foo', router)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /foo/bar')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/foo/bar`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
})
})
it('should support asynchronous middlewares', done => {
const app = express()
const router = express.Router()
it('should support asynchronous routers', done => {
const app = express()
const router = express.Router()
router.use((req, res, next) => setTimeout(() => next()))
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
router.get('/user/:id', (req, res) => {
setTimeout(() => res.status(200).send())
})
app.use('/app', router)
app.use('/app', router)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
})
})
it('should not lose the current path when changing scope', done => {
const app = express()
const router = express.Router()
it('should support asynchronous middlewares', done => {
const app = express()
const router = express.Router()
router.use((req, res, next) => {
const scope = tracer.scopeManager().active()
const child = tracer.startSpan('child', {
childOf: scope.span()
router.use((req, res, next) => setTimeout(() => next()))
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
tracer.scopeManager().activate(child)
app.use('/app', router)
child.finish()
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
next()
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/1`)
.catch(done)
})
})
})
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
it('should support nested applications', done => {
const app = express()
const childApp = express()
app.use('/app', router)
childApp.use('/child', (req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][1]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
app.use('/parent', childApp)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/123`)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0]).to.have.length(1)
expect(traces[0][0]).to.have.property('resource', 'GET /parent/child')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/parent/child`)
.catch(done)
})
})
})
})
it('should not lose the current path without a scope', done => {
const app = express()
const router = express.Router()
it('should not lose the current path when changing scope', done => {
const app = express()
const router = express.Router()
router.use((req, res, next) => {
const scope = tracer.scopeManager().active()
router.use((req, res, next) => {
const scope = tracer.scopeManager().active()
const child = tracer.startSpan('child', {
childOf: scope.span()
})
scope.close()
tracer.scopeManager().activate(child)
next()
})
child.finish()
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
next()
})
app.use('/app', router)
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
app.use('/app', router)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/123`)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][1]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/123`)
.catch(done)
})
})
})
})
it('should not leak the current scope to other requests when using a task queue', done => {
const app = express()
it('should not lose the current path without a scope', done => {
const app = express()
const router = express.Router()
let handler
router.use((req, res, next) => {
const scope = tracer.scopeManager().active()
const interval = setInterval(() => {
if (handler) {
handler()
scope.close()
clearInterval(interval)
next()
})
expect(tracer.scopeManager().active()).to.be.null
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
done()
}
})
app.use('/app', router)
app.use((req, res, next) => {
handler = next
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
app.get('/app', (req, res) => {
res.status(200).send()
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app/user/123`)
.catch(done)
})
})
})
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app`)
.catch(done)
it('should not lose the current path on error', done => {
const app = express()
app.get('/app', (req, res, next) => {
next(new Error())
})
})
})
it('should fallback to the the verb if a path pattern could not be found', done => {
const app = express()
app.use((error, req, res, next) => {
res.status(200).send(error.message)
})
app.use((req, res, next) => res.status(200).send())
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app')
})
.then(done)
.catch(done)
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET')
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app`)
.catch(done)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app`)
.catch(done)
})
})
})
it('should reactivate the span when the active scope is closed', done => {
const app = express()
it('should not leak the current scope to other requests when using a task queue', done => {
const app = express()
let span
let scope
let handler
app.use((req, res, next) => {
scope = tracer.scopeManager().active()
span = scope.span()
scope.close()
next()
})
const interval = setInterval(() => {
if (handler) {
handler()
app.get('/user', (req, res) => {
const scope = tracer.scopeManager().active()
clearInterval(interval)
res.status(200).send()
expect(tracer.scopeManager().active()).to.be.null
try {
expect(scope).to.not.be.null
expect(scope.span()).to.equal(span)
done()
} catch (e) {
done(e)
}
})
done()
}
})
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/user`)
.catch(done)
app.use((req, res, next) => {
handler = next
})
})
})
it('should only include paths for routes that matched', done => {
const app = express()
const router = express.Router()
app.get('/app', (req, res) => {
res.status(200).send()
})
router.use('/baz', (req, res, next) => next())
router.get('/user/:id', (req, res) => {
res.status(200).send()
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app`)
.catch(done)
})
})
})
router.use('/qux', (req, res, next) => next())
app.use('/foo', (req, res, next) => next())
app.use('/app', router)
app.use('/bar', (req, res, next) => next())
it('should fallback to the the verb if a path pattern could not be found', done => {
const app = express()
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
app.use((req, res, next) => res.status(200).send())
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/app/user/123`)
.then(res => {
expect(res.status).to.equal(200)
expect(res.data).to.be.empty
done()
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/app`)
.catch(done)
})
})
})
})
it('should extract its parent span from the headers', done => {
const app = express()
it('should reactivate the span when the active scope is closed', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send()
let span
let scope
app.use((req, res, next) => {
scope = tracer.scopeManager().active()
span = scope.span()
scope.close()
next()
})
app.get('/user', (req, res) => {
const scope = tracer.scopeManager().active()
res.status(200).send()
try {
expect(scope).to.not.be.null
expect(scope.span()).to.equal(span)
done()
} catch (e) {
done(e)
}
})
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/user`)
.catch(done)
})
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].trace_id.toString()).to.equal('1234')
expect(traces[0][0].parent_id.toString()).to.equal('5678')
it('should only include paths for routes that matched', done => {
const app = express()
const router = express.Router()
router.use('/baz', (req, res, next) => next())
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
.then(done)
.catch(done)
router.use('/qux', (req, res, next) => next())
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
headers: {
'x-datadog-trace-id': '1234',
'x-datadog-parent-id': '5678',
'ot-baggage-foo': 'bar'
}
app.use('/foo', (req, res, next) => next())
app.use('/app', router)
app.use('/bar', (req, res, next) => next())
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/app/user/123`)
.then(res => {
expect(res.status).to.equal(200)
expect(res.data).to.be.empty
done()
})
.catch(done)
})
})
})
})
it('should handle errors', done => {
const app = express()
it('should extract its parent span from the headers', done => {
const app = express()
app.use((req, res, next) => {
next()
})
app.get('/user', (req, res) => {
res.status(200).send()
})
app.get('/user', (req, res) => {
res.status(500).send()
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].trace_id.toString()).to.equal('1234')
expect(traces[0][0].parent_id.toString()).to.equal('5678')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
headers: {
'x-datadog-trace-id': '1234',
'x-datadog-parent-id': '5678',
'ot-baggage-foo': 'bar'
}
})
.catch(done)
})
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('error', 1)
expect(traces[0][0]).to.have.property('resource', 'GET /user')
expect(traces[0][0].meta).to.have.property('http.status_code', '500')
it('should handle errors', done => {
const app = express()
done()
app.use((req, res, next) => {
next()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
validateStatus: status => status === 500
})
.catch(done)
app.get('/user', (req, res) => {
res.status(500).send()
})
})
})
})
describe('with configuration', () => {
let config
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('error', 1)
expect(traces[0][0]).to.have.property('resource', 'GET /user')
expect(traces[0][0].meta).to.have.property('http.status_code', '500')
beforeEach(() => {
config = {
service: 'custom',
validateStatus: code => code < 400
}
done()
})
return agent.load(plugin, 'express', config)
.then(() => {
express = require('express')
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
validateStatus: status => status === 500
})
.catch(done)
})
})
})
})
it('should be configured with the correct service name', done => {
const app = express()
describe('with configuration', () => {
let config
app.get('/user', (req, res) => {
res.status(200).send()
})
beforeEach(() => {
config = {
service: 'custom',
validateStatus: code => code < 400
}
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
return agent.load(plugin, 'express', config)
.then(() => {
express = require(`./versions/express@${version}`).get()
})
.then(done)
.catch(done)
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
it('should be configured with the correct service name', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
})
})
})
})
it('should be configured with the correct status code validator', done => {
const app = express()
it('should be configured with the correct status code validator', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(400).send()
})
app.get('/user', (req, res) => {
res.status(400).send()
})
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('error', 1)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
validateStatus: status => status === 400
getPort().then(port => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('error', 1)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`, {
validateStatus: status => status === 400
})
.catch(done)
})
})

@@ -552,0 +607,0 @@ })

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/graphql')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let tracer

@@ -139,297 +139,283 @@ let graphql

describe('graphql', () => {
beforeEach(() => {
plugin = require('../../src/plugins/graphql')
tracer = require('../..')
withVersions(plugin, 'graphql', version => {
beforeEach(() => {
tracer = require('../..')
sort = spans => spans.sort((a, b) => a.start.toString() > b.start.toString() ? 1 : -1)
})
sort = spans => spans.sort((a, b) => a.start.toString() > b.start.toString() ? 1 : -1)
})
afterEach(() => {
agent.close()
})
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'graphql')
.then(() => {
graphql = require('graphql')
buildSchema()
})
afterEach(() => {
agent.close()
agent.wipe()
})
it('should instrument operations', done => {
const source = `query MyQuery { hello(name: "world") }`
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'graphql')
.then(() => {
graphql = require(`./versions/graphql@${version}`).get()
buildSchema()
})
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should instrument operations', done => {
const source = `query MyQuery { hello(name: "world") }`
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)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql(schema, source).catch(done)
})
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)
it('should instrument fields', done => {
const source = `{ hello(name: "world") }`
graphql.graphql(schema, source).catch(done)
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should instrument fields', done => {
const source = `{ hello(name: "world") }`
expect(spans).to.have.length(3)
expect(spans[1]).to.have.property('service', 'test-graphql')
expect(spans[1]).to.have.property('name', 'graphql.field')
expect(spans[1]).to.have.property('resource', 'hello')
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql(schema, source).catch(done)
})
expect(spans).to.have.length(3)
expect(spans[1]).to.have.property('service', 'test-graphql')
expect(spans[1]).to.have.property('name', 'graphql.field')
expect(spans[1]).to.have.property('resource', 'hello')
})
.then(done)
.catch(done)
it('should instrument schema resolvers', done => {
const source = `{ hello(name: "world") }`
graphql.graphql(schema, source).catch(done)
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should instrument schema resolvers', done => {
const source = `{ hello(name: "world") }`
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('service', 'test-graphql')
expect(spans[2]).to.have.property('name', 'graphql.resolve')
expect(spans[2]).to.have.property('resource', 'hello')
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql(schema, source).catch(done)
})
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('service', 'test-graphql')
expect(spans[2]).to.have.property('name', 'graphql.resolve')
expect(spans[2]).to.have.property('resource', 'hello')
})
.then(done)
.catch(done)
it('should instrument nested field resolvers', done => {
const source = `
{
human {
name
address {
civicNumber
street
graphql.graphql(schema, source).catch(done)
})
it('should instrument nested field resolvers', done => {
const source = `
{
human {
name
address {
civicNumber
street
}
}
}
}
`
`
agent
.use(traces => {
const spans = sort(traces[0])
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(11)
expect(spans).to.have.length(11)
const query = spans[0]
const humanField = spans[1]
const humanResolve = spans[2]
const humanNameField = spans[3]
const humanNameResolve = spans[4]
const addressField = spans[5]
const addressResolve = spans[6]
const addressCivicNumberField = spans[7]
const addressCivicNumberResolve = spans[8]
const addressStreetField = spans[9]
const addressStreetResolve = spans[10]
const query = spans[0]
const humanField = spans[1]
const humanResolve = spans[2]
const humanNameField = spans[3]
const humanNameResolve = spans[4]
const addressField = spans[5]
const addressResolve = spans[6]
const addressCivicNumberField = spans[7]
const addressCivicNumberResolve = spans[8]
const addressStreetField = spans[9]
const addressStreetResolve = spans[10]
expect(query).to.have.property('name', 'graphql.query')
expect(query).to.have.property('resource', 'query')
expect(query).to.have.property('name', 'graphql.query')
expect(query).to.have.property('resource', 'query')
expect(humanField).to.have.property('name', 'graphql.field')
expect(humanField).to.have.property('resource', 'human')
expect(humanField.parent_id.toString()).to.equal(query.span_id.toString())
expect(humanField.duration.toNumber()).to.be.lte(query.duration.toNumber())
expect(humanField).to.have.property('name', 'graphql.field')
expect(humanField).to.have.property('resource', 'human')
expect(humanField.parent_id.toString()).to.equal(query.span_id.toString())
expect(humanField.duration.toNumber()).to.be.lte(query.duration.toNumber())
expect(humanResolve).to.have.property('name', 'graphql.resolve')
expect(humanResolve).to.have.property('resource', 'human')
expect(humanResolve.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(humanResolve.duration.toNumber()).to.be.lte(humanField.duration.toNumber())
expect(humanResolve).to.have.property('name', 'graphql.resolve')
expect(humanResolve).to.have.property('resource', 'human')
expect(humanResolve.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(humanResolve.duration.toNumber()).to.be.lte(humanField.duration.toNumber())
expect(humanNameField).to.have.property('name', 'graphql.field')
expect(humanNameField).to.have.property('resource', 'human.name')
expect(humanNameField.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(humanNameField).to.have.property('name', 'graphql.field')
expect(humanNameField).to.have.property('resource', 'human.name')
expect(humanNameField.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(humanNameResolve).to.have.property('name', 'graphql.resolve')
expect(humanNameResolve).to.have.property('resource', 'human.name')
expect(humanNameResolve.parent_id.toString()).to.equal(humanNameField.span_id.toString())
expect(humanNameResolve).to.have.property('name', 'graphql.resolve')
expect(humanNameResolve).to.have.property('resource', 'human.name')
expect(humanNameResolve.parent_id.toString()).to.equal(humanNameField.span_id.toString())
expect(addressField).to.have.property('name', 'graphql.field')
expect(addressField).to.have.property('resource', 'human.address')
expect(addressField.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(addressField.duration.toNumber()).to.be.lte(humanField.duration.toNumber())
expect(addressField).to.have.property('name', 'graphql.field')
expect(addressField).to.have.property('resource', 'human.address')
expect(addressField.parent_id.toString()).to.equal(humanField.span_id.toString())
expect(addressField.duration.toNumber()).to.be.lte(humanField.duration.toNumber())
expect(addressResolve).to.have.property('name', 'graphql.resolve')
expect(addressResolve).to.have.property('resource', 'human.address')
expect(addressResolve.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressResolve.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressResolve).to.have.property('name', 'graphql.resolve')
expect(addressResolve).to.have.property('resource', 'human.address')
expect(addressResolve.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressResolve.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressCivicNumberField).to.have.property('name', 'graphql.field')
expect(addressCivicNumberField).to.have.property('resource', 'human.address.civicNumber')
expect(addressCivicNumberField.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressCivicNumberField.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressCivicNumberField).to.have.property('name', 'graphql.field')
expect(addressCivicNumberField).to.have.property('resource', 'human.address.civicNumber')
expect(addressCivicNumberField.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressCivicNumberField.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressCivicNumberResolve).to.have.property('name', 'graphql.resolve')
expect(addressCivicNumberResolve).to.have.property('resource', 'human.address.civicNumber')
expect(addressCivicNumberResolve.parent_id.toString()).to.equal(addressCivicNumberField.span_id.toString())
expect(addressCivicNumberResolve.duration.toNumber()).to.be.lte(addressCivicNumberField.duration.toNumber())
expect(addressCivicNumberResolve).to.have.property('name', 'graphql.resolve')
expect(addressCivicNumberResolve).to.have.property('resource', 'human.address.civicNumber')
expect(addressCivicNumberResolve.parent_id.toString())
.to.equal(addressCivicNumberField.span_id.toString())
expect(addressCivicNumberResolve.duration.toNumber())
.to.be.lte(addressCivicNumberField.duration.toNumber())
expect(addressStreetField).to.have.property('name', 'graphql.field')
expect(addressStreetField).to.have.property('resource', 'human.address.street')
expect(addressStreetField.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressStreetField.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressStreetField).to.have.property('name', 'graphql.field')
expect(addressStreetField).to.have.property('resource', 'human.address.street')
expect(addressStreetField.parent_id.toString()).to.equal(addressField.span_id.toString())
expect(addressStreetField.duration.toNumber()).to.be.lte(addressField.duration.toNumber())
expect(addressStreetResolve).to.have.property('name', 'graphql.resolve')
expect(addressStreetResolve).to.have.property('resource', 'human.address.street')
expect(addressStreetResolve.parent_id.toString()).to.equal(addressStreetField.span_id.toString())
expect(addressStreetResolve.duration.toNumber()).to.be.lte(addressStreetField.duration.toNumber())
})
.then(done)
.catch(done)
expect(addressStreetResolve).to.have.property('name', 'graphql.resolve')
expect(addressStreetResolve).to.have.property('resource', 'human.address.street')
expect(addressStreetResolve.parent_id.toString()).to.equal(addressStreetField.span_id.toString())
expect(addressStreetResolve.duration.toNumber()).to.be.lte(addressStreetField.duration.toNumber())
})
.then(done)
.catch(done)
graphql.graphql(schema, source).catch(done)
})
graphql.graphql(schema, source).catch(done)
})
it('should instrument list field resolvers', done => {
const source = `{ friends { name } }`
it('should instrument list field resolvers', done => {
const source = `{ friends { name } }`
agent
.use(traces => {
const spans = sort(traces[0])
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(7)
expect(spans).to.have.length(7)
const query = spans[0]
const friendsField = spans[1]
const friendsResolve = spans[2]
const friend0NameField = spans[3]
const friend0NameResolve = spans[4]
const friend1NameField = spans[5]
const friend1NameResolve = spans[6]
const query = spans[0]
const friendsField = spans[1]
const friendsResolve = spans[2]
const friend0NameField = spans[3]
const friend0NameResolve = spans[4]
const friend1NameField = spans[5]
const friend1NameResolve = spans[6]
expect(query).to.have.property('name', 'graphql.query')
expect(query).to.have.property('resource', 'query')
expect(query).to.have.property('name', 'graphql.query')
expect(query).to.have.property('resource', 'query')
expect(friendsField).to.have.property('name', 'graphql.field')
expect(friendsField).to.have.property('resource', 'friends')
expect(friendsField.parent_id.toString()).to.equal(query.span_id.toString())
expect(friendsField).to.have.property('name', 'graphql.field')
expect(friendsField).to.have.property('resource', 'friends')
expect(friendsField.parent_id.toString()).to.equal(query.span_id.toString())
expect(friendsResolve).to.have.property('name', 'graphql.resolve')
expect(friendsResolve).to.have.property('resource', 'friends')
expect(friendsResolve.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friendsResolve).to.have.property('name', 'graphql.resolve')
expect(friendsResolve).to.have.property('resource', 'friends')
expect(friendsResolve.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friend0NameField).to.have.property('name', 'graphql.field')
expect(friend0NameField).to.have.property('resource', 'friends.0.name')
expect(friend0NameField.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friend0NameField).to.have.property('name', 'graphql.field')
expect(friend0NameField).to.have.property('resource', 'friends.0.name')
expect(friend0NameField.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friend0NameResolve).to.have.property('name', 'graphql.resolve')
expect(friend0NameResolve).to.have.property('resource', 'friends.0.name')
expect(friend0NameResolve.parent_id.toString()).to.equal(friend0NameField.span_id.toString())
expect(friend0NameResolve).to.have.property('name', 'graphql.resolve')
expect(friend0NameResolve).to.have.property('resource', 'friends.0.name')
expect(friend0NameResolve.parent_id.toString()).to.equal(friend0NameField.span_id.toString())
expect(friend1NameField).to.have.property('name', 'graphql.field')
expect(friend1NameField).to.have.property('resource', 'friends.1.name')
expect(friend1NameField.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friend1NameField).to.have.property('name', 'graphql.field')
expect(friend1NameField).to.have.property('resource', 'friends.1.name')
expect(friend1NameField.parent_id.toString()).to.equal(friendsField.span_id.toString())
expect(friend1NameResolve).to.have.property('name', 'graphql.resolve')
expect(friend1NameResolve).to.have.property('resource', 'friends.1.name')
expect(friend1NameResolve.parent_id.toString()).to.equal(friend1NameField.span_id.toString())
})
.then(done)
.catch(done)
expect(friend1NameResolve).to.have.property('name', 'graphql.resolve')
expect(friend1NameResolve).to.have.property('resource', 'friends.1.name')
expect(friend1NameResolve.parent_id.toString()).to.equal(friend1NameField.span_id.toString())
})
.then(done)
.catch(done)
graphql.graphql(schema, source).catch(done)
})
graphql.graphql(schema, source).catch(done)
})
it('should instrument mutations', done => {
const source = `mutation { human { name } }`
it('should instrument mutations', done => {
const source = `mutation { human { name } }`
agent
.use(traces => {
const spans = sort(traces[0])
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(5)
expect(spans[0]).to.have.property('name', 'graphql.mutation')
})
.then(done)
.catch(done)
expect(spans).to.have.length(5)
expect(spans[0]).to.have.property('name', 'graphql.mutation')
})
.then(done)
.catch(done)
graphql.graphql(schema, source).catch(done)
})
graphql.graphql(schema, source).catch(done)
})
it('should handle a circular schema', done => {
const source = `{ human { pets { owner { name } } } }`
it('should handle a circular schema', done => {
const source = `{ human { pets { owner { name } } } }`
graphql.graphql(schema, source)
.then((result) => {
expect(result.data.human.pets[0].owner.name).to.equal('test')
graphql.graphql(schema, source)
.then((result) => {
expect(result.data.human.pets[0].owner.name).to.equal('test')
done()
})
.catch(done)
})
done()
})
.catch(done)
})
it('should ignore the default field resolver', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
it('should ignore the default field resolver', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
const source = `{ hello }`
const source = `{ hello }`
agent
.use(traces => {
const spans = sort(traces[0])
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(1)
expect(spans[0]).to.have.property('resource', 'query')
})
.then(done)
.catch(done)
expect(spans).to.have.length(1)
expect(spans[0]).to.have.property('resource', 'query')
})
.then(done)
.catch(done)
graphql.graphql(schema, source, { hello: 'world' }).catch(done)
})
graphql.graphql(schema, source, { hello: 'world' }).catch(done)
})
it('should ignore the execution field resolver without a rootValue resolver', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
it('should ignore the execution field resolver without a rootValue resolver', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
const source = `{ hello }`
const source = `{ hello }`
const rootValue = { hello: 'world' }
const rootValue = { hello: 'world' }
const fieldResolver = (source, args, contextValue, info) => {
return source[info.fieldName]
}
const fieldResolver = (source, args, contextValue, info) => {
return source[info.fieldName]
}
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(1)
expect(spans[0]).to.have.property('resource', 'query')
})
.then(done)
.catch(done)
graphql.graphql({ schema, source, rootValue, fieldResolver }).catch(done)
})
it('should not instrument schema resolvers multiple times', done => {
const source = `{ hello(name: "world") }`
agent.use(() => { // skip first call
agent

@@ -439,3 +425,4 @@ .use(traces => {

expect(spans).to.have.length(3)
expect(spans).to.have.length(1)
expect(spans[0]).to.have.property('resource', 'query')
})

@@ -445,232 +432,270 @@ .then(done)

graphql.graphql({ schema, source, rootValue, fieldResolver }).catch(done)
})
it('should not instrument schema resolvers multiple times', done => {
const source = `{ hello(name: "world") }`
agent.use(() => { // skip first call
agent
.use(traces => {
const spans = sort(traces[0])
expect(spans).to.have.length(3)
})
.then(done)
.catch(done)
graphql.graphql(schema, source).catch(done)
})
graphql.graphql(schema, source).catch(done)
})
graphql.graphql(schema, source).catch(done)
})
it('should run rootValue resolvers in the current context', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
it('should run rootValue resolvers in the current context', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
const source = `{ hello }`
const rootValue = {
hello () {
expect(tracer.scopeManager().active()).to.not.be.null
done()
}
}
`)
const source = `{ hello }`
graphql.graphql({ schema, source, rootValue }).catch(done)
})
const rootValue = {
hello () {
expect(tracer.scopeManager().active()).to.not.be.null
done()
}
}
it('should run returned promise in the parent context', () => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
graphql.graphql({ schema, source, rootValue }).catch(done)
})
const source = `{ hello }`
it('should run returned promise in the parent context', () => {
const schema = graphql.buildSchema(`
type Query {
hello: String
const rootValue = {
hello () {
return Promise.resolve('test')
}
}
`)
const source = `{ hello }`
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
const rootValue = {
hello () {
return Promise.resolve('test')
}
}
return graphql.graphql({ schema, source, rootValue })
.then(value => {
expect(value).to.have.nested.property('data.hello', 'test')
expect(tracer.scopeManager().active()).to.equal(scope)
})
})
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
it('should handle unsupported operations', () => {
const query = `query MyQuery { hello(name: "world") }`
const subscription = `subscription { human { name } }`
return graphql.graphql({ schema, source, rootValue })
.then(value => {
expect(value).to.have.nested.property('data.hello', 'test')
expect(tracer.scopeManager().active()).to.equal(scope)
})
})
return graphql.graphql(schema, query)
.then(() => graphql.graphql(schema, subscription))
.then(result => {
expect(result).to.not.have.property('errors')
})
})
it('should handle unsupported operations', () => {
const query = `query MyQuery { hello(name: "world") }`
const subscription = `subscription { human { name } }`
it('should handle calling low level APIs directly', done => {
const source = `query MyQuery { hello(name: "world") }`
const document = graphql.parse(source)
return graphql.graphql(schema, query)
.then(() => graphql.graphql(schema, subscription))
.then(result => {
expect(result).to.not.have.property('errors')
})
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should handle calling low level APIs directly', done => {
const source = `query MyQuery { hello(name: "world") }`
const document = graphql.parse(source)
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)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.execute({ schema, document })
})
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)
it('should handle Source objects', done => {
const source = `query MyQuery { hello(name: "world") }`
const document = graphql.parse(new graphql.Source(source))
graphql.execute({ schema, document })
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should handle Source objects', done => {
const source = `query MyQuery { hello(name: "world") }`
const document = graphql.parse(new graphql.Source(source))
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)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.execute(schema, document)
})
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)
it('should handle executor exceptions', done => {
schema = new graphql.GraphQLSchema({
query: new graphql.GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {}
}
})
})
.then(done)
.catch(done)
graphql.execute(schema, document)
})
const source = `{ hello }`
const document = graphql.parse(source)
it('should handle executor exceptions', done => {
schema = new graphql.GraphQLSchema({
query: new graphql.GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {}
}
})
})
let error
const source = `{ hello }`
const document = graphql.parse(source)
agent
.use(traces => {
const spans = sort(traces[0])
let error
expect(spans).to.have.length(1)
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')
expect(spans[0].meta).to.have.property('graphql.document', source)
expect(spans[0]).to.have.property('error', 1)
expect(spans[0].meta).to.have.property('error.type', error.name)
expect(spans[0].meta).to.have.property('error.msg', error.message)
expect(spans[0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
try {
graphql.execute(schema, document)
} catch (e) {
error = e
}
})
expect(spans).to.have.length(1)
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')
expect(spans[0].meta).to.have.property('graphql.document', source)
expect(spans[0]).to.have.property('error', 1)
expect(spans[0].meta).to.have.property('error.type', error.name)
expect(spans[0].meta).to.have.property('error.msg', error.message)
expect(spans[0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
it('should handle resolver exceptions', done => {
const error = new Error('test')
try {
graphql.execute(schema, document)
} catch (e) {
error = e
}
})
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
it('should handle resolver exceptions', done => {
const error = new Error('test')
const source = `{ hello }`
const schema = graphql.buildSchema(`
type Query {
hello: String
const rootValue = {
hello: () => {
throw error
}
}
`)
const source = `{ hello }`
agent
.use(traces => {
const spans = sort(traces[0])
const rootValue = {
hello: () => {
throw error
}
}
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('error', 1)
expect(spans[2].meta).to.have.property('error.type', error.name)
expect(spans[2].meta).to.have.property('error.msg', error.message)
expect(spans[2].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql({ schema, source, rootValue }).catch(done)
})
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('error', 1)
expect(spans[2].meta).to.have.property('error.type', error.name)
expect(spans[2].meta).to.have.property('error.msg', error.message)
expect(spans[2].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
it('should handle rejected promises', done => {
const error = new Error('test')
graphql.graphql({ schema, source, rootValue }).catch(done)
})
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
it('should handle rejected promises', done => {
const error = new Error('test')
const source = `{ hello }`
const schema = graphql.buildSchema(`
type Query {
hello: String
const rootValue = {
hello: () => {
return Promise.reject(error)
}
}
`)
const source = `{ hello }`
agent
.use(traces => {
const spans = sort(traces[0])
const rootValue = {
hello: () => {
return Promise.reject(error)
}
}
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('error', 1)
expect(spans[2].meta).to.have.property('error.type', error.name)
expect(spans[2].meta).to.have.property('error.msg', error.message)
expect(spans[2].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql({ schema, source, rootValue }).catch(done)
})
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('error', 1)
expect(spans[2].meta).to.have.property('error.type', error.name)
expect(spans[2].meta).to.have.property('error.msg', error.message)
expect(spans[2].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
it('should support multiple executions with the same contextValue', done => {
const schema = graphql.buildSchema(`
type Query {
hello: String
}
`)
graphql.graphql({ schema, source, rootValue }).catch(done)
})
})
const source = `{ hello }`
describe('with configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'graphql', { service: 'test' })
.then(() => {
graphql = require('graphql')
buildSchema()
})
const rootValue = {
hello: () => 'world'
}
const contextValue = {}
graphql.graphql({ schema, source, rootValue, contextValue })
.then(() => graphql.graphql({ schema, source, rootValue, contextValue }))
.then(() => done())
.catch(done)
})
})
it('should be configured with the correct values', done => {
const source = `{ hello(name: "world") }`
describe('with configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'graphql', { service: 'test' })
.then(() => {
graphql = require(`./versions/graphql@${version}`).get()
buildSchema()
})
})
agent
.use(traces => {
const spans = sort(traces[0])
it('should be configured with the correct values', done => {
const source = `{ hello(name: "world") }`
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('service', 'test')
})
.then(done)
.catch(done)
agent
.use(traces => {
const spans = sort(traces[0])
graphql.graphql(schema, source).catch(done)
expect(spans).to.have.length(3)
expect(spans[2]).to.have.property('service', 'test')
})
.then(done)
.catch(done)
graphql.graphql(schema, source).catch(done)
})
})

@@ -677,0 +702,0 @@ })

@@ -152,2 +152,22 @@ 'use strict'

it('should wait for other listeners before resuming the response stream', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send('OK')
})
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`, res => {
setTimeout(() => {
res.on('data', () => done())
})
})
req.end()
})
})
})
it('should inject its parent span in the headers', done => {

@@ -154,0 +174,0 @@ const app = express()

'use strict'
const agent = require('./agent')
const Buffer = require('safe-buffer').Buffer
const plugin = require('../../src/plugins/mongodb-core')

@@ -8,3 +10,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let mongo

@@ -17,284 +18,304 @@ let server

describe('mongodb-core', () => {
beforeEach(() => {
plugin = require('../../src/plugins/mongodb-core')
platform = require('../../src/platform')
tracer = require('../..')
withVersions(plugin, 'mongodb-core', version => {
beforeEach(() => {
platform = require('../../src/platform')
tracer = require('../..')
collection = platform.id().toString()
})
collection = platform.id().toString()
})
afterEach(() => {
agent.close()
server.destroy()
})
afterEach(() => {
agent.close()
server.destroy()
})
describe('without configuration', () => {
beforeEach(done => {
agent.load(plugin, 'mongodb-core')
.then(() => {
mongo = require('mongodb-core')
describe('without configuration', () => {
beforeEach(done => {
agent.load(plugin, 'mongodb-core')
.then(() => {
mongo = require(`./versions/mongodb-core@${version}`).get()
server = new mongo.Server({
host: 'localhost',
port: 27017,
reconnect: false
server = new mongo.Server({
host: 'localhost',
port: 27017,
reconnect: false
})
server.on('connect', () => done())
server.on('error', done)
server.connect()
})
.catch(done)
})
server.on('connect', () => done())
server.on('error', done)
describe('server', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `insert test.${collection}`
server.connect()
expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'test-mongodb')
expect(span).to.have.property('resource', resource)
expect(span).to.have.property('type', 'mongodb')
expect(span.meta).to.have.property('db.name', `test.${collection}`)
expect(span.meta).to.have.property('out.host', 'localhost')
})
.then(done)
.catch(done)
server.insert(`test.${collection}`, [{ a: 1 }], {}, () => {})
})
.catch(done)
})
describe('server', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `insert test.${collection}`
it('should use the correct resource name for arbitrary commands', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `planCacheListPlans test.${collection} {}`
expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'test-mongodb')
expect(span).to.have.property('resource', resource)
expect(span).to.have.property('type', 'mongodb')
expect(span.meta).to.have.property('db.name', `test.${collection}`)
expect(span.meta).to.have.property('out.host', 'localhost')
})
.then(done)
.catch(done)
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
server.insert(`test.${collection}`, [{ a: 1 }], {}, () => {})
})
server.command(`test.${collection}`, {
planCacheListPlans: `test.${collection}`,
query: {}
}, () => {})
})
it('should use the correct resource name for arbitrary commands', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `planCacheListPlans test.${collection} {}`
it('should use a fallback for unknown commands', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `unknownCommand test.${collection}`
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
server.command(`test.${collection}`, {
planCacheListPlans: `test.${collection}`,
query: {}
}, () => {})
})
server.command(`test.${collection}`, {
invalidCommand: `test.${collection}`
}, () => {})
})
it('should use a fallback for unknown commands', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `unknownCommand test.${collection}`
it('should sanitize the query as the resource', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `find test.${collection} {"foo":"?","bar":{"baz":"?"}}`
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
server.command(`test.${collection}`, {
invalidCommand: `test.${collection}`
}, () => {})
})
server.command(`test.${collection}`, {
find: `test.${collection}`,
query: {
foo: 1,
bar: {
baz: [1, 2, 3]
}
}
}, () => {})
})
it('should sanitize the query as the resource', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `find test.${collection} {"foo":"?","bar":{"baz":"?"}}`
it('should sanitize buffers as values and not as objects', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `find test.${collection} {"_id":"?"}`
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
server.command(`test.${collection}`, {
find: `test.${collection}`,
query: {
foo: 1,
bar: {
baz: [1, 2, 3]
server.command(`test.${collection}`, {
find: `test.${collection}`,
query: {
_id: Buffer.from('1234')
}
}
}, () => {})
})
}, () => {})
})
it('should run the callback in the parent context', done => {
server.insert(`test.${collection}`, [{ a: 1 }], {}, () => {
expect(tracer.scopeManager().active()).to.be.null
done()
it('should run the callback in the parent context', done => {
server.insert(`test.${collection}`, [{ a: 1 }], {}, () => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
server.insert('', [{ a: 1 }], (err) => {
error = err
server.destroy()
})
.then(done)
.catch(done)
server.insert('', [{ a: 1 }], (err) => {
error = err
server.destroy()
})
})
})
describe('cursor', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
describe('cursor', () => {
it('should do automatic instrumentation', done => {
agent
.use(traces => {
const span = traces[0][0]
expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'test-mongodb')
expect(span).to.have.property('type', 'mongodb')
expect(span.meta).to.have.property('db.name', `test.${collection}`)
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '27017')
})
.then(done)
.catch(done)
expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'test-mongodb')
expect(span).to.have.property('type', 'mongodb')
expect(span.meta).to.have.property('db.name', `test.${collection}`)
expect(span.meta).to.have.property('out.host', 'localhost')
expect(span.meta).to.have.property('out.port', '27017')
})
.then(done)
.catch(done)
const cursor = server.cursor(`test.${collection}`, {
insert: `test.${collection}`,
documents: [{ a: 1 }]
}, {})
const cursor = server.cursor(`test.${collection}`, {
insert: `test.${collection}`,
documents: [{ a: 1 }]
}, {})
cursor.next()
})
it('should have the correct index', done => {
let cursor
agent.use(() => {
cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: {}
}, { batchSize: 1 })
cursor.next()
})
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('mongodb.cursor.index', '0')
})
.then(() => cursor.next())
.catch(done)
it('should have the correct index', done => {
let cursor
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('mongodb.cursor.index', '1')
agent.use(() => {
cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: {}
}, { batchSize: 1 })
cursor.next()
})
.then(done)
.catch(done)
server.insert(`test.${collection}`, [{ a: 1 }, { a: 2 }], {})
})
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('mongodb.cursor.index', '0')
})
.then(() => cursor.next())
.catch(done)
it('should sanitize the query as the resource', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `find test.${collection} {"foo":"?","bar":{"baz":"?"}}`
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('mongodb.cursor.index', '1')
})
.then(done)
.catch(done)
expect(span).to.have.property('resource', resource)
server.insert(`test.${collection}`, [{ a: 1 }, { a: 2 }], {})
})
it('should sanitize the query as the resource', done => {
agent
.use(traces => {
const span = traces[0][0]
const resource = `find test.${collection} {"foo":"?","bar":{"baz":"?"}}`
expect(span).to.have.property('resource', resource)
})
.then(done)
.catch(done)
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: {
foo: 1,
bar: {
baz: [1, 2, 3]
}
}
})
.then(done)
.catch(done)
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: {
foo: 1,
bar: {
baz: [1, 2, 3]
}
}
cursor.next()
})
cursor.next()
})
it('should run the callback in the parent context', done => {
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: { a: 1 }
})
it('should run the callback in the parent context', done => {
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: { a: 1 }
cursor.next(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
cursor.next(() => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: 'invalid'
})
.then(done)
.catch(done)
const cursor = server.cursor(`test.${collection}`, {
find: `test.${collection}`,
query: 'invalid'
cursor.next(err => {
error = err
})
})
cursor.next(err => {
error = err
})
})
})
})
describe('with configuration', () => {
let config
describe('with configuration', () => {
let config
beforeEach(done => {
config = {
service: 'custom'
}
beforeEach(done => {
config = {
service: 'custom'
}
agent.load(plugin, 'mongodb-core', config)
.then(() => {
mongo = require('mongodb-core')
agent.load(plugin, 'mongodb-core', config)
.then(() => {
mongo = require(`./versions/mongodb-core@${version}`).get()
server = new mongo.Server({
host: 'localhost',
port: 27017,
reconnect: false
})
server = new mongo.Server({
host: 'localhost',
port: 27017,
reconnect: false
})
server.on('connect', () => done())
server.on('error', done)
server.on('connect', () => done())
server.on('error', done)
server.connect()
})
.catch(done)
})
server.connect()
})
.catch(done)
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
server.insert(`test.${collection}`, [{ a: 1 }], () => {})
server.insert(`test.${collection}`, [{ a: 1 }], () => {})
})
})

@@ -301,0 +322,0 @@ })

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/mysql')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let mysql

@@ -14,185 +14,185 @@ let tracer

describe('mysql', () => {
beforeEach(() => {
plugin = require('../../src/plugins/mysql')
tracer = require('../..')
})
withVersions(plugin, 'mysql', version => {
beforeEach(() => {
tracer = require('../..')
})
afterEach(() => {
agent.close()
})
afterEach(() => {
agent.close()
agent.wipe()
})
describe('without configuration', () => {
let connection
describe('without configuration', () => {
let connection
beforeEach(() => {
return agent.load(plugin, 'mysql')
.then(() => {
mysql = require('mysql')
beforeEach(() => {
return agent.load(plugin, 'mysql')
.then(() => {
mysql = require(`./versions/mysql@${version}`).get()
connection = mysql.createConnection({
host: 'localhost',
user: 'user',
password: 'userpass',
database: 'db'
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'db'
})
connection.connect()
})
})
connection.connect()
})
})
afterEach(done => {
connection.end(done)
})
afterEach(done => {
connection.end(done)
})
it('should propagate context to callbacks', done => {
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
it('should propagate context to callbacks', done => {
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
})
})
it('should run the callback in the parent context', done => {
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
it('should run the callback in the parent context', done => {
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
})
})
it('should run event listeners in the parent context', done => {
const query = connection.query('SELECT 1 + 1 AS solution')
it('should run event listeners in the parent context', done => {
const query = connection.query('SELECT 1 + 1 AS solution')
query.on('result', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
query.on('result', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
})
})
it('should do automatic instrumentation', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'db')
expect(traces[0][0].meta).to.have.property('db.user', 'user')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
it('should do automatic instrumentation', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'db')
expect(traces[0][0].meta).to.have.property('db.user', 'root')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
done()
})
done()
})
connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
if (error) throw error
connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
if (error) throw error
})
})
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
done()
done()
})
connection.query('INVALID', (err, results, fields) => {
error = err
})
})
connection.query('INVALID', (err, results, fields) => {
error = err
it('should work without a callback', done => {
agent.use(traces => {
done()
})
connection.query('SELECT 1 + 1 AS solution')
})
})
it('should work without a callback', done => {
agent.use(traces => {
done()
})
describe('with configuration', () => {
let connection
let config
connection.query('SELECT 1 + 1 AS solution')
})
})
beforeEach(() => {
config = {
service: 'custom'
}
describe('with configuration', () => {
let connection
let config
return agent.load(plugin, 'mysql', config)
.then(() => {
mysql = require(`./versions/mysql@${version}`).get()
beforeEach(() => {
config = {
service: 'custom'
}
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'db'
})
return agent.load(plugin, 'mysql', config)
.then(() => {
mysql = require('mysql')
connection = mysql.createConnection({
host: 'localhost',
user: 'user',
password: 'userpass',
database: 'db'
connection.connect()
})
})
connection.connect()
afterEach(done => {
connection.end(done)
})
it('should be configured with the correct values', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
done()
})
})
afterEach(done => {
connection.end(done)
})
it('should be configured with the correct values', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
done()
connection.query('SELECT 1 + 1 AS solution', () => {})
})
connection.query('SELECT 1 + 1 AS solution')
})
})
describe('with a connection pool', () => {
let pool
describe('with a connection pool', () => {
let pool
beforeEach(() => {
return agent.load(plugin, 'mysql')
.then(() => {
mysql = require('mysql')
beforeEach(() => {
return agent.load(plugin, 'mysql')
.then(() => {
mysql = require(`./versions/mysql@${version}`).get()
pool = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'user',
password: 'userpass'
pool = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'root',
database: 'db'
})
})
})
})
})
afterEach(done => {
pool.end(done)
})
afterEach(done => {
pool.end(done)
})
it('should do automatic instrumentation', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.user', 'user')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
it('should do automatic instrumentation', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.user', 'root')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
done()
done()
})
pool.query('SELECT 1 + 1 AS solution', () => {})
})
pool.query('SELECT 1 + 1 AS solution')
})
it('should run the callback in the parent context', done => {
pool.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
it('should run the callback in the parent context', done => {
pool.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
})

@@ -199,0 +199,0 @@ })

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/mysql2')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let mysql2

@@ -14,191 +14,190 @@ let tracer

describe('mysql2', () => {
beforeEach(() => {
plugin = require('../../src/plugins/mysql2')
tracer = require('../..')
})
withVersions(plugin, 'mysql2', version => {
beforeEach(() => {
tracer = require('../..')
})
afterEach(() => {
agent.close()
})
afterEach(() => {
agent.close()
agent.wipe()
})
describe('without configuration', () => {
let connection
describe('without configuration', () => {
let connection
beforeEach(() => {
return agent.load(plugin, 'mysql2')
.then(() => {
mysql2 = require('mysql2')
beforeEach(() => {
return agent.load(plugin, 'mysql2')
.then(() => {
mysql2 = require(`./versions/mysql2@${version}`).get()
connection = mysql2.createConnection({
host: 'localhost',
user: 'user',
password: 'userpass',
database: 'db'
connection = mysql2.createConnection({
host: 'localhost',
user: 'root',
database: 'db'
})
connection.connect()
})
})
connection.connect()
})
})
afterEach(done => {
connection.end(done)
})
afterEach(done => {
connection.end(done)
})
it('should propagate context to callbacks', done => {
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
it('should propagate context to callbacks', done => {
const span = tracer.startSpan('test')
const scope = tracer.scopeManager().activate(span)
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
})
})
it('should run the callback in the parent context', done => {
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
it('should run the callback in the parent context', done => {
connection.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
})
})
it('should run event listeners in the parent context', done => {
const query = connection.query('SELECT 1 + 1 AS solution')
it('should run event listeners in the parent context', done => {
const query = connection.query('SELECT 1 + 1 AS solution')
query.on('result', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
query.on('result', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
})
})
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'db')
expect(traces[0][0].meta).to.have.property('db.user', 'user')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'db')
expect(traces[0][0].meta).to.have.property('db.user', 'root')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
})
.then(done)
.catch(done)
connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
if (error) throw error
})
.then(done)
.catch(done)
connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
if (error) throw error
})
})
it('should handle errors', done => {
let error
it('should handle errors', done => {
let error
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
connection.query('INVALID', (err, results, fields) => {
error = err
})
.then(done)
.catch(done)
})
connection.query('INVALID', (err, results, fields) => {
error = err
it('should work without a callback', done => {
agent
.use(() => {})
.then(done)
.catch(done)
connection.query('SELECT 1 + 1 AS solution')
})
})
it('should work without a callback', done => {
agent
.use(() => {})
.then(done)
.catch(done)
describe('with configuration', () => {
let connection
let config
connection.query('SELECT 1 + 1 AS solution')
})
})
beforeEach(() => {
config = {
service: 'custom'
}
describe('with configuration', () => {
let connection
let config
return agent.load(plugin, 'mysql2', config)
.then(() => {
mysql2 = require(`./versions/mysql2@${version}`).get()
beforeEach(() => {
config = {
service: 'custom'
}
connection = mysql2.createConnection({
host: 'localhost',
user: 'root',
database: 'db'
})
return agent.load(plugin, 'mysql2', config)
.then(() => {
mysql2 = require('mysql2')
connection.connect()
})
})
connection = mysql2.createConnection({
host: 'localhost',
user: 'user',
password: 'userpass',
database: 'db'
afterEach(done => {
connection.end(done)
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
connection.connect()
})
connection.query('SELECT 1 + 1 AS solution')
})
})
afterEach(done => {
connection.end(done)
})
describe('with a connection pool', () => {
let pool
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
beforeEach(() => {
return agent.load(plugin, 'mysql2')
.then(() => {
mysql2 = require(`./versions/mysql2@${version}`).get()
connection.query('SELECT 1 + 1 AS solution')
})
})
pool = mysql2.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'root'
})
})
})
describe('with a connection pool', () => {
let pool
afterEach(done => {
pool.end(done)
})
beforeEach(() => {
return agent.load(plugin, 'mysql2')
.then(() => {
mysql2 = require('mysql2')
pool = mysql2.createPool({
connectionLimit: 10,
host: 'localhost',
user: 'user',
password: 'userpass'
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.user', 'root')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
})
})
})
.then(done)
.catch(done)
afterEach(done => {
pool.end(done)
})
pool.query('SELECT 1 + 1 AS solution')
})
it('should do automatic instrumentation', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.user', 'user')
expect(traces[0][0].meta).to.have.property('db.type', 'mysql')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
it('should run the callback in the parent context', done => {
pool.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})
.then(done)
.catch(done)
pool.query('SELECT 1 + 1 AS solution')
})
it('should run the callback in the parent context', done => {
pool.query('SELECT 1 + 1 AS solution', () => {
const active = tracer.scopeManager().active()
expect(active).to.be.null
done()
})

@@ -205,0 +204,0 @@ })

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/pg')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let pg

@@ -15,63 +15,90 @@ let client

describe('pg', () => {
beforeEach(() => {
plugin = require('../../src/plugins/pg')
tracer = require('../..')
})
withVersions(plugin, 'pg', version => {
beforeEach(() => {
tracer = require('../..')
})
afterEach(() => {
agent.close()
})
afterEach(() => {
agent.close()
})
describe('when using a client', () => {
beforeEach(done => {
agent.load(plugin, 'pg')
.then(() => {
pg = require('pg')
describe('when using a client', () => {
beforeEach(done => {
agent.load(plugin, 'pg')
.then(() => {
pg = require(`./versions/pg@${version}`).get()
client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
})
client.connect(err => done(err))
})
.catch(done)
})
client.connect(err => done(err))
it('should do automatic instrumentation when using callbacks', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-postgres')
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'postgres')
expect(traces[0][0].meta).to.have.property('db.user', 'postgres')
expect(traces[0][0].meta).to.have.property('db.type', 'postgres')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
done()
})
.catch(done)
})
it('should do automatic instrumentation when using callbacks', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test-postgres')
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')
expect(traces[0][0]).to.have.property('type', 'sql')
expect(traces[0][0].meta).to.have.property('db.name', 'postgres')
expect(traces[0][0].meta).to.have.property('db.user', 'postgres')
expect(traces[0][0].meta).to.have.property('db.type', 'postgres')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
done()
client.end((err) => {
if (err) throw err
})
})
})
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
it('should handle errors', done => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', 'error')
expect(traces[0][0].meta).to.have.property('error.msg', 'syntax error at or near "INVALID"')
expect(traces[0][0].meta).to.have.property('error.stack')
client.end((err) => {
if (err) throw err
done()
})
client.query('INVALID', (err, result) => {
expect(err).to.be.an('error')
client.end((err) => {
if (err) throw err
})
})
})
})
it('should handle errors', done => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', 'error')
expect(traces[0][0].meta).to.have.property('error.msg', 'syntax error at or near "INVALID"')
expect(traces[0][0].meta).to.have.property('error.stack')
it('should run the callback in the parent context', done => {
const span = {}
const scope = tracer.scopeManager().activate(span)
done()
client.query('SELECT $1::text as message', ['Hello World!'], () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
client.end((err) => {
if (err) throw err
})
})
client.query('INVALID', (err, result) => {
expect(err).to.be.an('error')
it('should work without a callback', done => {
agent.use(traces => {
done()
})
client.query('SELECT $1::text as message', ['Hello World!'])
client.end((err) => {

@@ -83,109 +110,83 @@ if (err) throw err

it('should run the callback in the parent context', done => {
const span = {}
const scope = tracer.scopeManager().activate(span)
describe('when using a pool', () => {
let pool
client.query('SELECT $1::text as message', ['Hello World!'], () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
beforeEach(done => {
agent.load(plugin, 'pg')
.then(() => {
pg = require('pg')
client.end((err) => {
if (err) throw err
})
})
pool = new pg.Pool({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
})
it('should work without a callback', done => {
agent.use(traces => {
done()
pool.connect((err, c) => {
client = c
done(err)
})
})
.catch(done)
})
client.query('SELECT $1::text as message', ['Hello World!'])
client.end((err) => {
if (err) throw err
afterEach(() => {
client && client.release()
})
})
})
describe('when using a pool', () => {
let pool
it('should run the callback in the parent context', done => {
const span = {}
const scope = tracer.scopeManager().activate(span)
beforeEach(done => {
agent.load(plugin, 'pg')
.then(() => {
pg = require('pg')
pool.query('SELECT $1::text as message', ['Hello World!'], () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
pool = new pg.Pool({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
})
pool.connect((err, c) => {
client = c
done(err)
})
pool.end((err) => {
if (err) throw err
})
.catch(done)
})
})
afterEach(() => {
client && client.release()
})
describe('with configuration', () => {
let config
it('should run the callback in the parent context', done => {
const span = {}
const scope = tracer.scopeManager().activate(span)
beforeEach(done => {
config = {
service: 'custom'
}
pool.query('SELECT $1::text as message', ['Hello World!'], () => {
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()
})
agent.load(plugin, 'pg', config)
.then(() => {
pg = require('pg')
pool.end((err) => {
if (err) throw err
client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
})
client.connect(err => done(err))
})
.catch(done)
})
})
})
describe('with configuration', () => {
let config
it('should be configured with the correct values', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
beforeEach(done => {
config = {
service: 'custom'
}
done()
})
agent.load(plugin, 'pg', config)
.then(() => {
pg = require('pg')
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
client.end((err) => {
if (err) throw err
})
client.connect(err => done(err))
})
.catch(done)
})
it('should be configured with the correct values', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
done()
})
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
client.end((err) => {
if (err) throw err
})
})
})

@@ -192,0 +193,0 @@ })

'use strict'
const agent = require('./agent')
const plugin = require('../../src/plugins/redis')

@@ -8,3 +9,2 @@ wrapIt()

describe('Plugin', () => {
let plugin
let redis

@@ -15,116 +15,117 @@ let tracer

describe('redis', () => {
beforeEach(() => {
plugin = require('../../src/plugins/redis')
tracer = require('../..')
})
afterEach(() => {
client.quit()
agent.close()
})
describe('without configuration', () => {
withVersions(plugin, 'redis', version => {
beforeEach(() => {
return agent.load(plugin, 'redis')
.then(() => {
redis = require('redis')
client = redis.createClient()
})
tracer = require('../..')
})
it('should do automatic instrumentation when using callbacks', done => {
client.on('error', done)
agent.use(() => client.get('foo')) // wait for initial info command
agent
.use(traces => {
expect(traces[0][0]).to.have.property('name', 'redis.command')
expect(traces[0][0]).to.have.property('service', 'test-redis')
expect(traces[0][0]).to.have.property('resource', 'get')
expect(traces[0][0]).to.have.property('type', 'redis')
expect(traces[0][0].meta).to.have.property('db.name', '0')
expect(traces[0][0].meta).to.have.property('db.type', 'redis')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
expect(traces[0][0].meta).to.have.property('out.host', '127.0.0.1')
expect(traces[0][0].meta).to.have.property('out.port', '6379')
})
.then(done)
.catch(done)
afterEach(() => {
client.quit()
agent.close()
})
it('should run the callback in the parent context', done => {
client.on('error', done)
client.get('foo', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'redis')
.then(() => {
redis = require(`./versions/redis@${version}`).get()
client = redis.createClient()
})
})
})
it('should run client emitter listeners in the parent context', done => {
client.on('error', done)
it('should do automatic instrumentation when using callbacks', done => {
client.on('error', done)
client.on('ready', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
agent.use(() => client.get('foo')) // wait for initial info command
agent
.use(traces => {
expect(traces[0][0]).to.have.property('name', 'redis.command')
expect(traces[0][0]).to.have.property('service', 'test-redis')
expect(traces[0][0]).to.have.property('resource', 'get')
expect(traces[0][0]).to.have.property('type', 'redis')
expect(traces[0][0].meta).to.have.property('db.name', '0')
expect(traces[0][0].meta).to.have.property('db.type', 'redis')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
expect(traces[0][0].meta).to.have.property('out.host', '127.0.0.1')
expect(traces[0][0].meta).to.have.property('out.port', '6379')
})
.then(done)
.catch(done)
})
})
it('should run stream emitter listeners in the parent context', done => {
client.on('error', done)
it('should run the callback in the parent context', done => {
client.on('error', done)
client.stream.on('close', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
client.get('foo', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
client.stream.destroy()
})
it('should run client emitter listeners in the parent context', done => {
client.on('error', done)
it('should handle errors', done => {
let error
client.on('ready', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
})
client.on('error', done)
it('should run stream emitter listeners in the parent context', done => {
client.on('error', done)
agent.use(() => { // wait for initial info command
client.set('foo', 123, 'bar', (err, res) => {
error = err
client.stream.on('close', () => {
expect(tracer.scopeManager().active()).to.be.null
done()
})
client.stream.destroy()
})
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
it('should handle errors', done => {
let error
client.on('error', done)
agent.use(() => { // wait for initial info command
client.set('foo', 123, 'bar', (err, res) => {
error = err
})
})
.then(done)
.catch(done)
agent
.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', error.name)
expect(traces[0][0].meta).to.have.property('error.msg', error.message)
expect(traces[0][0].meta).to.have.property('error.stack', error.stack)
})
.then(done)
.catch(done)
})
})
})
describe('with configuration', () => {
let config
describe('with configuration', () => {
let config
beforeEach(() => {
config = {
service: 'custom'
}
beforeEach(() => {
config = {
service: 'custom'
}
return agent.load(plugin, 'redis', config)
.then(() => {
redis = require('redis')
client = redis.createClient()
})
})
return agent.load(plugin, 'redis', config)
.then(() => {
redis = require(`./versions/redis@${version}`).get()
client = redis.createClient()
})
})
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
it('should be configured with the correct values', done => {
agent
.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
})
.then(done)
.catch(done)
client.on('error', done)
client.on('error', done)
})
})

@@ -131,0 +132,0 @@ })

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

const nock = require('nock')
const semver = require('semver')
const retry = require('retry')

@@ -37,2 +38,3 @@ const pg = require('pg')

global.wrapIt = wrapIt
global.withVersions = withVersions

@@ -101,4 +103,3 @@ platform.use(node)

host: 'localhost',
user: 'user',
password: 'userpass',
user: 'root',
database: 'db'

@@ -239,1 +240,32 @@ })

}
function withVersions (plugin, moduleName, range, cb) {
const instrumentations = [].concat(plugin)
const testVersions = new Map()
if (!cb) {
cb = range
range = null
}
instrumentations
.filter(instrumentation => instrumentation.name === moduleName)
.forEach(instrumentation => {
instrumentation.versions
.filter(version => !range || semver.satisfies(version, range))
.forEach(version => {
const min = semver.coerce(version).version
const max = require(`./plugins/versions/${moduleName}@${version}`).version()
testVersions.set(min, { range: version, test: min })
testVersions.set(max, { range: version, test: version })
})
})
Array.from(testVersions)
.sort(v => v[0].localeCompare(v[0]))
.map(v => Object.assign({}, v[1], { version: v[0] }))
.forEach(v => {
describe(`with ${moduleName} ${v.range} (${v.version})`, () => cb(v.test))
})
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc