Comparing version 0.8.0-beta.0 to 0.8.0-beta.1
@@ -10,2 +10,3 @@ 'use strict' | ||
SAMPLING_PRIORITY: 'sampling.priority', | ||
EVENT_SAMPLE_RATE: '_dd1.sr.eausr', | ||
ERROR: 'error', | ||
@@ -12,0 +13,0 @@ |
@@ -1,1 +0,1 @@ | ||
module.exports = '0.8.0-beta.0' | ||
module.exports = '0.8.0-beta.1' |
{ | ||
"name": "dd-trace", | ||
"version": "0.8.0-beta.0", | ||
"version": "0.8.0-beta.1", | ||
"description": "Datadog APM tracing client for JavaScript", | ||
@@ -41,2 +41,3 @@ "main": "index.js", | ||
"async-hook-jl": "^1.7.6", | ||
"emitter-listener": "^1.1.2", | ||
"int64-buffer": "^0.1.9", | ||
@@ -43,0 +44,0 @@ "koalas": "^1.0.2", |
@@ -14,3 +14,3 @@ # dd-trace-js | ||
For a basic product overview, check out our [setup documentation](https://docs.datadoghq.com/tracing/setup/javascript/). | ||
For a basic product overview, check out our [setup documentation](https://docs.datadoghq.com/tracing/languages/nodejs/). | ||
@@ -17,0 +17,0 @@ For installation, configuration, and details about using the API, check out our [API documentation](https://datadog.github.io/dd-trace-js). |
@@ -5,3 +5,4 @@ 'use strict' | ||
SAMPLE_RATE_METRIC_KEY: '_sample_rate', | ||
SAMPLING_PRIORITY_KEY: '_sampling_priority_v1' | ||
SAMPLING_PRIORITY_KEY: '_sampling_priority_v1', | ||
EVENT_SAMPLE_RATE_KEY: '_dd1.sr.eausr' | ||
} |
@@ -5,4 +5,7 @@ 'use strict' | ||
const constants = require('./constants') | ||
const tags = require('../ext/tags') | ||
const SAMPLING_PRIORITY_KEY = constants.SAMPLING_PRIORITY_KEY | ||
const EVENT_SAMPLE_RATE_KEY = constants.EVENT_SAMPLE_RATE_KEY | ||
const EVENT_SAMPLE_RATE = tags.EVENT_SAMPLE_RATE | ||
@@ -63,2 +66,4 @@ const map = { | ||
break | ||
case EVENT_SAMPLE_RATE: | ||
break | ||
default: | ||
@@ -82,2 +87,3 @@ trace.meta[tag] = String(tags[tag]) | ||
const spanContext = span.context() | ||
const eventSampleRate = parseFloat(spanContext._tags[EVENT_SAMPLE_RATE]) | ||
@@ -93,4 +99,8 @@ Object.keys(spanContext._metrics).forEach(metric => { | ||
} | ||
if (eventSampleRate >= 0 && eventSampleRate <= 1) { | ||
trace.metrics[EVENT_SAMPLE_RATE_KEY] = eventSampleRate | ||
} | ||
} | ||
module.exports = format |
@@ -82,6 +82,11 @@ 'use strict' | ||
} | ||
Object.defineProperty(nodule[name], '_datadog_patched', { | ||
value: true, | ||
configurable: true | ||
}) | ||
}) | ||
}) | ||
return shimmer.massWrap.call(this, nodules, names, wrapper) | ||
shimmer.massWrap.call(this, nodules, names, wrapper) | ||
} | ||
@@ -93,3 +98,9 @@ | ||
return shimmer.massUnwrap.call(this, nodules, names, wrapper) | ||
shimmer.massUnwrap.call(this, nodules, names, wrapper) | ||
nodules.forEach(nodule => { | ||
names.forEach(name => { | ||
nodule[name] && delete nodule[name]._datadog_patched | ||
}) | ||
}) | ||
} | ||
@@ -114,3 +125,3 @@ | ||
)) | ||
.forEach(plugin => this._validate(plugin, moduleBaseDir)) | ||
.forEach(plugin => this._validate(plugin, moduleBaseDir, moduleVersion)) | ||
@@ -145,3 +156,3 @@ this._plugins | ||
_validate (plugin, moduleBaseDir) { | ||
_validate (plugin, moduleBaseDir, moduleVersion) { | ||
const meta = this._plugins.get(plugin) | ||
@@ -151,2 +162,3 @@ const instrumentations = [].concat(plugin) | ||
for (let i = 0; i < instrumentations.length; i++) { | ||
if (instrumentations[i].versions && !matchVersion(moduleVersion, instrumentations[i].versions)) continue | ||
if (instrumentations[i].file && !exists(moduleBaseDir, instrumentations[i].file)) { | ||
@@ -153,0 +165,0 @@ this._fail(plugin) |
'use strict' | ||
const memoize = require('lodash.memoize') | ||
const _default = { | ||
@@ -8,6 +10,7 @@ debug: message => console.log(message), /* eslint-disable-line no-console */ | ||
let _logger = _default | ||
let _enabled = false | ||
let _logger | ||
let _enabled | ||
let _deprecate | ||
module.exports = { | ||
const log = { | ||
use (logger) { | ||
@@ -30,2 +33,6 @@ if (logger && logger.debug instanceof Function && logger.error instanceof Function) { | ||
_enabled = false | ||
_deprecate = memoize((code, message) => { | ||
_logger.error(message) | ||
return this | ||
}) | ||
@@ -53,3 +60,11 @@ return this | ||
return this | ||
}, | ||
deprecate (code, message) { | ||
return _deprecate(code, message) | ||
} | ||
} | ||
log.reset() | ||
module.exports = log |
@@ -10,10 +10,14 @@ 'use strict' | ||
let ScopeManager | ||
let Scope | ||
if (process.env.DD_CONTEXT_PROPAGATION === 'false') { | ||
ScopeManager = require('./scope/noop/scope_manager') | ||
Scope = require('./scope/new/base') | ||
} else { | ||
ScopeManager = require('./scope/scope_manager') | ||
Scope = require('./scope/new/scope') | ||
} | ||
this._scopeManager = new ScopeManager() | ||
this._scope = new Scope() | ||
} | ||
@@ -20,0 +24,0 @@ |
@@ -9,3 +9,5 @@ 'use strict' | ||
try { | ||
const promise = send.apply(this, arguments) | ||
const promise = tracer.scope().activate(span, () => { | ||
return send.apply(this, arguments) | ||
}) | ||
@@ -30,12 +32,5 @@ return wrapPromise(promise, span) | ||
process.nextTick(() => { | ||
const scope = tracer.scopeManager().activate(span, true) | ||
try { | ||
messageReceived.apply(this, arguments) | ||
} finally { | ||
if (process.env.DD_CONTEXT_PROPAGATION === 'false') { | ||
scope.close() | ||
} | ||
} | ||
return tracer.scope().activate(span, () => { | ||
messageReceived.apply(this, arguments) | ||
span.finish() | ||
}) | ||
@@ -42,0 +37,0 @@ } |
@@ -30,5 +30,3 @@ 'use strict' | ||
setImmediate(() => { | ||
const scope = tracer.scopeManager().activate(span, true) | ||
tracer.scope().activate(span, () => { | ||
try { | ||
@@ -39,5 +37,3 @@ dispatchMessage.apply(this, arguments) | ||
} finally { | ||
if (process.env.DD_CONTEXT_PROPAGATION === 'false') { | ||
scope.close() | ||
} | ||
span.finish() | ||
} | ||
@@ -50,16 +46,16 @@ }) | ||
function sendWithTrace (send, channel, args, tracer, config, method, fields) { | ||
const parentScope = tracer.scopeManager().active() | ||
const span = tracer.startSpan('amqp.command', { | ||
childOf: parentScope && parentScope.span() | ||
}) | ||
const childOf = tracer.scopeManager().active() | ||
const span = tracer.startSpan('amqp.command', { childOf }) | ||
addTags(channel, tracer, config, span, method, fields) | ||
try { | ||
return send.apply(channel, args) | ||
} catch (e) { | ||
throw addError(span, e) | ||
} finally { | ||
span.finish() | ||
} | ||
return tracer.scope().activate(span, () => { | ||
try { | ||
return send.apply(channel, args) | ||
} catch (e) { | ||
throw addError(span, e) | ||
} finally { | ||
span.finish() | ||
} | ||
}) | ||
} | ||
@@ -66,0 +62,0 @@ |
@@ -8,5 +8,5 @@ 'use strict' | ||
return function requestWithTrace (params, cb) { | ||
const scope = tracer.scopeManager().active() | ||
const childOf = tracer.scope().active() | ||
const span = tracer.startSpan('elasticsearch.query', { | ||
childOf: scope && scope.span(), | ||
childOf, | ||
tags: { | ||
@@ -28,11 +28,15 @@ [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
if (typeof cb === 'function') { | ||
return request.call(this, params, wrapCallback(tracer, span, cb)) | ||
} else { | ||
const promise = request.apply(this, arguments) | ||
cb = tracer.scope().bind(cb, childOf) | ||
promise.then(() => finish(span), e => finish(span, e)) | ||
return tracer.scope().activate(span, () => { | ||
if (typeof cb === 'function') { | ||
return request.call(this, params, wrapCallback(tracer, span, cb)) | ||
} else { | ||
const promise = request.apply(this, arguments) | ||
return promise | ||
} | ||
promise.then(() => finish(span), e => finish(span, e)) | ||
return promise | ||
} | ||
}) | ||
} | ||
@@ -39,0 +43,0 @@ } |
@@ -112,7 +112,7 @@ 'use strict' | ||
const fieldParent = getFieldParent(operation, path) | ||
const scope = tracer.scopeManager().activate(fieldParent) | ||
return call(resolve, this, arguments, () => { | ||
scope.close() | ||
updateFinishTime(operation, path) | ||
return tracer.scope().activate(fieldParent, () => { | ||
return call(resolve, this, arguments, () => { | ||
updateFinishTime(operation, path) | ||
}) | ||
}) | ||
@@ -122,5 +122,6 @@ } | ||
const field = assertField(tracer, config, operation, path, info) | ||
const scope = tracer.scopeManager().activate(field.resolveSpan) | ||
return call(resolve, this, arguments, err => finish(scope, operation, path, err)) | ||
return tracer.scope().activate(field.resolveSpan, () => { | ||
return call(resolve, this, arguments, err => finish(field.resolveSpan, operation, path, err)) | ||
}) | ||
} | ||
@@ -258,3 +259,3 @@ | ||
const def = document.definitions.find(def => def.kind === 'OperationDefinition') | ||
const parentScope = tracer.scopeManager().active() | ||
const childOf = tracer.scope().active() | ||
const tags = { | ||
@@ -287,3 +288,3 @@ 'service.name': getService(tracer, config), | ||
startTime, | ||
childOf: parentScope && parentScope.span() | ||
childOf | ||
}) | ||
@@ -338,3 +339,3 @@ | ||
function finish (scope, operation, path, error) { | ||
function finish (span, operation, path, error) { | ||
const field = getField(operation, path) | ||
@@ -348,8 +349,5 @@ | ||
const span = scope.span() | ||
addError(span, error) | ||
span.finish() | ||
scope.close() | ||
@@ -356,0 +354,0 @@ updateFinishTime(operation, path) |
@@ -6,14 +6,8 @@ 'use strict' | ||
function createWrapGenerate (tracer, config) { | ||
config = web.normalizeConfig(config) | ||
return function wrapGenerate (generate) { | ||
return function generateWithTrace (server, req, res, options) { | ||
let request | ||
const request = generate.apply(this, arguments) | ||
web.instrument(tracer, config, req, res, 'hapi.request', () => { | ||
request = generate.apply(this, arguments) | ||
web.beforeEnd(req, () => { | ||
web.enterRoute(req, request.route.path) | ||
}) | ||
web.beforeEnd(req, () => { | ||
web.enterRoute(req, request.route.path) | ||
}) | ||
@@ -32,15 +26,24 @@ | ||
const req = this.raw.req | ||
const res = this.raw.res | ||
let returnValue | ||
web.beforeEnd(req, () => { | ||
web.enterRoute(req, this.route.path) | ||
}) | ||
web.instrument(tracer, config, req, res, 'hapi.request', () => { | ||
returnValue = execute.apply(this, arguments) | ||
return execute.apply(this, arguments) | ||
} | ||
} | ||
} | ||
web.beforeEnd(req, () => { | ||
web.enterRoute(req, this.route.path) | ||
function createWrapDispatch (tracer, config) { | ||
config = web.normalizeConfig(config) | ||
return function wrapDispatch (dispatch) { | ||
return function dispatchWithTrace (options) { | ||
const handler = dispatch.apply(this, arguments) | ||
return function (req, res) { | ||
return web.instrument(tracer, config, req, res, 'hapi.request', () => { | ||
return handler.apply(this, arguments) | ||
}) | ||
}) | ||
return returnValue | ||
} | ||
} | ||
@@ -83,3 +86,36 @@ } | ||
} | ||
}, | ||
{ | ||
name: 'hapi', | ||
versions: ['7.2 - 16'], | ||
file: 'lib/connection.js', | ||
patch (Connection, tracer, config) { | ||
this.wrap(Connection.prototype, '_dispatch', createWrapDispatch(tracer, config)) | ||
}, | ||
unpatch (Connection) { | ||
this.unwrap(Connection.prototype, '_dispatch') | ||
} | ||
}, | ||
{ | ||
name: 'hapi', | ||
versions: ['17'], | ||
file: 'lib/core.js', | ||
patch (Core, tracer, config) { | ||
this.wrap(Core.prototype, '_dispatch', createWrapDispatch(tracer, config)) | ||
}, | ||
unpatch (Core) { | ||
this.unwrap(Core.prototype, '_dispatch') | ||
} | ||
}, | ||
{ | ||
name: 'hapi', | ||
versions: ['2 - 7.1'], | ||
file: 'lib/server.js', | ||
patch (Server, tracer, config) { | ||
this.wrap(Server.prototype, '_dispatch', createWrapDispatch(tracer, config)) | ||
}, | ||
unpatch (Server) { | ||
this.unwrap(Server.prototype, '_dispatch') | ||
} | ||
} | ||
] |
@@ -20,4 +20,5 @@ 'use strict' | ||
const options = args.options | ||
const callback = args.callback | ||
let callback = args.callback | ||
if (!config.filter(uri)) { | ||
@@ -29,6 +30,6 @@ return request.call(this, options, callback) | ||
const parentScope = tracer.scopeManager().active() | ||
const parent = parentScope && parentScope.span() | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('http.request', { | ||
childOf: parent, | ||
childOf, | ||
tags: { | ||
@@ -48,12 +49,7 @@ [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
const req = request.call(this, options, callback) | ||
callback = scope.bind(callback, childOf) | ||
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()) | ||
} | ||
}) | ||
const req = scope.bind(request, span).call(this, options, function (res) { | ||
scope.bind(res) | ||
req.on('response', res => { | ||
span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode) | ||
@@ -66,4 +62,15 @@ | ||
res.on('end', () => span.finish()) | ||
return callback && callback.apply(this, arguments) | ||
}) | ||
scope.bind(req) | ||
req.on('socket', () => { | ||
// empty the data stream when no other listener exists to consume it | ||
if (!callback && req.listenerCount('response') === 1) { | ||
req.on('response', res => res.resume()) | ||
} | ||
}) | ||
req.on('error', err => { | ||
@@ -70,0 +77,0 @@ span.addTags({ |
@@ -11,3 +11,5 @@ 'use strict' | ||
if (eventName === 'request') { | ||
web.instrument(tracer, config, req, res, 'http.request') | ||
return web.instrument(tracer, config, req, res, 'http.request', () => { | ||
return emit.apply(this, arguments) | ||
}) | ||
} | ||
@@ -14,0 +16,0 @@ |
@@ -7,2 +7,4 @@ 'use strict' | ||
'bluebird': require('./bluebird'), | ||
'bunyan': require('./bunyan'), | ||
'dns': require('./dns'), | ||
'elasticsearch': require('./elasticsearch'), | ||
@@ -19,2 +21,3 @@ 'express': require('./express'), | ||
'mysql2': require('./mysql2'), | ||
'net': require('./net'), | ||
'pg': require('./pg'), | ||
@@ -24,3 +27,4 @@ 'q': require('./q'), | ||
'restify': require('./restify'), | ||
'when': require('./when') | ||
'when': require('./when'), | ||
'winston': require('./winston') | ||
} |
@@ -14,3 +14,3 @@ 'use strict' | ||
return sendCommand.apply(this, arguments) | ||
return tracer.scope().bind(sendCommand, span).apply(this, arguments) | ||
} | ||
@@ -17,0 +17,0 @@ } |
@@ -25,4 +25,3 @@ 'use strict' | ||
this.middleware.push(function (ctx, next) { | ||
web.reactivate(ctx.req) | ||
return fn.apply(this, arguments) | ||
return web.reactivate(ctx.req, () => fn.apply(this, arguments)) | ||
}) | ||
@@ -29,0 +28,0 @@ |
@@ -6,5 +6,6 @@ 'use strict' | ||
return function commandWithTrace (queryCompiler, server) { | ||
const scope = tracer.scopeManager().active() | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('memcached.command', { | ||
childOf: scope && scope.span(), | ||
childOf, | ||
tags: { | ||
@@ -17,5 +18,5 @@ 'span.kind': 'client', | ||
queryCompiler = wrapQueryCompiler(queryCompiler, this, server, span) | ||
queryCompiler = wrapQueryCompiler(queryCompiler, this, server, scope, span) | ||
return command.call(this, queryCompiler, server) | ||
return scope.bind(command, span).call(this, queryCompiler, server) | ||
} | ||
@@ -25,3 +26,5 @@ } | ||
function wrapQueryCompiler (original, client, server, span) { | ||
function wrapQueryCompiler (original, client, server, scope, span) { | ||
const parent = scope.active() | ||
return function () { | ||
@@ -38,3 +41,3 @@ const query = original.apply(this, arguments) | ||
query.callback = function (err) { | ||
query.callback = scope.bind(function (err) { | ||
addError(span, err) | ||
@@ -45,3 +48,3 @@ | ||
return callback.apply(this, arguments) | ||
} | ||
}, parent) | ||
@@ -48,0 +51,0 @@ return query |
@@ -8,6 +8,5 @@ 'use strict' | ||
return function operationWithTrace (ns, ops, options, callback) { | ||
const parentScope = tracer.scopeManager().active() | ||
const span = tracer.startSpan('mongodb.query', { | ||
childOf: parentScope && parentScope.span() | ||
}) | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('mongodb.query', { childOf }) | ||
@@ -17,5 +16,9 @@ addTags(span, tracer, config, ns, ops, this, operationName) | ||
if (typeof options === 'function') { | ||
return operation.call(this, ns, ops, wrapCallback(tracer, span, options)) | ||
return scope | ||
.bind(operation, span) | ||
.call(this, ns, ops, wrapCallback(tracer, span, options)) | ||
} else { | ||
return operation.call(this, ns, ops, options, wrapCallback(tracer, span, callback)) | ||
return scope | ||
.bind(operation, span) | ||
.call(this, ns, ops, options, wrapCallback(tracer, span, callback)) | ||
} | ||
@@ -29,6 +32,5 @@ } | ||
return function nextWithTrace (cb) { | ||
const parentScope = tracer.scopeManager().active() | ||
const span = tracer.startSpan('mongodb.query', { | ||
childOf: parentScope && parentScope.span() | ||
}) | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('mongodb.query', { childOf }) | ||
@@ -43,3 +45,3 @@ addTags(span, tracer, config, this.ns, this.cmd, this.topology) | ||
next.call(this, wrapCallback(tracer, span, cb, this)) | ||
scope.bind(next, span).call(this, wrapCallback(tracer, span, cb, this)) | ||
} | ||
@@ -79,3 +81,3 @@ } | ||
function wrapCallback (tracer, span, done, cursor) { | ||
return (err, res) => { | ||
return tracer.scope().bind((err, res) => { | ||
if (err) { | ||
@@ -98,3 +100,3 @@ span.addTags({ | ||
} | ||
} | ||
}) | ||
} | ||
@@ -101,0 +103,0 @@ |
@@ -8,6 +8,6 @@ 'use strict' | ||
return function queryWithTrace (sql, values, cb) { | ||
const parentScope = tracer.scopeManager().active() | ||
const parent = parentScope && parentScope.span() | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('mysql.query', { | ||
childOf: parent, | ||
childOf, | ||
tags: { | ||
@@ -28,3 +28,3 @@ [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
const sequence = query.call(this, sql, values, cb) | ||
const sequence = scope.bind(query, span).call(this, sql, values, cb) | ||
@@ -34,3 +34,3 @@ span.setTag('resource.name', sequence.sql) | ||
if (sequence._callback) { | ||
sequence._callback = wrapCallback(tracer, span, parent, sequence._callback) | ||
sequence._callback = wrapCallback(tracer, span, childOf, sequence._callback) | ||
} else { | ||
@@ -48,3 +48,3 @@ sequence.on('end', () => { | ||
function wrapCallback (tracer, span, parent, done) { | ||
return (err, res) => { | ||
return tracer.scope().bind((err, res) => { | ||
if (err) { | ||
@@ -65,3 +65,3 @@ span.addTags({ | ||
done(err, res) | ||
} | ||
}, parent) | ||
} | ||
@@ -68,0 +68,0 @@ |
@@ -8,6 +8,6 @@ 'use strict' | ||
return function queryWithTrace (sql, values, cb) { | ||
const parentScope = tracer.scopeManager().active() | ||
const parent = parentScope && parentScope.span() | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan('mysql.query', { | ||
childOf: parent, | ||
childOf, | ||
tags: { | ||
@@ -28,3 +28,3 @@ [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
const sequence = query.call(this, sql, values, cb) | ||
const sequence = scope.bind(query, span).call(this, sql, values, cb) | ||
@@ -34,3 +34,3 @@ span.setTag('resource.name', sequence.sql) | ||
if (sequence.onResult) { | ||
sequence.onResult = wrapCallback(tracer, span, parent, sequence.onResult) | ||
sequence.onResult = wrapCallback(tracer, span, childOf, sequence.onResult) | ||
} else { | ||
@@ -48,3 +48,3 @@ sequence.on('end', () => { | ||
function wrapCallback (tracer, span, parent, done) { | ||
return (err, res) => { | ||
return tracer.scope().bind((err, res) => { | ||
if (err) { | ||
@@ -65,3 +65,3 @@ span.addTags({ | ||
done(err, res) | ||
} | ||
}) | ||
} | ||
@@ -68,0 +68,0 @@ |
@@ -10,3 +10,15 @@ 'use strict' | ||
return function queryTrace () { | ||
const retval = query.apply(this, arguments) | ||
const scope = tracer.scope() | ||
const childOf = scope.active() | ||
const span = tracer.startSpan(OPERATION_NAME, { | ||
childOf, | ||
tags: { | ||
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
'service.name': config.service || `${tracer._service}-postgres`, | ||
'span.type': 'sql', | ||
'db.type': 'postgres' | ||
} | ||
}) | ||
const retval = scope.bind(query, span).apply(this, arguments) | ||
const pgQuery = this.queryQueue[this.queryQueue.length - 1] || this.activeQuery | ||
@@ -22,14 +34,3 @@ | ||
const parentScope = tracer.scopeManager().active() | ||
const parent = parentScope && parentScope.span() | ||
const span = tracer.startSpan(OPERATION_NAME, { | ||
childOf: parent, | ||
tags: { | ||
[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, | ||
'service.name': config.service || `${tracer._service}-postgres`, | ||
'resource.name': statement, | ||
'span.type': 'sql', | ||
'db.type': 'postgres' | ||
} | ||
}) | ||
span.setTag('resource.name', statement) | ||
@@ -45,3 +46,3 @@ if (params) { | ||
pgQuery.callback = (err, res) => { | ||
pgQuery.callback = scope.bind((err, res) => { | ||
if (err) { | ||
@@ -58,9 +59,5 @@ span.addTags({ | ||
if (originalCallback) { | ||
if (parent) { | ||
tracer.scopeManager().activate(parent) | ||
} | ||
originalCallback(err, res) | ||
} | ||
} | ||
}, childOf) | ||
@@ -67,0 +64,0 @@ return retval |
@@ -8,7 +8,8 @@ 'use strict' | ||
return function internalSendCommandWithTrace (options) { | ||
const scope = tracer.scope() | ||
const span = startSpan(tracer, config, this, options.command, options.args) | ||
options.callback = tx.wrap(span, options.callback) | ||
options.callback = scope.bind(tx.wrap(span, options.callback)) | ||
return internalSendCommand.call(this, options) | ||
return scope.bind(internalSendCommand, span).call(this, options) | ||
} | ||
@@ -21,13 +22,14 @@ } | ||
return function sendCommandWithTrace (command, args, callback) { | ||
const scope = tracer.scope() | ||
const span = startSpan(tracer, config, this, command, args) | ||
if (callback) { | ||
callback = tx.wrap(span, callback) | ||
} else if (args) { | ||
args[(args.length || 1) - 1] = tx.wrap(span, args[args.length - 1]) | ||
if (typeof callback === 'function') { | ||
callback = scope.bind(tx.wrap(span, callback)) | ||
} else if (Array.isArray(args) && typeof args[args.length - 1] === 'function') { | ||
args[args.length - 1] = scope.bind(tx.wrap(span, args[args.length - 1])) | ||
} else { | ||
args = [tx.wrap(span)] | ||
callback = tx.wrap(span) | ||
} | ||
return sendCommand.call(this, command, args, callback) | ||
return scope.bind(sendCommand, span).call(this, command, args, callback) | ||
} | ||
@@ -34,0 +36,0 @@ } |
@@ -12,10 +12,11 @@ 'use strict' | ||
return function setupRequestWithTrace (req, res) { | ||
web.instrument(tracer, config, req, res, 'restify.request') | ||
web.beforeEnd(req, () => { | ||
if (req.route) { | ||
web.enterRoute(req, req.route.path) | ||
} | ||
return web.instrument(tracer, config, req, res, 'restify.request', () => { | ||
web.beforeEnd(req, () => { | ||
if (req.route) { | ||
web.enterRoute(req, req.route.path) | ||
} | ||
}) | ||
return setupRequest.apply(this, arguments) | ||
}) | ||
return setupRequest.apply(this, arguments) | ||
} | ||
@@ -49,4 +50,3 @@ } | ||
return function (req, res, next) { | ||
web.reactivate(req) | ||
return fn.apply(this, arguments) | ||
return web.reactivate(req, () => fn.apply(this, arguments)) | ||
} | ||
@@ -53,0 +53,0 @@ } |
@@ -96,7 +96,5 @@ 'use strict' | ||
web.exitMiddleware(req) | ||
web.finish(req) | ||
process.nextTick(() => { | ||
originalNext.apply(null, arguments) | ||
}) | ||
originalNext.apply(null, arguments) | ||
} | ||
@@ -116,9 +114,9 @@ } | ||
function callHandle (layer, handle, req, args) { | ||
web.enterMiddleware(req, handle, 'express.middleware') | ||
try { | ||
return handle.apply(layer, args) | ||
} catch (e) { | ||
throw addError(web.active(req), e) | ||
} | ||
return web.wrapMiddleware(req, handle, 'express.middleware', () => { | ||
try { | ||
return handle.apply(layer, args) | ||
} catch (e) { | ||
throw addError(web.active(req), e) | ||
} | ||
}) | ||
} | ||
@@ -125,0 +123,0 @@ |
@@ -24,8 +24,9 @@ 'use strict' | ||
const scope = tracer.scopeManager().active() | ||
const span = tracer.scope().active() | ||
return function () { | ||
tracer.scopeManager().activate(scope ? scope.span() : null) | ||
return callback.apply(this, arguments) | ||
return tracer.scope().activate(span, () => { | ||
return callback.apply(this, arguments) | ||
}) | ||
} | ||
} |
@@ -8,5 +8,5 @@ 'use strict' | ||
instrument (tracer, config, db, command, args) { | ||
const scope = tracer.scopeManager().active() | ||
const childOf = tracer.scope().active() | ||
const span = tracer.startSpan('redis.command', { | ||
childOf: scope && scope.span(), | ||
childOf, | ||
tags: { | ||
@@ -13,0 +13,0 @@ 'span.kind': 'client', |
'use strict' | ||
const eventSampler = require('../../event_sampler') | ||
const FORMAT_HTTP_HEADERS = require('opentracing').FORMAT_HTTP_HEADERS | ||
@@ -46,13 +47,12 @@ const log = require('../../log') | ||
callback && callback(span) | ||
eventSampler.sample(span, config.eventSampleRate) | ||
wrapEnd(req) | ||
return span | ||
return callback && tracer.scope().activate(span, () => callback(span)) | ||
}, | ||
// Reactivate the request scope in case it was changed by a middleware. | ||
reactivate (req) { | ||
req._datadog.scope && req._datadog.scope.close() | ||
req._datadog.scope = req._datadog.tracer.scopeManager().activate(req._datadog.span) | ||
reactivate (req, fn) { | ||
return req._datadog.tracer.scope().activate(req._datadog.span, fn) | ||
}, | ||
@@ -71,4 +71,4 @@ | ||
// Start a new middleware span and activate a new scope with the span. | ||
enterMiddleware (req, middleware, name) { | ||
if (!this.active(req)) return | ||
wrapMiddleware (req, middleware, name, fn) { | ||
if (!this.active(req)) return fn() | ||
@@ -78,3 +78,2 @@ const tracer = req._datadog.tracer | ||
const span = tracer.startSpan(name, { childOf }) | ||
const scope = tracer.scopeManager().activate(span) | ||
@@ -85,19 +84,14 @@ span.addTags({ | ||
req._datadog.middleware.push(scope) | ||
req._datadog.middleware.push(span) | ||
return span | ||
return tracer.scope().activate(span, fn) | ||
}, | ||
// Close the active middleware scope and finish its span. | ||
exitMiddleware (req) { | ||
// Finish the active middleware span. | ||
finish (req) { | ||
if (!this.active(req)) return | ||
const scope = req._datadog.middleware.pop() | ||
const span = req._datadog.middleware.pop() | ||
if (!scope) return | ||
const span = scope.span() | ||
span.finish() | ||
scope.close() | ||
span && span.finish() | ||
}, | ||
@@ -117,3 +111,2 @@ | ||
span: null, | ||
scope: null, | ||
paths: [], | ||
@@ -136,3 +129,3 @@ middleware: [], | ||
return req._datadog.middleware.slice(-1)[0].span() | ||
return req._datadog.middleware.slice(-1)[0] | ||
} | ||
@@ -151,7 +144,5 @@ } | ||
const span = tracer.startSpan(name, { childOf }) | ||
const scope = tracer.scopeManager().activate(span) | ||
req._datadog.tracer = tracer | ||
req._datadog.span = span | ||
req._datadog.scope = scope | ||
req._datadog.res = res | ||
@@ -174,3 +165,2 @@ | ||
req._datadog.span.finish() | ||
req._datadog.scope && req._datadog.scope.close() | ||
req._datadog.finished = true | ||
@@ -182,7 +172,6 @@ } | ||
let scope | ||
let span | ||
while ((scope = req._datadog.middleware.pop())) { | ||
scope.span().finish() | ||
scope.close() | ||
while ((span = req._datadog.middleware.pop())) { | ||
span.finish() | ||
} | ||
@@ -189,0 +178,0 @@ } |
'use strict' | ||
const BaseTracer = require('opentracing').Tracer | ||
const memoize = require('lodash.memoize') | ||
const NoopTracer = require('./noop') | ||
@@ -25,7 +24,7 @@ const DatadogTracer = require('./tracer') | ||
this._instrumenter = new Instrumenter(this) | ||
this._deprecate = memoize(method => log.debug([ | ||
this._deprecate = method => log.deprecate(`tracer.${method}`, [ | ||
`tracer.${method}() is deprecated.`, | ||
'Please use tracer.startSpan() and tracer.scopeManager() instead.', | ||
'Please use tracer.startSpan() and tracer.scope() instead.', | ||
'See: https://datadog.github.io/dd-trace-js/#manual-instrumentation.' | ||
])) | ||
].join(' ')) | ||
} | ||
@@ -121,5 +120,15 @@ | ||
scopeManager () { | ||
this._deprecate('scopeManager') | ||
return this._tracer.scopeManager.apply(this._tracer, arguments) | ||
} | ||
/** | ||
* Get the current scope to manage context propagation for the tracer. | ||
* | ||
* @returns {ScopeManager} The scope manager. | ||
*/ | ||
scope () { | ||
return this._tracer.scope.apply(this._tracer, arguments) | ||
} | ||
currentSpan () { | ||
@@ -126,0 +135,0 @@ this._deprecate('currentSpan') |
@@ -13,15 +13,28 @@ 'use strict' | ||
const stack = [] | ||
module.exports = { | ||
createHook: (callbacks) => { | ||
const hooks = { | ||
init: (uid, handle, provider, parentUid, parentHandle) => { | ||
createHook (callbacks) { | ||
const hooks = {} | ||
if (callbacks.init) { | ||
hooks.init = (uid, handle, provider, parentUid, parentHandle) => { | ||
callbacks.init(uid) | ||
}, | ||
pre: (uid, handle) => { | ||
} | ||
} | ||
if (callbacks.before) { | ||
hooks.pre = (uid, handle) => { | ||
callbacks.before(uid) | ||
}, | ||
post: (uid, handle, didThrow) => { | ||
} | ||
} | ||
if (callbacks.after) { | ||
hooks.post = (uid, handle, didThrow) => { | ||
callbacks.after(uid) | ||
}, | ||
destroy: (uid) => { | ||
} | ||
} | ||
if (callbacks.destroy) { | ||
hooks.destroy = (uid) => { | ||
callbacks.destroy(uid) | ||
@@ -31,2 +44,13 @@ } | ||
asyncHook.addHooks({ | ||
pre: (uid, handle) => { | ||
stack.push(uid) | ||
}, | ||
post: (uid, handle, didThrow) => { | ||
if (uid === this.executionAsyncId()) { | ||
stack.pop() | ||
} | ||
} | ||
}) | ||
asyncHook.enable() | ||
@@ -38,3 +62,7 @@ | ||
} | ||
}, | ||
executionAsyncId () { | ||
return stack[stack.length - 1] || 0 | ||
} | ||
} |
'use strict' | ||
const Span = require('opentracing').Span | ||
const Scope = require('./scope') | ||
@@ -7,2 +8,4 @@ | ||
const span = new Span() | ||
class ScopeManager { | ||
@@ -18,3 +21,3 @@ constructor () { | ||
active () { | ||
return null | ||
return new Scope(span) | ||
} | ||
@@ -21,0 +24,0 @@ |
@@ -7,2 +7,3 @@ 'use strict' | ||
this._finishSpanOnClose = finishSpanOnClose | ||
this.close() | ||
} | ||
@@ -9,0 +10,0 @@ |
'use strict' | ||
const asyncHooks = require('./async_hooks') | ||
const Scope = require('./scope') | ||
const Context = require('./context') | ||
const ContextExecution = require('./context_execution') | ||
const ScopeManager = require('./noop/scope_manager') | ||
let singleton = null | ||
/** | ||
* The Datadog Scope Manager. This is used for context propagation. | ||
* | ||
* @hideconstructor | ||
*/ | ||
class ScopeManager { | ||
constructor () { | ||
if (singleton) { | ||
return singleton | ||
} | ||
singleton = this | ||
const execution = new ContextExecution() | ||
this._active = execution | ||
this._stack = [] | ||
this._contexts = new Map() | ||
this._executions = new Map() | ||
this._hook = asyncHooks.createHook({ | ||
init: this._init.bind(this), | ||
before: this._before.bind(this), | ||
after: this._after.bind(this), | ||
destroy: this._destroy.bind(this), | ||
promiseResolve: this._destroy.bind(this) | ||
}) | ||
this._enable() | ||
return this | ||
} | ||
/** | ||
* Get the current active scope or null if there is none. | ||
* | ||
* @returns {Scope} The active scope. | ||
*/ | ||
active () { | ||
let execution = this._active | ||
while (execution !== null) { | ||
const scope = execution.scope() | ||
if (scope) { | ||
return scope.span() ? scope : null | ||
} | ||
execution = execution.parent() | ||
} | ||
return null | ||
} | ||
/** | ||
* Activate a new scope wrapping the provided span. | ||
* | ||
* @param {external:"opentracing.Span"} span The span for which to activate the new scope. | ||
* @param {?Boolean} [finishSpanOnClose=false] Whether to automatically finish the span when the scope is closed. | ||
* @returns {Scope} The newly created and now active scope. | ||
*/ | ||
activate (span, finishSpanOnClose) { | ||
const execution = this._active | ||
const scope = new Scope(span, execution, finishSpanOnClose) | ||
execution.add(scope) | ||
return scope | ||
} | ||
_init (asyncId) { | ||
const context = new Context() | ||
context.link(this._active) | ||
context.retain() | ||
this._contexts.set(asyncId, context) | ||
} | ||
_before (asyncId) { | ||
const context = this._contexts.get(asyncId) | ||
if (context) { | ||
const execution = new ContextExecution(context) | ||
execution.retain() | ||
this._stack.push(this._active) | ||
this._executions.set(asyncId, execution) | ||
this._active = execution | ||
} | ||
} | ||
_after (asyncId) { | ||
const execution = this._executions.get(asyncId) | ||
if (execution) { | ||
execution.exit() | ||
execution.release() | ||
this._active = this._stack.pop() | ||
this._executions.delete(asyncId) | ||
} | ||
} | ||
_destroy (asyncId) { | ||
const context = this._contexts.get(asyncId) | ||
if (context) { | ||
this._contexts.delete(asyncId) | ||
context.release() | ||
} | ||
} | ||
_enable () { | ||
this._hook.enable() | ||
} | ||
_disable () { | ||
this._hook.disable() | ||
} | ||
} | ||
module.exports = ScopeManager |
'use strict' | ||
const opentracing = require('opentracing') | ||
const Tracer = require('./opentracing/tracer') | ||
const noop = new opentracing.Span() | ||
class DatadogTracer extends Tracer { | ||
@@ -10,10 +13,14 @@ constructor (config) { | ||
let ScopeManager | ||
let Scope | ||
if (process.env.DD_CONTEXT_PROPAGATION === 'false') { | ||
ScopeManager = require('./scope/noop/scope_manager') | ||
Scope = require('./scope/new/base') | ||
} else { | ||
ScopeManager = require('./scope/scope_manager') | ||
Scope = require('./scope/new/scope') | ||
} | ||
this._scopeManager = new ScopeManager() | ||
this._scope = new Scope() | ||
} | ||
@@ -27,19 +34,3 @@ | ||
const childOf = options.childOf !== undefined ? options.childOf : this.currentSpan() | ||
const defaultTags = { | ||
'service.name': options.service || this._service, | ||
'resource.name': options.resource || name | ||
} | ||
if (options.type) { | ||
defaultTags['span.type'] = options.type | ||
} | ||
const tags = Object.assign(defaultTags, options.tags) | ||
const span = this.startSpan(name, { childOf, tags }) | ||
setImmediate(() => { | ||
this._scopeManager.activate(span, true) | ||
callback(span) | ||
}) | ||
callback(noop) | ||
} | ||
@@ -51,5 +42,8 @@ | ||
scope () { | ||
return this._scope | ||
} | ||
currentSpan () { | ||
const scope = this._scopeManager.active() | ||
return scope ? scope.span() : null | ||
return noop // return a noop span instead of null to avoid crashing the app | ||
} | ||
@@ -56,0 +50,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
143386
87
4088
6
21
3
+ Addedemitter-listener@^1.1.2
+ Addedemitter-listener@1.1.2(transitive)