Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dd-trace

Package Overview
Dependencies
Maintainers
3
Versions
583
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.1.3 to 0.1.4

scripts/release.js

3

lib/version.js

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

// generated by genversion
module.exports = '0.1.3'
module.exports = '0.1.4'
{
"name": "dd-trace",
"version": "0.1.3",
"version": "0.1.4",
"description": "Datadog APM tracing client for JavaScript (experimental)",

@@ -10,4 +10,3 @@ "main": "index.js",

"tdd": "mocha --watch",
"test": "nyc --reporter text --reporter lcov mocha",
"version": "genversion lib/version.js && git add lib/version.js"
"test": "nyc --reporter text --reporter lcov mocha"
},

@@ -66,3 +65,2 @@ "repository": {

"express": "^4.16.2",
"genversion": "^2.0.1",
"get-port": "^3.2.0",

@@ -69,0 +67,0 @@ "mocha": "^5.0.0",

@@ -8,14 +8,39 @@ 'use strict'

// TODO: lazy load built-in plugins
class Instrumenter {
constructor (tracer, config) {
constructor (tracer) {
this._tracer = tracer
this._plugins = loadPlugins(config)
this._integrations = loadIntegrations()
this._plugins = new Map()
this._instrumented = new Map()
}
patch () {
const instrumentedModules = this._plugins.map(plugin => plugin.name)
hook(instrumentedModules, this.hookModule.bind(this))
use (name, config) {
config = config || {}
if (typeof name === 'string') {
this._integrations
.filter(plugin => plugin.name === name)
.forEach(plugin => this._plugins.set(plugin, config))
} else {
[].concat(name)
.forEach(plugin => this._plugins.set(plugin, config))
}
this.reload()
}
patch (config) {
config = config || {}
if (config.plugins !== false) {
loadIntegrations().forEach(integration => {
this._plugins.has(integration) || this._plugins.set(integration)
})
}
this.reload()
}
unpatch () {

@@ -27,11 +52,20 @@ this._instrumented.forEach((instrumentation, moduleExports) => {

reload () {
const instrumentedModules = Array.from(this._plugins.keys()).map(plugin => plugin.name)
hook(instrumentedModules, this.hookModule.bind(this))
}
hookModule (moduleExports, moduleName, moduleBaseDir) {
const moduleVersion = getVersion(moduleBaseDir)
this._plugins
Array.from(this._plugins.keys())
.filter(plugin => plugin.name === moduleName)
.filter(plugin => matchVersion(moduleVersion, plugin.versions))
.forEach(plugin => {
plugin.patch(moduleExports, this._tracer)
this._instrumented.set(moduleExports, plugin)
let moduleToPatch = moduleExports
if (plugin.file) {
moduleToPatch = require(path.join(moduleBaseDir, plugin.file))
}
plugin.patch(moduleToPatch, this._tracer._tracer, this._plugins.get(plugin))
this._instrumented.set(moduleToPatch, plugin)
})

@@ -43,15 +77,8 @@

function loadPlugins (config) {
if (config.plugins === false) {
return []
}
const plugins = []
function loadIntegrations () {
const integrations = requireDir('./plugins')
Object.keys(integrations).forEach(key => {
plugins.push(integrations[key])
})
return plugins
return Object.keys(integrations)
.map(key => integrations[key])
.reduce((previous, current) => previous.concat(current), [])
}

@@ -58,0 +85,0 @@

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

const parentPath = parentModule(callerPath)
const pkg = readPkgUp.sync({ cwd: path.dirname(parentPath) }).pkg
const pkg = readPkgUp.sync({ cwd: path.dirname(parentPath) }).pkg || {}

@@ -13,0 +13,0 @@ this._service = pkg.name

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

function patch (express, tracer) {
function patch (express, tracer, config) {
METHODS.forEach((method) => {

@@ -39,3 +39,3 @@ shimmer.wrap(express.application, method, wrapper)

span.setTag('service.name', tracer._service)
span.setTag('service.name', config.service || tracer._service)
span.setTag('span.type', 'web')

@@ -42,0 +42,0 @@ span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode)

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

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

@@ -39,3 +39,3 @@ shimmer.wrap(http, 'get', get => makeRequestTrace(get))

span.addTags({
'service.name': 'http-client',
'service.name': config.service || 'http-client',
'span.type': 'web',

@@ -42,0 +42,0 @@ 'resource.name': options.pathname

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

function patch (pg, tracer) {
function patch (pg, tracer, config) {
function queryWrap (query) {

@@ -24,3 +24,3 @@ return function queryTrace () {

}, span => {
span.setTag('service.name', 'postgres')
span.setTag('service.name', config.service || 'postgres')
span.setTag('resource.name', statement)

@@ -27,0 +27,0 @@ span.setTag('db.name', params.database)

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

const Config = require('./config')
const Instrumenter = require('./instrumenter')
const platform = require('./platform')

@@ -16,2 +17,3 @@

this._tracer = noop
this._instrumenter = new Instrumenter(this)
}

@@ -24,2 +26,4 @@

const config = new Config(options)
this._instrumenter.patch(config)
this._tracer = new DatadogTracer(config)

@@ -31,6 +35,19 @@ }

trace () {
return this._tracer.trace.apply(this._tracer, arguments)
use () {
this._instrumenter.use.apply(this._instrumenter, arguments)
return this
}
trace (operationName, options, callback) {
if (callback) {
return this._tracer.trace.apply(this._tracer, arguments)
} else {
return new Promise((resolve, reject) => {
this._tracer.trace(operationName, options, span => {
resolve(span)
})
})
}
}
startSpan () {

@@ -37,0 +54,0 @@ return this._tracer.startSpan.apply(this._tracer, arguments)

@@ -11,7 +11,10 @@ 'use strict'

this._writer = new Writer(url, size)
this._scheduler = new Scheduler(() => this._writer.flush(), interval)
if (interval > 0) {
this._scheduler = new Scheduler(() => this._writer.flush(), interval)
}
}
init () {
this._scheduler.start()
this._scheduler && this._scheduler.start()
}

@@ -21,2 +24,6 @@

this._writer.append(span)
if (!this._scheduler) {
this._writer.flush()
}
}

@@ -23,0 +30,0 @@ }

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

const Tracer = require('./opentracing/tracer')
const Instrumenter = require('./instrumenter')

@@ -13,4 +12,2 @@ class DatadogTracer extends Tracer {

this._context = platform.context(config)
this._instrumenter = new Instrumenter(this, config)
this._instrumenter.patch()
}

@@ -17,0 +14,0 @@

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

port: listener.address().port,
flushInterval: 10,
flushInterval: 0,
plugins: false

@@ -28,0 +28,0 @@ })

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

@@ -11,5 +12,10 @@

let requireDir
let Connection
let Pool
let plugins
beforeEach(() => {
tracer = 'tracer'
tracer = {
_tracer: 'tracer'
}

@@ -23,9 +29,41 @@ integrations = {

express: {
name: 'express',
name: 'express-mock',
versions: ['4.x'],
patch: sinon.spy(),
unpatch: sinon.spy()
},
mysql: [
{
name: 'mysql-mock',
versions: ['2.x'],
file: 'lib/Connection.js',
patch: sinon.spy(),
unpatch: sinon.spy()
},
{
name: 'mysql-mock',
versions: ['2.x'],
file: 'lib/Pool.js',
patch: sinon.spy(),
unpatch: sinon.spy()
}
]
}
plugins = {
other: {
name: 'other',
versions: ['1.x'],
patch: sinon.spy(),
unpatch: sinon.spy()
}
}
const mysqlDir = path.normalize(path.join(__dirname, 'node_modules', 'mysql-mock'))
const connectionPath = path.join(mysqlDir, 'lib', 'Connection.js')
const poolPath = path.join(mysqlDir, 'lib', 'Pool.js')
Connection = 'Connection'
Pool = 'Pool'
requireDir = sinon.stub()

@@ -35,9 +73,72 @@ requireDir.withArgs('./plugins').returns(integrations)

Instrumenter = proxyquire('../src/instrumenter', {
'require-dir': requireDir
'require-dir': requireDir,
[connectionPath]: Connection,
[poolPath]: Pool
})
instrumenter = new Instrumenter(tracer)
})
describe('when enabled', () => {
beforeEach(() => {
instrumenter = new Instrumenter(tracer, { plugins: true })
describe('with integrations enabled', () => {
describe('use', () => {
it('should allow configuring a plugin by name', () => {
const config = { foo: 'bar' }
instrumenter.use('express-mock', config)
instrumenter.patch()
const express = require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', config)
})
it('should allow configuring a plugin by instance', () => {
const config = { foo: 'bar' }
instrumenter.use(integrations.express, config)
instrumenter.patch()
const express = require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', config)
})
it('should default to an empty plugin configuration', () => {
instrumenter.use('express-mock')
instrumenter.patch()
const express = require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {})
})
it('should support a plugin instance', () => {
const express = require('express-mock')
instrumenter.use(express)
instrumenter.patch()
require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer')
})
it('should reapply the require hook when called multiple times', () => {
instrumenter.use('mysql-mock')
instrumenter.use('express-mock')
instrumenter.patch()
require('express-mock')
expect(integrations.express.patch).to.have.been.called
})
it('should support third party plugins', () => {
instrumenter.use(plugins.other)
instrumenter.patch()
const other = require('other')
expect(plugins.other.patch).to.have.been.calledWith(other, 'tracer')
})
})

@@ -49,5 +150,5 @@

const express = require('express')
const express = require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, tracer)
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer')
})

@@ -59,5 +160,5 @@

const express = require('express')
const express = require('express-mock')
expect(integrations.express.patch).to.not.have.been.calledWith(express, tracer)
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer')
})

@@ -70,4 +171,15 @@

expect(integrations.http.patch).to.have.been.calledWith(http, tracer)
expect(integrations.http.patch).to.have.been.called
expect(integrations.http.patch).to.have.been.calledWith(http, 'tracer')
})
it('should support patching multiple files', () => {
instrumenter.patch()
const mysql = require('mysql-mock')
expect(mysql).to.deep.equal({ foo: 'bar' })
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer')
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer')
})
})

@@ -79,3 +191,3 @@

const express = require('express')
const express = require('express-mock')

@@ -89,14 +201,31 @@ instrumenter.unpatch()

describe('when disabled', () => {
beforeEach(() => {
instrumenter = new Instrumenter(tracer, { plugins: false })
describe('with integrations disabled', () => {
describe('use', () => {
it('should still allow adding plugins manually by name', () => {
instrumenter.use('express-mock')
instrumenter.patch({ plugins: false })
const express = require('express-mock')
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer')
})
})
it('should support an array of plugins', () => {
instrumenter.use(integrations.mysql)
instrumenter.patch({ plugins: false })
require('mysql-mock')
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer')
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer')
})
describe('patch', () => {
it('should not patch any module', () => {
instrumenter.patch()
instrumenter.patch({ plugins: false })
const express = require('express')
const express = require('express-mock')
expect(integrations.express.patch).to.not.have.been.calledWith(express, tracer)
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer')
})

@@ -103,0 +232,0 @@ })

'use strict'
const apiCompatibilityChecks = require('opentracing/lib/test/api_compatibility').default
const DatadogTracer = require('../../src/opentracing/tracer')
const tracer = require('../..')
apiCompatibilityChecks(() => {
const clock = sinon.useFakeTimers()
const tracer = new DatadogTracer({ service: 'test' })
clock.restore()
return tracer
return tracer.init({
service: 'test',
flushInterval: 0,
plugins: false
})
})

@@ -123,5 +123,15 @@ 'use strict'

let service
let load
let readPkgUp
beforeEach(() => {
readPkgUp = {
sync: sinon.stub()
}
platform = require('../../../src/platform/node')
load = proxyquire('../src/platform/node/load', {
'read-pkg-up': readPkgUp
})
service = platform._service

@@ -140,2 +150,10 @@ })

it('should not load the service name if the module information is unavailable', () => {
readPkgUp.sync.returns({ pkg: undefined })
load.call(platform)
expect(platform._service).to.be.undefined
})
it('should work even in subfolders', () => {

@@ -306,3 +324,2 @@ require('./load/indirect')

let namespace
let cls
let clsBluebird

@@ -312,4 +329,4 @@ let config

beforeEach(() => {
clsBluebird = sinon.spy(require('cls-bluebird'))
require.cache[require.resolve('cls-bluebird')].exports = clsBluebird
require('cls-bluebird')
clsBluebird = sinon.spy(require.cache[require.resolve('cls-bluebird')], 'exports')
context = require('../../../src/platform/node/context')

@@ -319,3 +336,3 @@ })

afterEach(() => {
cls.destroyNamespace('dd-trace')
require.cache[require.resolve('cls-bluebird')].exports.restore()
})

@@ -325,3 +342,2 @@

beforeEach(() => {
cls = require('continuation-local-storage')
config = { experimental: { asyncHooks: false } }

@@ -337,3 +353,2 @@ namespace = context(config)

beforeEach(() => {
cls = require('cls-hooked')
config = { experimental: { asyncHooks: true } }

@@ -348,6 +363,2 @@ namespace = context(config)

function testContext (modulePath) {
afterEach(() => {
delete require.cache[require.resolve(modulePath)]
})
it('should use the correct implementation from the experimental flag', () => {

@@ -381,7 +392,7 @@ expect(namespace).to.equal(require(modulePath))

setImmediate(() => test())
namespace.run(() => {
namespace.set('foo', childValue)
})
test()
})

@@ -388,0 +399,0 @@

@@ -13,5 +13,6 @@ 'use strict'

let tracer = null
let handlers = []
module.exports = {
load (plugin, moduleToPatch) {
load (plugin, moduleToPatch, config) {
tracer = require('../..')

@@ -25,2 +26,11 @@ agent = express()

agent.put('/v0.3/traces', (req, res) => {
res.status(200).send('OK')
if (handlers[0]) {
handlers[0](req.body)
handlers.shift()
}
})
return getPort().then(port => {

@@ -32,3 +42,6 @@ return new Promise((resolve, reject) => {

server.on('close', () => plugin.unpatch(moduleToPatch))
server.on('close', () => {
tracer._instrumenter.unpatch()
tracer = null
})

@@ -38,7 +51,9 @@ tracer.init({

port,
flushInterval: 10,
flushInterval: 0,
plugins: false
})
plugin.patch(moduleToPatch, tracer._tracer)
tracer.use(plugin, config)
require(moduleToPatch)
})

@@ -49,5 +64,11 @@ })

use (callback) {
agent.put('/v0.3/traces', (req, res) => {
res.status(200).send('OK')
callback(req.body)
return new Promise((resolve, reject) => {
handlers.push(function () {
try {
callback.apply(null, arguments)
resolve()
} catch (e) {
reject(e)
}
})
})

@@ -64,5 +85,5 @@ },

agent = null
tracer = null
handlers = []
delete require.cache[require.resolve('../..')]
}
}

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

context = require('../../src/platform').context({ experimental: { asyncHooks: false } })
return agent.load(plugin, express)
})

@@ -28,74 +26,110 @@

it('should do automatic instrumentation', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send()
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'express')
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'web')
expect(traces[0][0]).to.have.property('resource', '/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')
it('should do automatic instrumentation', done => {
const app = express()
done()
app.get('/user', (req, res) => {
res.status(200).send()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'test')
expect(traces[0][0]).to.have.property('type', 'web')
expect(traces[0][0]).to.have.property('resource', '/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')
done()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
})
})
})
})
it('should support custom routers', done => {
const app = express()
it('should support custom routers', done => {
const app = express()
app.use((req, res) => {
res.status(200).send()
app.use((req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'express.request')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
done()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}`)
.catch(done)
})
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('resource', 'express.request')
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
it('should support context propagation', done => {
const app = express()
done()
app.use((req, res, next) => {
context.set('foo', 'bar')
next()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}`)
.catch(done)
app.get('/user', (req, res) => {
res.status(200).send(context.get('foo'))
})
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/user`)
.then(res => {
expect(res.status).to.equal(200)
expect(res.data).to.equal('bar')
done()
})
.catch(done)
})
})
})
})
it('should support context propagation', done => {
const app = express()
it('should extract its parent span from the headers', done => {
const app = express()
app.use((req, res, next) => {
context.set('foo', 'bar')
next()
})
app.get('/user', (req, res) => {
expect(agent.currentSpan().context().baggageItems).to.have.property('foo', 'bar')
res.status(200).send()
})
app.get('/user', (req, res) => {
res.status(200).send(context.get('foo'))
})
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')
getPort().then(port => {
appListener = app.listen(port, 'localhost', () => {
axios.get(`http://localhost:${port}/user`)
.then(res => {
expect(res.status).to.equal(200)
expect(res.data).to.equal('bar')
done()
})
.catch(done)
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)
})
})

@@ -105,28 +139,32 @@ })

it('should extract its parent span from the headers', done => {
const app = express()
describe('with configuration', () => {
let config
app.get('/user', (req, res) => {
expect(agent.currentSpan().context().baggageItems).to.have.property('foo', 'bar')
res.status(200).send()
beforeEach(() => {
config = {
service: 'custom'
}
return agent.load(plugin, 'express', config)
})
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 be configured with the correct values', done => {
const app = express()
done()
app.get('/user', (req, res) => {
res.status(200).send()
})
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('service', 'custom')
done()
})
appListener = app.listen(port, 'localhost', () => {
axios
.get(`http://localhost:${port}/user`)
.catch(done)
})
})

@@ -133,0 +171,0 @@ })

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

http = require('http')
return agent.load(plugin, http)
})

@@ -27,107 +25,154 @@

it('should do automatic instrumentation', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send()
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'http')
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'http-client')
expect(traces[0][0]).to.have.property('type', 'web')
expect(traces[0][0]).to.have.property('resource', '/user')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
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')
it('should do automatic instrumentation', done => {
const app = express()
done()
app.get('/user', (req, res) => {
res.status(200).send()
})
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'http-client')
expect(traces[0][0]).to.have.property('type', 'web')
expect(traces[0][0]).to.have.property('resource', '/user')
expect(traces[0][0].meta).to.have.property('span.kind', 'client')
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')
done()
})
req.end()
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
})
req.end()
})
})
})
})
it('should also support http.get', done => {
const app = express()
it('should also support http.get', done => {
const app = express()
app.get('/user', (req, res) => {
res.status(200).send()
app.get('/user', (req, res) => {
res.status(200).send()
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.not.be.undefined
done()
})
appListener = app.listen(port, 'localhost', () => {
const req = http.get(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
})
req.end()
})
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.not.be.undefined
it('should support configuration as an URL object', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/user`)
done()
done()
})
const uri = {
hostname: 'localhost',
port,
pathname: '/user'
}
const req = http.request(uri)
req.end()
})
})
appListener = app.listen(port, 'localhost', () => {
const req = http.get(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
it('should use the correct defaults when not specified', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/`)
done()
})
const req = http.request({
port
})
req.end()
})
})
})
it('should support configuration as an URL object', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/user`)
it('should not require consuming the data', done => {
const app = express()
done()
app.get('/user', (req, res) => {
res.status(200).send()
})
const uri = {
hostname: 'localhost',
port,
pathname: '/user'
}
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.not.be.undefined
const req = http.request(uri)
done()
})
req.end()
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`)
req.end()
})
})
})
})
it('should use the correct defaults when not specified', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/`)
it('should inject its parent span in the headers', done => {
const app = express()
done()
})
app.get('/user', (req, res) => {
expect(req.get('x-datadog-trace-id')).to.be.a('string')
expect(req.get('x-datadog-parent-id')).to.be.a('string')
const req = http.request({
port
res.status(200).send()
})
req.end()
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
it('should not require consuming the data', done => {
const app = express()
done()
})
app.get('/user', (req, res) => {
res.status(200).send()
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`)
req.end()
})
})
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.not.be.undefined
it('should handle errors', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', 'Error')
expect(traces[0][0].meta).to.have.property('error.msg', `connect ECONNREFUSED 127.0.0.1:${port}`)
expect(traces[0][0].meta).to.have.property('error.stack')
done()
})
done()
})
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`)

@@ -140,40 +185,35 @@

it('should inject its parent span in the headers', done => {
const app = express()
describe('with configuration', () => {
let config
app.get('/user', (req, res) => {
expect(req.get('x-datadog-trace-id')).to.be.a('string')
expect(req.get('x-datadog-parent-id')).to.be.a('string')
beforeEach(() => {
config = {
service: 'custom'
}
res.status(200).send()
return agent.load(plugin, 'http', config)
})
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('http.status_code', '200')
it('should be configured with the correct values', done => {
const app = express()
done()
app.get('/user', (req, res) => {
res.status(200).send()
})
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`)
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
req.end()
})
})
})
done()
})
it('should handle errors', done => {
getPort().then(port => {
agent.use(traces => {
expect(traces[0][0].meta).to.have.property('error.type', 'Error')
expect(traces[0][0].meta).to.have.property('error.msg', `connect ECONNREFUSED 127.0.0.1:${port}`)
expect(traces[0][0].meta).to.have.property('error.stack')
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
})
done()
req.end()
})
})
const req = http.request(`http://localhost:${port}/user`)
req.end()
})

