dd-trace 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +22 -0
- package/package.json +1 -1
- package/packages/datadog-instrumentations/index.js +5 -3
- package/packages/datadog-instrumentations/src/couchbase.js +143 -0
- package/packages/datadog-instrumentations/src/elasticsearch.js +74 -0
- package/packages/datadog-plugin-couchbase/src/index.js +51 -148
- package/packages/datadog-plugin-elasticsearch/src/index.js +41 -82
- package/packages/datadog-plugin-fastify/src/fastify.js +22 -1
- package/packages/datadog-plugin-winston/src/index.js +4 -1
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +4 -0
- package/packages/dd-trace/src/tagger.js +14 -21
- package/packages/dd-trace/src/tracer.js +1 -1
- package/NOTICE +0 -4
- package/scripts/tracer-runner.js +0 -13
package/index.d.ts
CHANGED
|
@@ -406,6 +406,28 @@ export declare interface TracerOptions {
|
|
|
406
406
|
* @default true
|
|
407
407
|
*/
|
|
408
408
|
orphanable?: boolean
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Configuration of the AppSec protection. Can be a boolean as an alias to `appsec.enabled`.
|
|
412
|
+
*/
|
|
413
|
+
appsec?: boolean | {
|
|
414
|
+
/**
|
|
415
|
+
* Whether to enable AppSec.
|
|
416
|
+
* @default false
|
|
417
|
+
*/
|
|
418
|
+
enabled?: boolean,
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Specifies a path to a custom rules file.
|
|
422
|
+
*/
|
|
423
|
+
rules?: string,
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Controls the maximum amount of traces sampled by AppSec attacks, per second.
|
|
427
|
+
* @default 100
|
|
428
|
+
*/
|
|
429
|
+
rateLimit?: number
|
|
430
|
+
};
|
|
409
431
|
}
|
|
410
432
|
|
|
411
433
|
/** @hidden */
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
require('./src/bluebird')
|
|
4
|
+
require('./src/couchbase')
|
|
3
5
|
require('./src/dns')
|
|
6
|
+
require('./src/elasticsearch')
|
|
4
7
|
require('./src/memcached')
|
|
5
8
|
require('./src/mysql')
|
|
6
9
|
require('./src/mysql2')
|
|
7
|
-
require('./src/bluebird')
|
|
8
|
-
require('./src/when')
|
|
9
10
|
require('./src/promise')
|
|
10
|
-
require('./src/q')
|
|
11
11
|
require('./src/promise-js')
|
|
12
|
+
require('./src/q')
|
|
13
|
+
require('./src/when')
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
|
|
11
|
+
const startCh = channel('apm:couchbase:query:start')
|
|
12
|
+
const asyncEndCh = channel('apm:couchbase:query:async-end')
|
|
13
|
+
const endCh = channel('apm:couchbase:query:end')
|
|
14
|
+
const errorCh = channel('apm:couchbase:query:error')
|
|
15
|
+
|
|
16
|
+
Bucket.prototype._maybeInvoke = wrapMaybeInvoke(Bucket.prototype._maybeInvoke)
|
|
17
|
+
Bucket.prototype.query = wrapQuery(Bucket.prototype.query)
|
|
18
|
+
|
|
19
|
+
shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
|
|
20
|
+
if (!startCh.hasSubscribers) {
|
|
21
|
+
return _n1qlReq.apply(this, arguments)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
|
|
25
|
+
|
|
26
|
+
const n1qlQuery = q && q.statement
|
|
27
|
+
|
|
28
|
+
startCh.publish({ resource: n1qlQuery, bucket: this })
|
|
29
|
+
|
|
30
|
+
emitter.once('rows', AsyncResource.bind(() => {
|
|
31
|
+
asyncEndCh.publish(undefined)
|
|
32
|
+
}))
|
|
33
|
+
|
|
34
|
+
emitter.once('error', AsyncResource.bind((error) => {
|
|
35
|
+
errorCh.publish(error)
|
|
36
|
+
asyncEndCh.publish(undefined)
|
|
37
|
+
}))
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
return _n1qlReq.apply(this, arguments)
|
|
41
|
+
} catch (err) {
|
|
42
|
+
err.stack // trigger getting the stack at the original throwing point
|
|
43
|
+
errorCh.publish(err)
|
|
44
|
+
|
|
45
|
+
throw err
|
|
46
|
+
} finally {
|
|
47
|
+
endCh.publish(undefined)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
Bucket.prototype.upsert = wrap('apm:couchbase:upsert', Bucket.prototype.upsert)
|
|
52
|
+
Bucket.prototype.insert = wrap('apm:couchbase:insert', Bucket.prototype.insert)
|
|
53
|
+
Bucket.prototype.replace = wrap('apm:couchbase:replace', Bucket.prototype.replace)
|
|
54
|
+
Bucket.prototype.append = wrap('apm:couchbase:append', Bucket.prototype.append)
|
|
55
|
+
Bucket.prototype.prepend = wrap('apm:couchbase:prepend', Bucket.prototype.prepend)
|
|
56
|
+
|
|
57
|
+
return Bucket
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Cluster => {
|
|
61
|
+
Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
|
|
62
|
+
Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
|
|
63
|
+
|
|
64
|
+
return Cluster
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
function findCallbackIndex (args) {
|
|
68
|
+
for (let i = args.length - 1; i >= 2; i--) {
|
|
69
|
+
if (typeof args[i] === 'function') return i
|
|
70
|
+
}
|
|
71
|
+
return -1
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function wrapMaybeInvoke (_maybeInvoke) {
|
|
75
|
+
const wrapped = function (fn, args) {
|
|
76
|
+
if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
|
|
77
|
+
|
|
78
|
+
const callbackIndex = args.length - 1
|
|
79
|
+
const callback = args[callbackIndex]
|
|
80
|
+
|
|
81
|
+
if (callback instanceof Function) {
|
|
82
|
+
args[callbackIndex] = AsyncResource.bind(callback)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return _maybeInvoke.apply(this, arguments)
|
|
86
|
+
}
|
|
87
|
+
return shimmer.wrap(_maybeInvoke, wrapped)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function wrapQuery (query) {
|
|
91
|
+
const wrapped = function (q, params, callback) {
|
|
92
|
+
callback = AsyncResource.bind(arguments[arguments.length - 1])
|
|
93
|
+
|
|
94
|
+
if (typeof callback === 'function') {
|
|
95
|
+
arguments[arguments.length - 1] = callback
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const res = query.apply(this, arguments)
|
|
99
|
+
return res
|
|
100
|
+
}
|
|
101
|
+
return shimmer.wrap(query, wrapped)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function wrap (prefix, fn) {
|
|
105
|
+
const startCh = channel(prefix + ':start')
|
|
106
|
+
const endCh = channel(prefix + ':end')
|
|
107
|
+
const asyncEndCh = channel(prefix + ':async-end')
|
|
108
|
+
const errorCh = channel(prefix + ':error')
|
|
109
|
+
|
|
110
|
+
const wrapped = function (key, value, options, callback) {
|
|
111
|
+
if (!startCh.hasSubscribers) {
|
|
112
|
+
return fn.apply(this, arguments)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const callbackIndex = findCallbackIndex(arguments)
|
|
116
|
+
|
|
117
|
+
if (callbackIndex < 0) return fn.apply(this, arguments)
|
|
118
|
+
|
|
119
|
+
const cb = arguments[callbackIndex]
|
|
120
|
+
|
|
121
|
+
startCh.publish({ bucket: this })
|
|
122
|
+
|
|
123
|
+
arguments[callbackIndex] = function (error, result) {
|
|
124
|
+
if (error) {
|
|
125
|
+
errorCh.publish(error)
|
|
126
|
+
}
|
|
127
|
+
asyncEndCh.publish(result)
|
|
128
|
+
return cb.apply(this, arguments)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
return fn.apply(this, arguments)
|
|
133
|
+
} catch (error) {
|
|
134
|
+
error.stack // trigger getting the stack at the original throwing point
|
|
135
|
+
errorCh.publish(error)
|
|
136
|
+
|
|
137
|
+
throw error
|
|
138
|
+
} finally {
|
|
139
|
+
endCh.publish(undefined)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return shimmer.wrap(fn, wrapped)
|
|
143
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const startCh = channel('apm:elasticsearch:query:start')
|
|
11
|
+
const asyncEndCh = channel('apm:elasticsearch:query:async-end')
|
|
12
|
+
const endCh = channel('apm:elasticsearch:query:end')
|
|
13
|
+
const errorCh = channel('apm:elasticsearch:query:error')
|
|
14
|
+
|
|
15
|
+
addHook({ name: '@elastic/elasticsearch', file: 'lib/Transport.js', versions: ['>=5.6.16'] }, Transport => {
|
|
16
|
+
shimmer.wrap(Transport.prototype, 'request', wrapRequest)
|
|
17
|
+
return Transport
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
addHook({ name: 'elasticsearch', file: 'src/lib/transport.js', versions: ['>=10'] }, Transport => {
|
|
21
|
+
shimmer.wrap(Transport.prototype, 'request', wrapRequest)
|
|
22
|
+
return Transport
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function wrapRequest (request) {
|
|
26
|
+
return function (params, options, cb) {
|
|
27
|
+
if (!startCh.hasSubscribers) {
|
|
28
|
+
return request.apply(this, arguments)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!params) return request.apply(this, arguments)
|
|
32
|
+
|
|
33
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
34
|
+
|
|
35
|
+
startCh.publish({ params })
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const lastIndex = arguments.length - 1
|
|
39
|
+
cb = arguments[lastIndex]
|
|
40
|
+
|
|
41
|
+
if (typeof cb === 'function') {
|
|
42
|
+
cb = asyncResource.bind(cb)
|
|
43
|
+
|
|
44
|
+
arguments[lastIndex] = AsyncResource.bind(function (error) {
|
|
45
|
+
finish(params, error)
|
|
46
|
+
return cb.apply(null, arguments)
|
|
47
|
+
})
|
|
48
|
+
return request.apply(this, arguments)
|
|
49
|
+
} else {
|
|
50
|
+
const promise = request.apply(this, arguments)
|
|
51
|
+
if (promise && typeof promise.then === 'function') {
|
|
52
|
+
promise.then(() => finish(params), e => finish(params, e))
|
|
53
|
+
} else {
|
|
54
|
+
finish(params)
|
|
55
|
+
}
|
|
56
|
+
return promise
|
|
57
|
+
}
|
|
58
|
+
} catch (err) {
|
|
59
|
+
err.stack // trigger getting the stack at the original throwing point
|
|
60
|
+
errorCh.publish(err)
|
|
61
|
+
|
|
62
|
+
throw err
|
|
63
|
+
} finally {
|
|
64
|
+
endCh.publish(undefined)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function finish (params, error) {
|
|
70
|
+
if (error) {
|
|
71
|
+
errorCh.publish(error)
|
|
72
|
+
}
|
|
73
|
+
asyncEndCh.publish({ params })
|
|
74
|
+
}
|
|
@@ -1,171 +1,74 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
class CouchBasePlugin extends Plugin {
|
|
8
|
+
static get name () {
|
|
9
|
+
return 'couchbase'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
addSubs (func, start, asyncEnd = defaultAsyncEnd) {
|
|
13
|
+
this.addSub(`apm:couchbase:${func}:start`, start)
|
|
14
|
+
this.addSub(`apm:couchbase:${func}:end`, this.exit.bind(this))
|
|
15
|
+
this.addSub(`apm:couchbase:${func}:error`, errorHandler)
|
|
16
|
+
this.addSub(`apm:couchbase:${func}:async-end`, asyncEnd)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
startSpan (operation, customTags, store, bucket) {
|
|
20
|
+
const tags = {
|
|
12
21
|
'db.type': 'couchbase',
|
|
13
22
|
'component': 'couchbase',
|
|
14
|
-
'service.name': config.service || `${tracer._service}-couchbase`,
|
|
15
|
-
'resource.name':
|
|
16
|
-
|
|
23
|
+
'service.name': this.config.service || `${this.tracer._service}-couchbase`,
|
|
24
|
+
'resource.name': `couchbase.${operation}`,
|
|
25
|
+
'span.kind': 'client'
|
|
17
26
|
}
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
analyticsSampler.sample(span, config.measured)
|
|
21
|
-
|
|
22
|
-
return span
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function onRequestFinish (emitter, span) {
|
|
26
|
-
emitter.once('rows', () => {
|
|
27
|
-
span.finish()
|
|
28
|
-
})
|
|
29
|
-
emitter.once('error', (err) => {
|
|
30
|
-
span.setTag(Tags.ERROR, err)
|
|
31
|
-
span.finish()
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createWrapMaybeInvoke (tracer) {
|
|
36
|
-
return function wrapMaybeInvoke (_maybeInvoke) {
|
|
37
|
-
return function maybeInvokeWithTrace (fn, args) {
|
|
38
|
-
if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const callback = args[callbackIndex]
|
|
43
|
-
|
|
44
|
-
if (callback instanceof Function) {
|
|
45
|
-
args[callbackIndex] = scope.bind(callback)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return scope.bind(_maybeInvoke).apply(this, arguments)
|
|
28
|
+
for (const tag in customTags) {
|
|
29
|
+
tags[tag] = customTags[tag]
|
|
49
30
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return function wrapQuery (query) {
|
|
55
|
-
return function queryWithTrace (q, params, callback) {
|
|
56
|
-
const scope = tracer.scope()
|
|
31
|
+
const span = this.tracer.startSpan(`couchbase.${operation}`, {
|
|
32
|
+
childOf: store ? store.span : null,
|
|
33
|
+
tags
|
|
34
|
+
})
|
|
57
35
|
|
|
58
|
-
|
|
36
|
+
span.setTag('couchbase.bucket.name', bucket.name || bucket._name)
|
|
59
37
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return scope.bind(query.apply(this, arguments))
|
|
65
|
-
}
|
|
38
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
39
|
+
return span
|
|
66
40
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function createWrapN1qlReq (tracer, config) {
|
|
70
|
-
return function wrapN1qlReq (_n1qlReq) {
|
|
71
|
-
return function n1qlReqWithTrace (host, q, adhoc, emitter) {
|
|
72
|
-
if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
|
|
73
|
-
|
|
74
|
-
const scope = tracer.scope()
|
|
75
|
-
const n1qlQuery = q && q.statement
|
|
76
|
-
const span = startSpan(tracer, config, 'query', n1qlQuery)
|
|
77
41
|
|
|
78
|
-
|
|
42
|
+
constructor (...args) {
|
|
43
|
+
super(...args)
|
|
79
44
|
|
|
80
|
-
|
|
81
|
-
|
|
45
|
+
this.addSubs('query', ({ resource, bucket }) => {
|
|
46
|
+
const store = storage.getStore()
|
|
47
|
+
const span = this.startSpan('query', { 'span.type': 'sql', 'resource.name': resource }, store, bucket)
|
|
48
|
+
this.enter(span, store)
|
|
49
|
+
})
|
|
82
50
|
|
|
83
|
-
|
|
84
|
-
|
|
51
|
+
this._addCommandSubs('upsert')
|
|
52
|
+
this._addCommandSubs('insert')
|
|
53
|
+
this._addCommandSubs('replace')
|
|
54
|
+
this._addCommandSubs('append')
|
|
55
|
+
this._addCommandSubs('prepend')
|
|
85
56
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (callbackIndex < 0) return store.apply(this, arguments)
|
|
94
|
-
|
|
95
|
-
const scope = tracer.scope()
|
|
96
|
-
const span = startSpan(tracer, config, operation)
|
|
97
|
-
|
|
98
|
-
addBucketTag(span, this)
|
|
99
|
-
|
|
100
|
-
arguments[callbackIndex] = wrapCallback(span, arguments[callbackIndex])
|
|
101
|
-
|
|
102
|
-
return scope.bind(store, span).apply(this, arguments)
|
|
103
|
-
}
|
|
57
|
+
_addCommandSubs (name) {
|
|
58
|
+
this.addSubs(name, ({ bucket }) => {
|
|
59
|
+
const store = storage.getStore()
|
|
60
|
+
const span = this.startSpan(name, {}, store, bucket)
|
|
61
|
+
this.enter(span, store)
|
|
62
|
+
})
|
|
104
63
|
}
|
|
105
64
|
}
|
|
106
65
|
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function findCallbackIndex (args) {
|
|
112
|
-
for (let i = args.length - 1; i >= 2; i--) {
|
|
113
|
-
if (typeof args[i] === 'function') return i
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return -1
|
|
66
|
+
function defaultAsyncEnd () {
|
|
67
|
+
storage.getStore().span.finish()
|
|
117
68
|
}
|
|
118
69
|
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
span.setTag('error', err)
|
|
122
|
-
span.finish()
|
|
123
|
-
|
|
124
|
-
return callback.apply(this, arguments)
|
|
125
|
-
}
|
|
70
|
+
function errorHandler (error) {
|
|
71
|
+
storage.getStore().span.setTag('error', error)
|
|
126
72
|
}
|
|
127
73
|
|
|
128
|
-
module.exports =
|
|
129
|
-
{
|
|
130
|
-
name: 'couchbase',
|
|
131
|
-
versions: ['^2.6.5'],
|
|
132
|
-
file: 'lib/bucket.js',
|
|
133
|
-
patch (Bucket, tracer, config) {
|
|
134
|
-
tracer.scope().bind(Bucket.prototype)
|
|
135
|
-
|
|
136
|
-
this.wrap(Bucket.prototype, '_maybeInvoke', createWrapMaybeInvoke(tracer, config))
|
|
137
|
-
this.wrap(Bucket.prototype, 'query', createWrapQuery(tracer))
|
|
138
|
-
this.wrap(Bucket.prototype, '_n1qlReq', createWrapN1qlReq(tracer, config))
|
|
139
|
-
this.wrap(Bucket.prototype, 'upsert', createWrapStore(tracer, config, 'upsert'))
|
|
140
|
-
this.wrap(Bucket.prototype, 'insert', createWrapStore(tracer, config, 'insert'))
|
|
141
|
-
this.wrap(Bucket.prototype, 'replace', createWrapStore(tracer, config, 'replace'))
|
|
142
|
-
this.wrap(Bucket.prototype, 'append', createWrapStore(tracer, config, 'append'))
|
|
143
|
-
this.wrap(Bucket.prototype, 'prepend', createWrapStore(tracer, config, 'prepend'))
|
|
144
|
-
},
|
|
145
|
-
unpatch (Bucket, tracer) {
|
|
146
|
-
tracer.scope().unbind(Bucket.prototype)
|
|
147
|
-
|
|
148
|
-
this.unwrap(Bucket.prototype, '_maybeInvoke')
|
|
149
|
-
this.unwrap(Bucket.prototype, 'query')
|
|
150
|
-
this.unwrap(Bucket.prototype, '_n1qlReq')
|
|
151
|
-
this.unwrap(Bucket.prototype, 'upsert')
|
|
152
|
-
this.unwrap(Bucket.prototype, 'insert')
|
|
153
|
-
this.unwrap(Bucket.prototype, 'replace')
|
|
154
|
-
this.unwrap(Bucket.prototype, 'append')
|
|
155
|
-
this.unwrap(Bucket.prototype, 'prepend')
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: 'couchbase',
|
|
160
|
-
versions: ['^2.6.5'],
|
|
161
|
-
file: 'lib/cluster.js',
|
|
162
|
-
patch (Cluster, tracer, config) {
|
|
163
|
-
this.wrap(Cluster.prototype, '_maybeInvoke', createWrapMaybeInvoke(tracer, config))
|
|
164
|
-
this.wrap(Cluster.prototype, 'query', createWrapQuery(tracer))
|
|
165
|
-
},
|
|
166
|
-
unpatch (Cluster) {
|
|
167
|
-
this.unwrap(Cluster.prototype, '_maybeInvoke')
|
|
168
|
-
this.unwrap(Cluster.prototype, 'query')
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
]
|
|
74
|
+
module.exports = CouchBasePlugin
|
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
4
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
class ElasticsearchPlugin extends Plugin {
|
|
8
|
+
static get name () {
|
|
9
|
+
return 'elasticsearch'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
constructor (...args) {
|
|
13
|
+
super(...args)
|
|
14
|
+
|
|
15
|
+
this.addSub('apm:elasticsearch:query:start', ({ params }) => {
|
|
16
|
+
this.config = normalizeConfig(this.config)
|
|
11
17
|
|
|
12
|
-
const
|
|
18
|
+
const store = storage.getStore()
|
|
19
|
+
const childOf = store ? store.span : store
|
|
13
20
|
const body = getBody(params.body || params.bulkBody)
|
|
14
|
-
const
|
|
15
|
-
const span = tracer.startSpan('elasticsearch.query', {
|
|
21
|
+
const span = this.tracer.startSpan('elasticsearch.query', {
|
|
16
22
|
childOf,
|
|
17
23
|
tags: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
'service.name': config.service || `${tracer._service}-elasticsearch`,
|
|
24
|
+
'db.type': 'elasticsearch',
|
|
25
|
+
'span.kind': 'client',
|
|
26
|
+
'service.name': this.config.service || `${this.tracer._service}-elasticsearch`,
|
|
21
27
|
'resource.name': `${params.method} ${quantizePath(params.path)}`,
|
|
22
28
|
'span.type': 'elasticsearch',
|
|
23
29
|
'elasticsearch.url': params.path,
|
|
@@ -26,57 +32,25 @@ function createWrapRequest (tracer, config) {
|
|
|
26
32
|
'elasticsearch.params': JSON.stringify(params.querystring || params.query)
|
|
27
33
|
}
|
|
28
34
|
})
|
|
35
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
36
|
+
this.enter(span, store)
|
|
37
|
+
})
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (typeof cb === 'function') {
|
|
35
|
-
arguments[lastIndex] = wrapCallback(tracer, span, params, config, cb)
|
|
36
|
-
|
|
37
|
-
return tracer.scope().activate(span, () => request.apply(this, arguments))
|
|
38
|
-
} else {
|
|
39
|
-
const promise = request.apply(this, arguments)
|
|
40
|
-
|
|
41
|
-
if (promise && typeof promise.then === 'function') {
|
|
42
|
-
promise.then(() => finish(span, params, config), e => finish(span, params, config, e))
|
|
43
|
-
} else {
|
|
44
|
-
finish(span, params, config)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return promise
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
39
|
+
this.addSub('apm:elasticsearch:query:end', () => {
|
|
40
|
+
this.exit()
|
|
41
|
+
})
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
58
|
-
}
|
|
43
|
+
this.addSub('apm:elasticsearch:query:error', err => {
|
|
44
|
+
const span = storage.getStore().span
|
|
45
|
+
span.setTag('error', err)
|
|
46
|
+
})
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
'error.msg': err.message,
|
|
65
|
-
'error.stack': err.stack
|
|
48
|
+
this.addSub('apm:elasticsearch:query:async-end', ({ params }) => {
|
|
49
|
+
const span = storage.getStore().span
|
|
50
|
+
this.config.hooks.query(span, params)
|
|
51
|
+
span.finish()
|
|
66
52
|
})
|
|
67
53
|
}
|
|
68
|
-
|
|
69
|
-
config.hooks.query(span, params)
|
|
70
|
-
|
|
71
|
-
span.finish()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function quantizePath (path) {
|
|
75
|
-
return path && path.replace(/[0-9]+/g, '?')
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getBody (body) {
|
|
79
|
-
return body && JSON.stringify(body)
|
|
80
54
|
}
|
|
81
55
|
|
|
82
56
|
function normalizeConfig (config) {
|
|
@@ -94,27 +68,12 @@ function getHooks (config) {
|
|
|
94
68
|
return { query }
|
|
95
69
|
}
|
|
96
70
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.unwrap(Transport.prototype, 'request')
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: '@elastic/elasticsearch',
|
|
111
|
-
file: 'lib/Transport.js',
|
|
112
|
-
versions: ['>=5.6.16'], // initial version of this module
|
|
113
|
-
patch (Transport, tracer, config) {
|
|
114
|
-
this.wrap(Transport.prototype, 'request', createWrapRequest(tracer, config))
|
|
115
|
-
},
|
|
116
|
-
unpatch (Transport) {
|
|
117
|
-
this.unwrap(Transport.prototype, 'request')
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
]
|
|
71
|
+
function getBody (body) {
|
|
72
|
+
return body && JSON.stringify(body)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function quantizePath (path) {
|
|
76
|
+
return path && path.replace(/[0-9]+/g, '?')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = ElasticsearchPlugin
|
|
@@ -165,7 +165,28 @@ function getRes (reply) {
|
|
|
165
165
|
module.exports = [
|
|
166
166
|
{
|
|
167
167
|
name: 'fastify',
|
|
168
|
-
versions: ['>=
|
|
168
|
+
versions: ['>=3'],
|
|
169
|
+
patch (fastify, tracer, config) {
|
|
170
|
+
// `fastify` is a function so we return a wrapper that will replace its export.
|
|
171
|
+
const wrapped = this.wrapExport(fastify, createWrapFastify(tracer, config)(fastify))
|
|
172
|
+
|
|
173
|
+
wrapped.fastify = wrapped
|
|
174
|
+
wrapped.default = wrapped
|
|
175
|
+
|
|
176
|
+
return wrapped
|
|
177
|
+
},
|
|
178
|
+
unpatch (fastify) {
|
|
179
|
+
const unwrapped = this.unwrapExport(fastify)
|
|
180
|
+
|
|
181
|
+
unwrapped.fastify = unwrapped
|
|
182
|
+
unwrapped.default = unwrapped
|
|
183
|
+
|
|
184
|
+
return unwrapped
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'fastify',
|
|
189
|
+
versions: ['1 - 2'],
|
|
169
190
|
patch (fastify, tracer, config) {
|
|
170
191
|
// `fastify` is a function so we return a wrapper that will replace its export.
|
|
171
192
|
return this.wrapExport(fastify, createWrapFastify(tracer, config)(fastify))
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { LOG } = require('../../../ext/formats')
|
|
4
4
|
|
|
5
|
+
const hasOwn = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
|
|
6
|
+
|
|
5
7
|
function chunkProxy (chunk, holder) {
|
|
6
8
|
return new Proxy(chunk, {
|
|
7
9
|
get (target, p, receiver) {
|
|
@@ -15,7 +17,8 @@ function chunkProxy (chunk, holder) {
|
|
|
15
17
|
}
|
|
16
18
|
},
|
|
17
19
|
ownKeys (target) {
|
|
18
|
-
|
|
20
|
+
const ownKeys = Reflect.ownKeys(target)
|
|
21
|
+
return hasOwn(target, 'dd') ? ownKeys : ['dd', ...ownKeys]
|
|
19
22
|
},
|
|
20
23
|
getOwnPropertyDescriptor (target, p) {
|
|
21
24
|
return Reflect.getOwnPropertyDescriptor(p === 'dd' ? holder : target, p)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '2.
|
|
1
|
+
module.exports = '2.2.0'
|
|
@@ -76,6 +76,10 @@ function incomingHttpEndTranslator (data) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// TODO: temporary express instrumentation, will use express plugin later
|
|
79
|
+
if (data.req.body !== undefined && data.req.body !== null) {
|
|
80
|
+
payload[addresses.HTTP_INCOMING_BODY] = data.req.body
|
|
81
|
+
}
|
|
82
|
+
|
|
79
83
|
if (data.req.query && typeof data.req.query === 'object') {
|
|
80
84
|
payload[addresses.HTTP_INCOMING_QUERY] = data.req.query
|
|
81
85
|
}
|
|
@@ -5,32 +5,25 @@ const log = require('./log')
|
|
|
5
5
|
function add (carrier, keyValuePairs) {
|
|
6
6
|
if (!carrier || !keyValuePairs) return
|
|
7
7
|
|
|
8
|
-
if (typeof keyValuePairs === 'string') {
|
|
9
|
-
return add(
|
|
10
|
-
carrier,
|
|
11
|
-
keyValuePairs
|
|
12
|
-
.split(',')
|
|
13
|
-
.filter(tag => tag.indexOf(':') !== -1)
|
|
14
|
-
.reduce((prev, next) => {
|
|
15
|
-
const tag = next.split(':')
|
|
16
|
-
const key = tag[0].trim()
|
|
17
|
-
const value = tag.slice(1).join(':').trim()
|
|
18
|
-
|
|
19
|
-
prev[key] = value
|
|
20
|
-
|
|
21
|
-
return prev
|
|
22
|
-
}, {})
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
8
|
if (Array.isArray(keyValuePairs)) {
|
|
27
9
|
return keyValuePairs.forEach(tags => add(carrier, tags))
|
|
28
10
|
}
|
|
29
11
|
|
|
30
12
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
13
|
+
if (typeof keyValuePairs === 'string') {
|
|
14
|
+
const segments = keyValuePairs.split(',')
|
|
15
|
+
for (const segment of segments) {
|
|
16
|
+
const separatorIndex = segment.indexOf(':')
|
|
17
|
+
if (separatorIndex === -1) continue
|
|
18
|
+
|
|
19
|
+
const key = segment.slice(0, separatorIndex)
|
|
20
|
+
const value = segment.slice(separatorIndex + 1)
|
|
21
|
+
|
|
22
|
+
carrier[key.trim()] = value.trim()
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
Object.assign(carrier, keyValuePairs)
|
|
26
|
+
}
|
|
34
27
|
} catch (e) {
|
|
35
28
|
log.error(e)
|
|
36
29
|
}
|
package/NOTICE
DELETED
package/scripts/tracer-runner.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const spawnWrap = require('spawn-wrap')
|
|
4
|
-
const path = require('path')
|
|
5
|
-
|
|
6
|
-
spawnWrap(['--require', path.join(__dirname, '..', 'init.js')])
|
|
7
|
-
|
|
8
|
-
const { spawn } = require('child_process')
|
|
9
|
-
|
|
10
|
-
const [command, ...argv] = process.argv.slice(2)
|
|
11
|
-
spawn(command, argv, {
|
|
12
|
-
stdio: 'inherit'
|
|
13
|
-
})
|