🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

dd-trace

Package Overview
Dependencies
Maintainers
3
Versions
639
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

to
0.5.0

3

CONTRIBUTING.md
# Contributing to dd-trace-js
As an open source project we welcome contributions of many forms, but due to the experimental pre-beta nature
of this repository, you should reach out before starting work on any major code changes.
Please reach out before starting work on any major code changes.
This will ensure we avoid duplicating work, or that your code can't be merged due to a rapidly changing

@@ -6,0 +5,0 @@ base. If you would like support for a module that is not listed, [contact support][1] to share a request.

@@ -194,2 +194,3 @@ <h1 id="home">Datadog JavaScript Tracer API</h1>

| service | http-client | The service name for this integration. |
| splitByDomain | false | Use the remote endpoint host as the service name instead of the default. |

@@ -196,0 +197,0 @@ <h3 id="mongodb-core">mongodb-core</h3>

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

module.exports = '0.4.0'
module.exports = '0.5.0'
{
"name": "dd-trace",
"version": "0.4.0",
"description": "Datadog APM tracing client for JavaScript (experimental)",
"version": "0.5.0",
"description": "Datadog APM tracing client for JavaScript",
"main": "index.js",

@@ -6,0 +6,0 @@ "scripts": {

@@ -6,5 +6,5 @@ # dd-trace-js

**JavaScript APM Tracer (beta)**
**JavaScript APM Tracer**
This project is in open beta and under active development. Please contact [Datadog support](https://docs.datadoghq.com/help) with any questions.
Datadog APM tracing client for JavaScript.

@@ -11,0 +11,0 @@ ## Getting Started

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

const debug = coalesce(options.debug, platform.env('DD_TRACE_DEBUG'), false)
const service = coalesce(options.service, platform.env('DD_SERVICE_NAME'), platform.service())
const service = coalesce(options.service, platform.env('DD_SERVICE_NAME'), platform.service(), 'node')
const env = coalesce(options.env, platform.env('DD_ENV'))

@@ -16,0 +16,0 @@ const protocol = 'http'

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

_finish (finishTime) {
if (this._duration !== undefined) {
return
}
finishTime = parseFloat(finishTime) || platform.now()

@@ -85,0 +89,0 @@

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

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

@@ -24,0 +25,0 @@ this._service = pkg.name

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

addTags(this, config, span, 'basic.deliver', fields)
addTags(this, tracer, config, span, 'basic.deliver', fields)

@@ -50,3 +50,3 @@ setImmediate(() => {

addTags(channel, config, span, method, fields)
addTags(channel, tracer, config, span, method, fields)

@@ -87,3 +87,3 @@ try {

function addTags (channel, config, span, method, fields) {
function addTags (channel, tracer, config, span, method, fields) {
const fieldNames = [

@@ -99,3 +99,3 @@ 'queue',

span.addTags({
'service.name': config.service || 'amqp',
'service.name': config.service || `${tracer._service}-amqp`,
'resource.name': getResourceName(method, fields),

@@ -102,0 +102,0 @@ 'span.type': 'worker'

@@ -14,5 +14,5 @@ 'use strict'

[Tags.DB_TYPE]: 'elasticsearch',
'service.name': config.service || 'elasticsearch',
'service.name': config.service || `${tracer._service}-elasticsearch`,
'resource.name': `${params.method} ${quantizePath(params.path)}`,
'span.type': 'db',
'span.type': 'elasticsearch',
'elasticsearch.url': params.path,

@@ -19,0 +19,0 @@ 'elasticsearch.method': params.method,

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

const returned = originalEnd.apply(this, arguments)
const paths = scope.span().context()._express_paths
const paths = req._datadog_paths

@@ -45,3 +45,3 @@ if (paths) {

span.setTag('service.name', config.service || tracer._service)
span.setTag('span.type', 'web')
span.setTag('span.type', 'http')
span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode)

@@ -82,4 +82,3 @@

if (matchers && scope) {
const context = scope.span().context()
const paths = context._express_paths || []
const paths = req._datadog_paths || []

@@ -89,3 +88,3 @@ // Try to guess which path actually matched

if (matchers[i].test(layer.path)) {
context._express_paths = paths.concat(matchers[i].path)
req._datadog_paths = paths.concat(matchers[i].path)

@@ -137,3 +136,3 @@ break

if (scope) {
const paths = scope.span().context()._express_paths
const paths = req._datadog_paths

@@ -140,0 +139,0 @@ if (paths && layer.path && !layer.regexp.fast_star) {

@@ -24,8 +24,12 @@ 'use strict'

options = typeof options === 'string' ? url.parse(uri) : Object.assign({}, options)
options.headers = options.headers || {}
const parentScope = tracer.scopeManager().active()
const parent = parentScope && parentScope.span()
const span = tracer.startSpan('http.request', {
childOf: parentScope && parentScope.span(),
childOf: parent,
tags: {
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT,
'service.name': config.service || 'http-client',
'service.name': getServiceName(tracer, config, options),
'resource.name': method,

@@ -38,5 +42,2 @@ 'span.type': 'web',

options = typeof options === 'string' ? url.parse(uri) : Object.assign({}, options)
options.headers = options.headers || {}
tracer.inject(span, FORMAT_HTTP_HEADERS, options.headers)

@@ -88,2 +89,23 @@

function getHost (options) {
if (typeof options === 'string') {
return url.parse(options).host
}
const hostname = options.hostname || options.host || 'localhost'
const port = options.port
return [hostname, port].filter(val => val).join(':')
}
function getServiceName (tracer, config, options) {
if (config.splitByDomain) {
return getHost(options)
} else if (config.service) {
return config.service
}
return `${tracer._service}-http-client`
}
function unpatch (http) {

@@ -94,6 +116,13 @@ this.unwrap(http, 'request')

module.exports = {
name: 'http',
patch,
unpatch
}
module.exports = [
{
name: 'http',
patch,
unpatch
},
{
name: 'https',
patch,
unpatch
}
]

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

addTags(span, config, resource, ns, this)
addTags(span, tracer, config, resource, ns, this)

@@ -218,3 +218,3 @@ if (typeof options === 'function') {

addTags(span, config, resource, this.ns, this.topology)
addTags(span, tracer, config, resource, this.ns, this.topology)

@@ -232,7 +232,7 @@ if (this.cursorState) {

function addTags (span, config, resource, ns, topology) {
function addTags (span, tracer, config, resource, ns, topology) {
span.addTags({
'service.name': config.service || 'mongodb',
'service.name': config.service || `${tracer._service}-mongodb`,
'resource.name': resource,
'span.type': 'db',
'span.type': 'mongodb',
'db.name': ns

@@ -239,0 +239,0 @@ })

@@ -9,7 +9,8 @@ 'use strict'

const parentScope = tracer.scopeManager().active()
const parent = parentScope && parentScope.span()
const span = tracer.startSpan('mysql.query', {
childOf: parentScope && parentScope.span(),
childOf: parent,
tags: {
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT,
'service.name': config.service || 'mysql',
'service.name': config.service || `${tracer._service}-mysql`,
'span.type': 'sql',

@@ -32,3 +33,3 @@ 'db.type': 'mysql',

if (sequence._callback) {
sequence._callback = wrapCallback(tracer, span, sequence._callback)
sequence._callback = wrapCallback(tracer, span, parent, sequence._callback)
} else {

@@ -45,3 +46,3 @@ sequence.on('end', () => {

function wrapCallback (tracer, span, done) {
function wrapCallback (tracer, span, parent, done) {
return (err, res) => {

@@ -58,2 +59,6 @@ if (err) {

if (parent) {
tracer.scopeManager().activate(parent)
}
done(err, res)

@@ -60,0 +65,0 @@ }

@@ -9,7 +9,8 @@ 'use strict'

const parentScope = tracer.scopeManager().active()
const parent = parentScope && parentScope.span()
const span = tracer.startSpan('mysql.query', {
childOf: parentScope && parentScope.span(),
childOf: parent,
tags: {
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT,
'service.name': config.service || 'mysql',
'service.name': config.service || `${tracer._service}-mysql`,
'span.type': 'sql',

@@ -32,3 +33,3 @@ 'db.type': 'mysql',

if (sequence.onResult) {
sequence.onResult = wrapCallback(span, sequence.onResult)
sequence.onResult = wrapCallback(tracer, span, parent, sequence.onResult)
} else {

@@ -45,3 +46,3 @@ sequence.on('end', () => {

function wrapCallback (span, done) {
function wrapCallback (tracer, span, parent, done) {
return (err, res) => {

@@ -58,2 +59,6 @@ if (err) {

if (parent) {
tracer.scopeManager().activate(parent)
}
done(err, res)

@@ -60,0 +65,0 @@ }

@@ -16,7 +16,8 @@ 'use strict'

const parentScope = tracer.scopeManager().active()
const parent = parentScope && parentScope.span()
const span = tracer.startSpan(OPERATION_NAME, {
childOf: parentScope && parentScope.span(),
childOf: parent,
tags: {
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT,
'service.name': config.service || 'postgres',
'service.name': config.service || `${tracer._service}-postgres`,
'resource.name': statement,

@@ -49,2 +50,6 @@ 'span.type': 'sql',

if (originalCallback) {
if (parent) {
tracer.scopeManager().activate(parent)
}
originalCallback(err, res)

@@ -51,0 +56,0 @@ }

@@ -14,5 +14,5 @@ 'use strict'

[Tags.DB_TYPE]: 'redis',
'service.name': config.service || 'redis',
'service.name': config.service || `${tracer._service}-redis`,
'resource.name': options.command,
'span.type': 'db',
'span.type': 'redis',
'db.name': this.selected_db || '0'

@@ -19,0 +19,0 @@ }

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

this._count = 0
this._exited = false
this._set = []

@@ -12,0 +11,0 @@

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

const singleton = null
let singleton = null

@@ -22,3 +22,4 @@ /**

const id = -1
singleton = this
const execution = new ContextExecution()

@@ -29,3 +30,3 @@

this._contexts = new Map()
this._executions = new Map([[ id, execution ]])
this._executions = new Map()

@@ -32,0 +33,0 @@ this._hook = asyncHooks.createHook({

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

}
platform.service.returns('test')

@@ -23,3 +22,3 @@ Config = proxyquire('../src/config', {

expect(config).to.have.property('service', 'test')
expect(config).to.have.property('service', 'node')
expect(config).to.have.property('enabled', true)

@@ -38,2 +37,10 @@ expect(config).to.have.property('debug', false)

it('should initialize from the platform', () => {
platform.service.returns('test')
const config = new Config()
expect(config).to.have.property('service', 'test')
})
it('should initialize from environment variables', () => {

@@ -40,0 +47,0 @@ platform.env.withArgs('DD_TRACE_AGENT_HOSTNAME').returns('agent')

@@ -153,3 +153,13 @@ 'use strict'

})
it('should not record the span if already finished', () => {
tracer._record.returns(Promise.resolve())
span = new Span(tracer, { operationName: 'operation' })
span.finish()
span.finish()
expect(tracer._record).to.have.been.calledOnce
})
})
})

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

tracer._instrumenter.unpatch()
tracer.scopeManager()._disable()
tracer = null

@@ -55,0 +54,0 @@ })

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

expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'amqp')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.declare test')

@@ -72,3 +72,3 @@ expect(span).to.have.property('type', 'worker')

expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'amqp')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'queue.delete test')

@@ -116,3 +116,3 @@ expect(span).to.have.property('type', 'worker')

expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'amqp')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', 'basic.publish exchange routingKey')

@@ -165,3 +165,3 @@ expect(span).to.have.property('type', 'worker')

expect(span).to.have.property('name', 'amqp.command')
expect(span).to.have.property('service', 'amqp')
expect(span).to.have.property('service', 'test-amqp')
expect(span).to.have.property('resource', `basic.deliver ${queue}`)

@@ -168,0 +168,0 @@ expect(span).to.have.property('type', 'worker')

@@ -86,5 +86,5 @@ 'use strict'

.use(traces => {
expect(traces[0][0]).to.have.property('service', 'elasticsearch')
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', 'db')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
})

@@ -146,5 +146,5 @@ .then(done)

.use(traces => {
expect(traces[0][0]).to.have.property('service', 'elasticsearch')
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', 'db')
expect(traces[0][0]).to.have.property('type', 'elasticsearch')
})

@@ -151,0 +151,0 @@ .then(done)

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

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('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /user')

@@ -78,3 +78,3 @@ expect(traces[0][0].meta).to.have.property('span.kind', 'server')

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('type', 'http')
expect(traces[0][0]).to.have.property('resource', 'GET /app/user/:id')

@@ -234,2 +234,41 @@ expect(traces[0][0].meta).to.have.property('span.kind', 'server')

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()
const child = tracer.startSpan('child', {
childOf: scope.span()
})
tracer.scopeManager().activate(child)
child.finish()
next()
})
router.get('/user/:id', (req, res) => {
res.status(200).send()
})
app.use('/app', router)
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 fallback to the the verb if a path pattern could not be found', done => {

@@ -236,0 +275,0 @@ const app = express()

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

.use(traces => {
expect(traces[0][0]).to.have.property('service', 'http-client')
expect(traces[0][0]).to.have.property('service', 'test-http-client')
expect(traces[0][0]).to.have.property('type', 'web')

@@ -238,3 +238,3 @@ expect(traces[0][0]).to.have.property('resource', 'GET')

describe('with configuration', () => {
describe('with service configuration', () => {
let config

@@ -279,3 +279,44 @@

})
describe('with splitByDomain configuration', () => {
let config
beforeEach(() => {
config = {
splitByDomain: true
}
return agent.load(plugin, 'http', config)
.then(() => {
http = require('http')
express = require('express')
})
})
it('should use the remote endpoint as the 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', `localhost:${port}`)
})
.then(done)
.catch(done)
appListener = app.listen(port, 'localhost', () => {
const req = http.request(`http://localhost:${port}/user`, res => {
res.on('data', () => {})
})
req.end()
})
})
})
})
})
})

@@ -57,5 +57,5 @@ 'use strict'

expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'mongodb')
expect(span).to.have.property('service', 'test-mongodb')
expect(span).to.have.property('resource', resource)
expect(span).to.have.property('type', 'db')
expect(span).to.have.property('type', 'mongodb')
expect(span.meta).to.have.property('db.name', `test.${collection}`)

@@ -158,4 +158,4 @@ expect(span.meta).to.have.property('out.host', 'localhost')

expect(span).to.have.property('name', 'mongodb.query')
expect(span).to.have.property('service', 'mongodb')
expect(span).to.have.property('type', 'db')
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}`)

@@ -162,0 +162,0 @@ expect(span.meta).to.have.property('out.host', 'localhost')

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

const active = tracer.scopeManager().active()
scope.close()
expect(active).to.equal(scope)
expect(active.span()).to.equal(scope.span())
done()

@@ -78,3 +77,3 @@ })

agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'mysql')
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')

@@ -181,3 +180,3 @@ expect(traces[0][0]).to.have.property('type', 'sql')

agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'mysql')
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')

@@ -184,0 +183,0 @@ expect(traces[0][0]).to.have.property('type', 'sql')

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

const active = tracer.scopeManager().active()
scope.close()
expect(active).to.equal(scope)
expect(active.span()).to.equal(scope.span())
done()

@@ -79,3 +78,3 @@ })

.use(traces => {
expect(traces[0][0]).to.have.property('service', 'mysql')
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')

@@ -187,3 +186,3 @@ expect(traces[0][0]).to.have.property('type', 'sql')

.use(traces => {
expect(traces[0][0]).to.have.property('service', 'mysql')
expect(traces[0][0]).to.have.property('service', 'test-mysql')
expect(traces[0][0]).to.have.property('resource', 'SELECT 1 + 1 AS solution')

@@ -190,0 +189,0 @@ expect(traces[0][0]).to.have.property('type', 'sql')

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

describe('without configuration', () => {
describe('when using a client', () => {
beforeEach(done => {

@@ -44,3 +44,3 @@ agent.load(plugin, 'pg')

agent.use(traces => {
expect(traces[0][0]).to.have.property('service', 'postgres')
expect(traces[0][0]).to.have.property('service', 'test-postgres')
expect(traces[0][0]).to.have.property('resource', 'SELECT $1::text as message')

@@ -84,4 +84,8 @@ expect(traces[0][0]).to.have.property('type', 'sql')

it('should run the callback in the parent context', done => {
const span = {}
const scope = tracer.scopeManager().activate(span)
client.query('SELECT $1::text as message', ['Hello World!'], () => {
expect(tracer.scopeManager().active()).to.be.null
const active = tracer.scopeManager().active()
expect(active.span()).to.equal(scope.span())
done()

@@ -107,2 +111,45 @@ })

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

@@ -109,0 +156,0 @@ let config

@@ -40,5 +40,5 @@ 'use strict'

expect(traces[0][0]).to.have.property('name', 'redis.command')
expect(traces[0][0]).to.have.property('service', 'redis')
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', 'db')
expect(traces[0][0]).to.have.property('type', 'redis')
expect(traces[0][0].meta).to.have.property('db.name', '0')

@@ -45,0 +45,0 @@ expect(traces[0][0].meta).to.have.property('db.type', 'redis')

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

afterEach(() => {
scopeManager._disable()
it('should be a singleton', () => {
expect(new ScopeManager()).to.equal(scopeManager)
})

@@ -38,0 +38,0 @@

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

const node = require('../src/platform/node')
const ScopeManager = require('../src/scope/scope_manager')
const scopeManager = new ScopeManager()
const retryOptions = {

@@ -37,2 +40,6 @@ retries: 60,

after(() => {
scopeManager._disable()
})
waitForServices()

@@ -190,4 +197,42 @@ .then(run)

function withoutScope (fn) {
return function () {
let active
while ((active = scopeManager.active())) {
active.close()
}
return fn.apply(this, arguments)
}
}
function wrapIt () {
// placeholder
const it = global.it
global.it = function (title, fn) {
if (!fn) {
return it.apply(this, arguments)
}
if (fn.length > 0) {
return it.call(this, title, function (done) {
arguments[0] = withoutScope(done)
return fn.apply(this, arguments)
})
} else {
return it.call(this, title, function () {
const result = fn.apply(this, arguments)
if (result && result.then) {
return result
.then(withoutScope(res => res))
.catch(withoutScope(err => Promise.reject(err)))
}
return result
})
}
}
}

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

afterEach(() => {
tracer.scopeManager()._disable()
})
describe('trace', () => {

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