newrelic 4.6.0 → 4.9.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.
Files changed (44) hide show
  1. package/NEWS.md +222 -1
  2. package/api.js +24 -11
  3. package/bin/compare-bench-results.js +167 -0
  4. package/bin/run-bench.js +87 -44
  5. package/bin/travis-setup.sh +18 -7
  6. package/index.js +16 -8
  7. package/lib/collector/remote-method.js +12 -0
  8. package/lib/config/default.js +5 -0
  9. package/lib/config/env.js +2 -1
  10. package/lib/config/index.js +5 -0
  11. package/lib/db/tracer.js +17 -6
  12. package/lib/environment.js +1 -1
  13. package/lib/errors/index.js +1 -1
  14. package/lib/instrumentation/bluebird.js +35 -45
  15. package/lib/instrumentation/core/async_hooks.js +8 -8
  16. package/lib/instrumentation/core/child_process.js +41 -34
  17. package/lib/instrumentation/core/crypto.js +9 -14
  18. package/lib/instrumentation/core/dns.js +9 -13
  19. package/lib/instrumentation/core/domain.js +10 -12
  20. package/lib/instrumentation/core/fs.js +47 -38
  21. package/lib/instrumentation/core/globals.js +12 -17
  22. package/lib/instrumentation/core/http.js +3 -3
  23. package/lib/instrumentation/core/inspector.js +8 -7
  24. package/lib/instrumentation/core/net.js +62 -66
  25. package/lib/instrumentation/core/timers.js +79 -40
  26. package/lib/instrumentation/core/zlib.js +22 -8
  27. package/lib/instrumentation/mongodb.js +158 -115
  28. package/lib/instrumentations.js +3 -2
  29. package/lib/priority-queue.js +5 -2
  30. package/lib/shim/constants.js +6 -0
  31. package/lib/shim/datastore-shim.js +1 -1
  32. package/lib/shim/index.js +9 -5
  33. package/lib/shim/message-shim.js +5 -4
  34. package/lib/shim/promise-shim.js +563 -0
  35. package/lib/shim/shim.js +90 -11
  36. package/lib/shim/specs/index.js +8 -5
  37. package/lib/shimmer.js +70 -28
  38. package/lib/transaction/dt-payload.js +16 -0
  39. package/lib/transaction/handle.js +1 -1
  40. package/lib/transaction/index.js +22 -8
  41. package/lib/transaction/trace/aggregator.js +3 -3
  42. package/lib/transaction/trace/index.js +30 -37
  43. package/lib/util/codec.js +4 -1
  44. package/package.json +10 -4
@@ -1,13 +1,12 @@
1
1
  'use strict'
2
2
 
3
- var record = require('../../metrics/recorders/generic')
4
- var NAMES = require('../../metrics/names')
5
- var wrap = require('../../shimmer').wrapMethod
3
+ const record = require('../../metrics/recorders/generic')
4
+ const NAMES = require('../../metrics/names')
6
5
 
7
6
  module.exports = initialize
8
7
 