@@ -180,0 +220,0 @@ })

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

plugin = proxyquire('../src/plugins/pg', { 'pg': pg })
return agent.load(plugin, pg)
})

@@ -22,56 +20,83 @@

it('should do automatic instrumentation when using callbacks', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'postgres')
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')
expect(traces[0][0]).to.have.property('type', 'db')
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()
describe('without configuration', () => {
beforeEach(() => {
return agent.load(plugin, 'pg')
})
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
})
it('should do automatic instrumentation when using callbacks', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'postgres')
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')
expect(traces[0][0]).to.have.property('type', 'db')
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.connect((err) => {
if (err) throw err
done()
})
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres',
application_name: 'test'
})
client.connect((err) => {
if (err) throw err
client.end((err) => {
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
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 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')
done()
})
done()
})
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
})
client.connect((err) => {
if (err) throw err
client.query('INVALID', (err, result) => {
expect(err).to.be.an('error')
client.end((err) => {
if (err) throw err
})
})
})
})
client.connect((err) => {
if (err) throw err
it('should work without a callback', done => {
agent.use(traces => {
done()
})
client.query('INVALID', (err, result) => {
expect(err).to.be.an('error')
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
})
client.connect((err) => {
if (err) throw err
client.query('SELECT $1::text as message', ['Hello World!'])
client.end((err) => {

@@ -84,19 +109,36 @@ if (err) throw err

it('should work without a callback', done => {
agent.use(traces => {
done()
})
describe('with configuration', () => {
let config
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
beforeEach(() => {
config = {
service: 'custom'
}
return agent.load(plugin, 'pg', config)
})
client.connect((err) => {
if (err) throw err
it('should be configured with the correct values', done => {
agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'custom')
client.query('SELECT $1::text as message', ['Hello World!'])
client.end((err) => {
done()
})
const client = new pg.Client({
user: 'postgres',
password: 'postgres',
database: 'postgres'
})
client.connect((err) => {
if (err) throw err
client.query('SELECT $1::text as message', ['Hello world!'], (err, result) => {
if (err) throw err
client.end((err) => {
if (err) throw err
})
})
})

@@ -103,0 +145,0 @@ })

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

let noop
let Instrumenter
let instrumenter
let Config

@@ -17,2 +19,3 @@ let config

tracer = {
use: sinon.stub().returns('tracer'),
trace: sinon.stub().returns('span'),

@@ -28,2 +31,3 @@ startSpan: sinon.stub().returns('span'),

noop = {
use: sinon.stub().returns('tracer'),
trace: sinon.stub().returns('span'),

@@ -38,4 +42,10 @@ startSpan: sinon.stub().returns('span'),

instrumenter = {
patch: sinon.spy(),
use: sinon.spy()
}
DatadogTracer = sinon.stub().returns(tracer)
NoopTracer = sinon.stub().returns(noop)
Instrumenter = sinon.stub().returns(instrumenter)

@@ -52,2 +62,3 @@ config = {}

'./noop': NoopTracer,
'./instrumenter': Instrumenter,
'./config': Config,

@@ -60,2 +71,11 @@ './platform': platform

describe('use', () => {
it('should call the underlying instrumenter', () => {
const returnValue = proxy.use('a', 'b', 'c')
expect(instrumenter.use).to.have.been.calledWith('a', 'b', 'c')
expect(returnValue).to.equal(proxy)
})
})
describe('uninitialized', () => {

@@ -99,2 +119,14 @@ describe('init', () => {

})
it('should return a promise if a callback is not provided', () => {
const promise = proxy.trace('a', 'b')
expect(noop.trace).to.have.been.calledWith('a', 'b')
noop.trace.firstCall.args[2]('span')
return promise.then(span => {
expect(span).to.equal('span')
})
})
})

@@ -161,2 +193,16 @@

// it('should setup automatic instrumentation', () => {
// expect(Instrumenter).to.have.been.calledWith(tracer)
// expect(instrumenter.patch).to.have.been.called
// })
describe('use', () => {
it('should call the underlying Instrumenter', () => {
const returnValue = proxy.use('a', 'b', 'c')
expect(instrumenter.use).to.have.been.calledWith('a', 'b', 'c')
expect(returnValue).to.equal(proxy)
})
})
describe('trace', () => {

@@ -169,2 +215,14 @@ it('should call the underlying DatadogTracer', () => {

})
it('should return a promise if a callback is not provided', () => {
const promise = proxy.trace('a', 'b')
expect(tracer.trace).to.have.been.calledWith('a', 'b')
tracer.trace.firstCall.args[2]('span')
return promise.then(span => {
expect(span).to.equal('span')
})
})
})

@@ -171,0 +229,0 @@

@@ -10,4 +10,6 @@ 'use strict'

let recorder
let span
beforeEach(() => {
span = {}
scheduler = {

@@ -27,31 +29,56 @@ start: sinon.spy(),

})
recorder = new Recorder('http://test', 1000, 2)
})
describe('init', () => {
it('should schedule flushing after the configured interval', () => {
writer.length = 0
describe('when interval is set to a positive number', () => {
beforeEach(() => {
recorder = new Recorder('http://test', 1000, 2)
})
recorder.init()
Scheduler.firstCall.args[0]()
describe('init', () => {
it('should schedule flushing after the configured interval', () => {
writer.length = 0
expect(scheduler.start).to.have.been.called
expect(writer.flush).to.have.been.called
recorder.init()
Scheduler.firstCall.args[0]()
expect(scheduler.start).to.have.been.called
expect(writer.flush).to.have.been.called
})
})
describe('record', () => {
beforeEach(() => {
span = {}
})
it('should record a span', () => {
writer.length = 0
recorder.record(span)
expect(writer.append).to.have.been.calledWith(span)
})
})
})
describe('record', () => {
let span
describe('when interval is set to 0', () => {
beforeEach(() => {
span = {}
recorder = new Recorder('http://test', 0)
})
it('should record a span', () => {
writer.length = 0
describe('init', () => {
it('should not schedule flushing', () => {
writer.length = 0
recorder.init()
expect(scheduler.start).to.not.have.been.called
})
})
it('should flush right away when interval is set to 0', () => {
recorder.record(span)
expect(writer.append).to.have.been.calledWith(span)
expect(writer.flush).to.have.been.called
})
})
})

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

instrumenter = {
use: sinon.spy(),
patch: sinon.spy()

@@ -38,9 +39,2 @@ }

it('should setup automatic instrumentation', () => {
tracer = new Tracer(config)
expect(Instrumenter).to.have.been.calledWith(tracer)
expect(instrumenter.patch).to.have.been.called
})
describe('trace', () => {

@@ -47,0 +41,0 @@ it('should run the callback with the new span', done => {

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