9
- function initialize(agent, fs) {
10
- var methods = [
8
+ function initialize(agent, fs, moduleName, shim) {
9
+ const methods = [
11
10
  'rename',
12
11
  'truncate',
13
12
  'chown',
@@ -40,52 +39,62 @@ function initialize(agent, fs) {
40
39
  'ftruncate'
41
40
  ]
42
41
 
43
- var uninstrumented = [
42
+ const nonRecordedMethods = [
44
43
  'write',
45
44
  'read'
46
45
  ]
47
46
 
48
- wrap(fs, 'fs', methods, segment)
49
- wrap(fs.realpath, 'fs.realpath', 'native', wrapRealPathNative)
50
- wrap(fs, 'fs', uninstrumented, agent.tracer.wrapFunctionNoSegment.bind(agent.tracer))
51
- wrap(fs, 'fs', ['watch'], wrapWatch)
52
- wrap(fs, 'fs', ['watchFile'], wrapWatchFile)
47
+ shim.record(fs, methods, recordFs)
53
48
 
54
- function segment(fn, method) {
55
- return agent.tracer.wrapFunctionLast(NAMES.FS.PREFIX + method, record, fn)
56
- }
49
+ const originalExists = shim.getOriginal(fs.exists)
50
+ Object.getOwnPropertySymbols(originalExists).forEach((symbol) => {
51
+ fs.exists[symbol] = originalExists[symbol]
52
+ })
57
53
 
58
- function wrapRealPathNative(fn) {
59
- return segment(fn, 'realpath.native')
60
- }
54
+ fs.realpath.native = shim.getOriginal(fs.realpath).native
61
55
 
62
- function wrapWatch(fn) {
63
- return function wrappedWatch() {
64
- var args = agent.tracer.slice(arguments)
65
- var last = args.length - 1
56
+ shim.record(
57
+ fs.realpath,
58
+ 'native',
59
+ function recordRealpathNative(shim, fn) {
60
+ return recordFs(shim, fn, 'realpath.native')
61
+ }
62
+ )
66
63
 
67
- if (typeof args[last] === 'function') {
68
- var cb = args[last]
69
- args[last] = agent.tracer.bindFunction(cb)
70
- }
64
+ shim.wrap(
65
+ fs,
66
+ nonRecordedMethods,
67
+ function wrapNonRecordedFs(shim, fn) {
68
+ return function wrappedNonRecordedFs() {
69
+ // these are called in tight loops so opting out early
70
+ if (!shim.getActiveSegment()) {
71
+ return fn.apply(this, arguments)
72
+ }
71
73
 
72
- return agent.tracer.bindEmitter(fn.apply(this, args))
73
- }
74
- }
74
+ const args = shim.argsToArray.apply(shim, arguments)
75
+ const cbIndex = args.length - 1
75
76
 
76
- function wrapWatchFile(fn) {
77
- return function wrappedWatchFile() {
78
- var args = agent.tracer.slice(arguments)
79
- var last = args.length - 1
77
+ shim.bindSegment(args, cbIndex)
80
78
 
81
- if (typeof args[last] === 'function') {
82
- var cb = args[last]
83
- args[last] = agent.tracer.bindFunction(cb)
84
- // allow unwatchFile to work despite cb being wrapped
85
- args[last].listener = cb
79
+ return fn.apply(this, args)
86
80
  }
81
+ }
82
+ )
83
+
84
+ shim.wrap(
85
+ fs,
86
+ ['watch', 'watchFile'],
87
+ function wrapFsWatch(shim, fn) {
88
+ return function wrappedFsWatch() {
89
+ const result = fn.apply(this, arguments)
90
+ shim.bindSegment(result, 'emit')
87
91
 
88
- return fn.apply(this, args)
92
+ return result
93
+ }
89
94
  }
95
+ )
96
+
97
+ function recordFs(shim, fn, name) {
98
+ return {name: NAMES.FS.PREFIX + name, callback: shim.LAST, recorder: record}
90
99
  }
91
100
  }
@@ -1,33 +1,30 @@
1
1
  'use strict'
2
2
 
3
3
  var asyncHooks = require('./async_hooks')
4
- var logger = require('../../logger').child({component: 'globals'})
5
- var shimmer = require('../../shimmer')
6
4
 
7
5
  module.exports = initialize
8
6
 
9
7
 
10
- function initialize(agent) {
8
+ function initialize(agent, nodule, name, shim) {
11
9
  let exceptionCallbackRegistered = false
12
10
 
13
11
  // `_fatalException` is an undocumented feature of domains, introduced in
14
12
  // Node.js v0.8. We use `_fatalException` because wrapping it will not
15
13
  // potentially change the behavior of the server unlike listening for
16
14
  // `uncaughtException`.
17
- shimmer.wrapMethod(process, 'process', '_fatalException', function wrapper(original) {
15
+ shim.wrap(process, '_fatalException', function wrapper(shim, original) {
18
16
  return function wrappedFatalException(error) {
19
17
  // Only record the error if we are not currently within an instrumented
20
18
  // domain.
21
19
  if (!process.domain && !exceptionCallbackRegistered) {
22
20
  agent.errors.add(null, error)
23
- agent.tracer.segment = null
21
+ shim.setActiveSegment(null)
24
22
  }
25
23
  return original.apply(this, arguments)
26
24
  }
27
25
  })
28
26
 
29
- shimmer.wrapMethod(process, 'process', 'emit', wrapEmit)
30
- function wrapEmit(original) {
27
+ shim.wrap(process, 'emit', function wrapEmit(shim, original) {
31
28
  return function wrappedEmit(ev, error, promise) {
32
29
  // Check for unhandledRejections here so we don't change the behavior of
33
30
  // the event.
@@ -38,23 +35,21 @@ function initialize(agent) {
38
35
  ? (asyncHooks.segmentMap.get(promise.__NR_id))
39
36
  : (promise.__NR_context && promise.__NR_context.getSegment())
40
37
  const tx = segment && segment.transaction
41
- logger.trace('Captured unhandled rejection for transaction %s', tx && tx.id)
38
+ shim.logger.trace(
39
+ 'Captured unhandled rejection for transaction %s',
40
+ tx && tx.id
41
+ )
42
42
  agent.errors.add(tx, error)
43
43
  }
44
44
  }
45
45
 
46
46
  return original.apply(this, arguments)
47
47
  }
48
- }
48
+ })
49
49
 
50
- shimmer.wrapMethod(
51
- process,
52
- 'process',
53
- 'setUncaughtExceptionCaptureCallback',
54
- wrapUncaughtExceptionCallback
55
- )
50
+ shim.wrap(process, 'setUncaughtExceptionCaptureCallback', wrapUncaughtExceptionCallback)
56
51
 
57
- function wrapUncaughtExceptionCallback(original) {
52
+ function wrapUncaughtExceptionCallback(shim, original) {
58
53
  return function wrapped(fn) {
59
54
  exceptionCallbackRegistered = fn !== null
60
55
  return original.apply(this, arguments)
@@ -63,5 +58,5 @@ function initialize(agent) {
63
58
 
64
59
  // This will initialize the most optimal native-promise instrumentation that
65
60
  // we have available.
66
- asyncHooks(agent)
61
+ asyncHooks(agent, shim)
67
62
  }
@@ -693,7 +693,7 @@ module.exports = function initialize(agent, http, moduleName) {
693
693
  *
694
694
  * @param {string} header - The raw X-NewRelic-Synthetics header
695
695
  * @param {string} encKey - Encoding key handed down from the server
696
- * @param {̄Array} trustedIds - Array of accounts to trust the header from.
696
+ * @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
697
697
  * @param {Transaction} transaction - Where the synthetics data is attached to.
698
698
  */
699
699
  function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
@@ -711,8 +711,8 @@ function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
711
711
  *
712
712
  * @param {string} header - The raw X-NewRelic-Synthetics header
713
713
  * @param {string} encKey - Encoding key handed down from the server
714
- * @param {̄Array} trustedIds - Array of accounts to trust the header from.
715
- * @return {Object or null} - On successful parse and verification an object of
714
+ * @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
715
+ * @return {Object|null} - On successful parse and verification an object of
716
716
  * synthetics data is returned, otherwise null is
717
717
  * returned.
718
718
  */
@@ -1,21 +1,22 @@
1
1
  'use strict'
2
2
 
3
- var wrap = require('../../shimmer').wrapMethod
4
-
5
3
  module.exports = initialize
6
4
 
7
- function initialize(agent, inspector) {
5
+ function initialize(agent, inspector, name, shim) {
8
6
  var sessionProto = inspector && inspector.Session && inspector.Session.prototype
9
7
  if (!sessionProto) {
10
8
  return false
11
9
  }
12
10
 
13
- wrap(
11
+ shim.wrap(
14
12
  sessionProto,
15
- 'inspector.Session.prototype',
16
13
  'post',
17
- function wrapPost(fn) {
18
- return agent.tracer.wrapFunctionNoSegment(fn, 'post')
14
+ function wrapPost(shim, fn) {
15
+ return function wrappedPost() {
16
+ var args = shim.argsToArray.apply(shim, arguments)
17
+ shim.bindCallbackSegment(args, shim.LAST)
18
+ return fn.apply(this, args)
19
+ }
19
20
  }
20
21
  )
21
22
  }
@@ -1,108 +1,104 @@
1
1
  'use strict'
2
2
 
3
- var shimmer = require('../../shimmer')
4
-
5
-
6
- module.exports = function initialize(agent, net) {
7
- shimmer.wrapMethod(net, 'net', ['connect', 'createConnection'], wrapCreate)
8
- function wrapCreate(original, name) {
3
+ module.exports = function initialize(agent, net, moduleName, shim) {
4
+ shim.wrap(net, ['connect', 'createConnection'], wrapCreate)
5
+ function wrapCreate(shim, fn, name) {
9
6
  return function wrappedCreateConnection() {
10
- if (!agent.getTransaction()) {
11
- return original.apply(this, arguments)
7
+ const segment = shim.getActiveSegment()
8
+ if (!segment) {
9
+ return fn.apply(this, arguments)
12
10
  }
13
11
 
14
- var segment = agent.tracer.createSegment('net.' + name)
15
- var sock = agent.tracer.bindFunction(original, segment, true).apply(this, arguments)
16
- wrapSocket(sock, segment)
12
+ const child = shim.createSegment('net.' + name, null, segment)
13
+ const sock = shim.applySegment(fn, child, true, this, arguments)
14
+ wrapSocket(sock, child)
17
15
  return sock
18
16
  }
19
17
  }
20
18
 
21
- net.Server.prototype.listen = agent.tracer.wrapFunctionNoSegment(
22
- net.Server.prototype.listen,
23
- 'net.Server.prototype.listen'
24
- )
25
-
26
- net.Server.prototype.close = agent.tracer.wrapFunctionNoSegment(
27
- net.Server.prototype.close,
28
- 'net.Server.prototype.close'
29
- )
30
-
31
- shimmer.wrapMethod(
32
- net.Server.prototype,
33
- 'net.Server.prototype',
34
- '_listen2',
35
- wrapListen2
36
- )
37
- shimmer.wrapMethod(
38
- net.Socket.prototype,
39
- 'net.Socket.prototype',
40
- 'connect',
41
- wrapConnect
42
- )
43
-
44
- function wrapListen2(original) {
19
+ const serverProto = net.Server.prototype
20
+
21
+ shim.wrap(serverProto, ['listen', 'close'], function wrapNoRecord(shim, fn) {
22
+ return function wrappedNoRecord() {
23
+ if (!shim.getActiveSegment()) {
24
+ return fn.apply(this, arguments)
25
+ }
26
+
27
+ const args = shim.argsToArray.apply(shim, arguments)
28
+ const cbIndex = args.length - 1
29
+
30
+ shim.bindSegment(args, cbIndex)
31
+
32
+ return fn.apply(this, args)
33
+ }
34
+ })
35
+
36
+ shim.wrap(serverProto, '_listen2', wrapListen2)
37
+ shim.wrap(net.Socket.prototype, 'connect', wrapConnect)
38
+
39
+ function wrapListen2(shim, fn) {
45
40
  return function wrappedListen2() {
46
- var segment = agent.tracer.getSegment()
47
- var emit = this.emit
41
+ const segment = shim.getActiveSegment()
42
+ const emit = this.emit
48
43
 
49
- if (!segment || !emit) return original.apply(this, arguments)
44
+ if (!segment || !emit) return fn.apply(this, arguments)
50
45
 
51
46
  this.emit = wrappedEmit
52
47
 
53
- return original.apply(this, arguments)
48
+ return fn.apply(this, arguments)
54
49
 
55
50
  function wrappedEmit(ev, socket) {
56
51
  if (ev !== 'connection' || !socket || !socket._handle) {
57
52
  return emit.apply(this, arguments)
58
53
  }
59
54
 
60
- var child = agent.tracer.createSegment('net.Server.onconnection', null, segment)
55
+ const child = shim.createSegment('net.Server.onconnection', segment)
61
56
 
62
57
  if (socket._handle.onread) {
63
- socket._handle.onread = agent.tracer.bindFunction(socket._handle.onread, child)
58
+ shim.bindSegment(socket._handle, 'onread', child)
64
59
  }
65
60
 
66
- return agent.tracer.bindFunction(emit, child, true).apply(this, arguments)
61
+ return shim.applySegment(emit, child, true, this, arguments)
67
62
  }
68
63
  }
69
64
  }
70
65
 
71
- function wrapConnect(original) {
66
+ function wrapConnect(shim, fn) {
72
67
  return function connectWrapper() {
73
- if (!agent.getTransaction()) return original.apply(this, arguments)
74
- var socket = this
75
- var args = normalizeConnectArgs(arguments)
76
- return agent.tracer.addSegment(
77
- 'net.Socket.connect',
78
- null,
79
- null,
80
- true,
81
- wrappedConnect
82
- )
83
-
84
- function wrappedConnect(child) {
85
- if (args[1]) args[1] = agent.tracer.bindFunction(args[1], child)
86
- var result = original.apply(socket, args)
87
- if (socket._handle) {
88
- socket._handle.onread = agent.tracer.bindFunction(socket._handle.onread, child)
89
- }
90
- agent.tracer.bindEmitter(socket, child)
91
- return result
68
+ if (!agent.getTransaction()) {
69
+ return fn.apply(this, arguments)
70
+ }
71
+
72
+ const socket = this
73
+ const args = normalizeConnectArgs(arguments)
74
+
75
+ const segment = shim.createSegment('net.Socket.connect')
76
+
77
+ if (args[1]) {
78
+ args[1] = shim.bindSegment(args[1], segment)
92
79
  }
80
+
81
+ const result = shim.applySegment(fn, segment, true, this, args)
82
+
83
+ if (socket._handle) {
84
+ shim.bindSegment(socket._handle, 'onread', segment)
85
+ }
86
+ shim.bindSegment(socket, 'emit', segment)
87
+
88
+ return result
93
89
  }
94
90
  }
95
91
 
96
92
  function wrapSocket(sock, segment) {
97
- shimmer.wrapMethod(sock, 'net.Socket', 'emit', function emitWrapper(emit) {
98
- return agent.tracer.bindFunction(emit, segment)
93
+ shim.wrap(sock, 'emit', function emitWrapper(shim, fn) {
94
+ return shim.bindSegment(fn, segment)
99
95
  })
100
96
  }
101
97
  }
102
98
 
103
99
  // taken from node master on 2013/10/30
104
100
  function normalizeConnectArgs(args) {
105
- var options = Object.create(null)
101
+ let options = Object.create(null)
106
102
 
107
103
  function toNumber(x) {
108
104
  return (x = Number(x)) >= 0 ? x : false
@@ -121,6 +117,6 @@ function normalizeConnectArgs(args) {
121
117
  }
122
118
  }
123
119
 
124
- var cb = args[args.length - 1]
120
+ const cb = args[args.length - 1]
125
121
  return typeof cb === 'function' ? [options, cb] : [options]
126
122
  }
@@ -1,60 +1,99 @@
1
1
  'use strict'
2
2
 
3
- var wrap = require('../../shimmer').wrapMethod
4
- var psemver = require('../../util/process-version')
5
-
6
3
  module.exports = initialize
7
4
 
8
- function initialize(agent, timers) {
9
- // As of iojs 1.6.3 all timers are on the global object, and do
10
- // not need a require('timers') call to access them
11
- if (timers !== global && psemver.satisfies('>=1.6.3') &&
12
- global.setTimeout && !global.setTimeout.__NR_original) {
13
- initialize(agent, global)
5
+ function initialize(agent, timers, moduleName, shim) {
6
+ const processMethods = ['nextTick', '_nextDomainTick', '_tickDomainCallback']
7
+
8
+ shim.wrap(
9
+ process,
10
+ processMethods,
11
+ function wrapProcess(shim, fn) {
12
+ return function wrappedProcess() {
13
+ const segment = shim.getActiveSegment()
14
+ if (!segment) {
15
+ return fn.apply(this, arguments)
16
+ }
17
+
18
+ // Manual copy because helper methods add significant overhead in some usages
19
+ var len = arguments.length
20
+ var args = new Array(len)
21
+ for (var i = 0; i < len; ++i) {
22
+ args[i] = arguments[i]
23
+ }
24
+
25
+ shim.bindSegment(args, shim.FIRST, segment)
26
+
27
+ return fn.apply(this, args)
28
+ }
29
+ }
30
+ )
31
+
32
+ instrumentTimerMethods(timers)
33
+
34
+ // If we need to instrument separate references to timers on the global object,
35
+ // do that now.
36
+ if (!shim.isWrapped(global.setTimeout)) {
37
+ instrumentTimerMethods(global)
14
38
  }
15
39
 
16
- var processMethods = ['nextTick', '_nextDomainTick', '_tickDomainCallback']
40
+ function instrumentTimerMethods(nodule) {
41
+ const asynchronizers = [
42
+ 'setTimeout',
43
+ 'setInterval'
44
+ ]
17
45
 
18
- wrap(process, 'process', processMethods, function bindProcess(original, method) {
19
- return agent.tracer.wrapFunctionFirstNoSegment(original, method)
20
- })
46
+ shim.record(nodule, asynchronizers, recordAsynchronizers)
21
47
 
22
- var asynchronizers = [
23
- 'setTimeout',
24
- 'setInterval'
25
- ]
48
+ // We don't want to create segments for setImmediate calls, as the
49
+ // object allocation may incur too much overhead in some situations
50
+ shim.wrap(nodule, 'setImmediate', wrapSetImmediate)
26
51
 
27
- wrap(timers, 'timers', asynchronizers, function wrapTimers(original, method) {
28
- return agent.tracer.wrapFunctionFirst('timers.' + method, null, original)
29
- })
52
+ shim.wrap(nodule, 'clearTimeout', wrapClearTimeout)
30
53
 
31
- // We don't want to create segments for setImmediate calls, as the
32
- // object allocation may incur too much overhead in some situations
33
- var uninstrumented = [
34
- 'setImmediate'
35
- ]
54
+ makeWrappedPromisifyCompatible(shim, nodule)
55
+ }
36
56
 
37
- wrap(timers, 'timers', uninstrumented, function wrapUninstrumented(original, method) {
38
- return agent.tracer.wrapFunctionFirstNoSegment(original, method)
39
- })
57
+ function wrapSetImmediate(shim, fn) {
58
+ return function wrappedSetImmediate() {
59
+ const args = shim.argsToArray.apply(shim, arguments)
60
+ shim.bindSegment(args, shim.FIRST)
40
61
 
41
- var clearTimeouts = ['clearTimeout']
62
+ return fn.apply(this, args)
63
+ }
64
+ }
42
65
 
43
- wrap(timers, 'timers', clearTimeouts, function wrapClear(original) {
44
- return function wrappedClear(timer) {
45
- var segment
66
+ function wrapClearTimeout(shim, fn) {
67
+ return function wrappedClearTimeout(timer) {
46
68
  if (timer && timer._onTimeout) {
47
- segment = agent.tracer.getSegmentFromWrapped(timer._onTimeout)
48
- timer._onTimeout = agent.tracer.getOriginal(timer._onTimeout)
69
+ const segment = timer._onTimeout.__NR_segment
70
+ if (segment) {
71
+ segment.ignore = true
72
+ }
49
73
  }
50
74
 
51
- if (timer && timer._onImmediate) {
52
- timer._onImmediate = agent.tracer.getOriginal(timer._onImmediate)
53
- }
75
+ return fn.apply(this, arguments)
76
+ }
77
+ }
78
+
79
+ function recordAsynchronizers(shim, fn, name) {
80
+ return {name: 'timers.' + name, callback: shim.FIRST}
81
+ }
82
+ }
83
+
84
+ function makeWrappedPromisifyCompatible(shim, timers) {
85
+ const originalSetTimout = shim.getOriginal(timers.setTimeout)
86
+ Object.getOwnPropertySymbols(originalSetTimout).forEach((symbol) => {
87
+ timers.setTimeout[symbol] = originalSetTimout[symbol]
88
+ })
54
89
 
55
- if (segment) segment.ignore = true
90
+ const originalSetInterval = shim.getOriginal(timers.setInterval)
91
+ Object.getOwnPropertySymbols(originalSetInterval).forEach((symbol) => {
92
+ timers.setInterval[symbol] = originalSetInterval[symbol]
93
+ })
56
94
 
57
- return original.apply(this, arguments)
58
- }
95
+ const originalSetImmediate = shim.getOriginal(timers.setImmediate)
96
+ Object.getOwnPropertySymbols(originalSetImmediate).forEach((symbol) => {
97
+ timers.setImmediate[symbol] = originalSetImmediate[symbol]
59
98
  })
60
99
  }
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- var wrap = require('../../shimmer').wrapMethod
3
+ const recorder = require('../../metrics/recorders/generic')
4
4
 
5
5
  module.exports = initialize
6
6
 
@@ -14,22 +14,36 @@ var methods = [
14
14
  'unzip'
15
15
  ]
16
16
 
17
- function initialize(agent, zlib) {
18
- var noSegment = agent.tracer.wrapFunctionNoSegment.bind(agent.tracer)
17
+ function initialize(agent, zlib, moduleName, shim) {
18
+ shim.record(zlib, methods, recordZLib)
19
+
19
20
  if (zlib.Deflate && zlib.Deflate.prototype) {
20
21
  var proto = Object.getPrototypeOf(zlib.Deflate.prototype)
21
22
  if (proto._transform) {
22
23
  // streams2
23
- wrap(proto, 'zlib', '_transform', noSegment)
24
+ shim.wrap(proto, '_transform', wrapNoSegment)
24
25
  } else if (proto.write && proto.flush && proto.end) {
25
26
  // plain ol' streams
26
- wrap(proto, 'zlib', ['write', 'flush', 'end'], noSegment)
27
+ shim.wrap(proto, ['write', 'flush', 'end'], wrapNoSegment)
27
28
  }
28
29
  }
29
30
 
30
- wrap(zlib, 'zlib', methods, segment)
31
+ function recordZLib(shim, fn, name) {
32
+ return {name: `zlib.${name}`, callback: shim.LAST, recorder}
33
+ }
34
+ }
35
+
36
+ function wrapNoSegment(shim, fn) {
37
+ return function wrappedZLibNoSegment() {
38
+ if (!shim.getActiveSegment()) {
39
+ return fn.apply(this, arguments)
40
+ }
41
+
42
+ const args = shim.argsToArray.apply(shim, arguments)
43
+ const cbIndex = args.length - 1
44
+
45
+ shim.bindSegment(args, cbIndex)
31
46
 
32
- function segment(fn, method) {
33
- return agent.tracer.wrapFunctionLast('zlib.' + method, null, fn)
47
+ return fn.apply(this, args)
34
48
  }
35
49
  }