newrelic 13.3.2 → 13.4.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 (111) hide show
  1. package/NEWS.md +43 -0
  2. package/THIRD_PARTY_NOTICES.md +11 -11
  3. package/esm-loader.mjs +2 -2
  4. package/lib/attributes.js +4 -4
  5. package/lib/collector/facts.js +1 -1
  6. package/lib/collector/http-agents.js +2 -2
  7. package/lib/collector/parse-response.js +9 -12
  8. package/lib/collector/remote-method.js +4 -5
  9. package/lib/config/formatters.js +2 -3
  10. package/lib/config/index.js +6 -6
  11. package/lib/harvester.js +1 -1
  12. package/lib/header-processing.js +3 -3
  13. package/lib/instrumentation/@node-redis/client.js +1 -1
  14. package/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js +2 -2
  15. package/lib/instrumentation/aws-sdk/v3/common.js +5 -5
  16. package/lib/instrumentation/aws-sdk/v3/dynamodb.js +4 -4
  17. package/lib/instrumentation/aws-sdk/v3/sns.js +9 -9
  18. package/lib/instrumentation/aws-sdk/v3/sqs.js +6 -6
  19. package/lib/instrumentation/core/http-outbound.js +1 -2
  20. package/lib/instrumentation/fastify/spec-builders.js +11 -11
  21. package/lib/instrumentation/fastify.js +4 -4
  22. package/lib/instrumentation/memcached.js +4 -4
  23. package/lib/instrumentation/mongodb.js +2 -2
  24. package/lib/instrumentation/undici.js +3 -3
  25. package/lib/instrumentations.js +0 -2
  26. package/lib/llm-events/aws-bedrock/bedrock-response.js +6 -6
  27. package/lib/llm-events/aws-bedrock/converse-stream-handler.js +1 -1
  28. package/lib/llm-events/aws-bedrock/stream-handler.js +4 -4
  29. package/lib/metrics/index.js +2 -2
  30. package/lib/metrics/normalizer/rule.js +1 -1
  31. package/lib/metrics/normalizer.js +4 -5
  32. package/lib/metrics/recorders/message-transaction.js +3 -3
  33. package/lib/otel/context-manager.js +4 -4
  34. package/lib/otel/metrics/index.js +3 -3
  35. package/lib/otel/setup.js +6 -0
  36. package/lib/otel/trace-propagator.js +1 -1
  37. package/lib/otel/traces/index.js +1 -1
  38. package/lib/prioritized-attributes.js +2 -2
  39. package/lib/serverless/aws-lambda.js +4 -4
  40. package/lib/shim/datastore-shim.js +1 -1
  41. package/lib/shim/message-shim/consume.js +1 -1
  42. package/lib/shim/message-shim/subscribe-consume.js +1 -2
  43. package/lib/shim/promise-shim.js +1 -3
  44. package/lib/shim/shim.js +3 -4
  45. package/lib/shim/transaction-shim.js +0 -1
  46. package/lib/shim/webframework-shim/common.js +2 -4
  47. package/lib/shim/webframework-shim/middleware.js +8 -8
  48. package/lib/spans/span-context.js +1 -1
  49. package/lib/spans/span-event-aggregator.js +2 -2
  50. package/lib/spans/span-event.js +6 -5
  51. package/lib/spans/streaming-span-attributes.js +1 -1
  52. package/lib/spans/streaming-span-event-aggregator.js +1 -2
  53. package/lib/stats/index.js +1 -1
  54. package/lib/subscriber-configs.js +2 -0
  55. package/lib/subscribers/amqplib/accept-message.js +14 -0
  56. package/lib/subscribers/amqplib/callback-model.js +39 -0
  57. package/lib/subscribers/amqplib/channel-model.js +39 -0
  58. package/lib/subscribers/amqplib/config.js +695 -0
  59. package/lib/subscribers/amqplib/connect.js +74 -0
  60. package/lib/subscribers/amqplib/consume.js +54 -0
  61. package/lib/subscribers/amqplib/get-cb.js +16 -0
  62. package/lib/subscribers/amqplib/get.js +50 -0
  63. package/lib/subscribers/amqplib/purge-queue-cb.js +16 -0
  64. package/lib/subscribers/amqplib/purge-queue.js +37 -0
  65. package/lib/subscribers/amqplib/send-message.js +44 -0
  66. package/lib/subscribers/amqplib/send-or-enqueue.js +20 -0
  67. package/lib/subscribers/amqplib/utils.js +53 -0
  68. package/lib/subscribers/application-logs.js +1 -1
  69. package/lib/subscribers/base.js +167 -9
  70. package/lib/subscribers/cassandra-driver/client-batch.js +49 -0
  71. package/lib/subscribers/cassandra-driver/client-connect.js +35 -0
  72. package/lib/subscribers/cassandra-driver/client-each-row.js +36 -0
  73. package/lib/subscribers/cassandra-driver/client-execute.js +36 -0
  74. package/lib/subscribers/cassandra-driver/client-shutdown.js +32 -0
  75. package/lib/subscribers/cassandra-driver/config.js +145 -0
  76. package/lib/subscribers/cassandra-driver/legacy-client-batch.js +22 -0
  77. package/lib/subscribers/cassandra-driver/legacy-client-connect.js +22 -0
  78. package/lib/subscribers/cassandra-driver/legacy-client-each-row.js +22 -0
  79. package/lib/subscribers/cassandra-driver/legacy-client-execute.js +21 -0
  80. package/lib/subscribers/cassandra-driver/legacy-client-shutdown.js +32 -0
  81. package/lib/subscribers/create-config.js +2 -4
  82. package/lib/subscribers/db-query.js +5 -1
  83. package/lib/subscribers/message-consumer.js +146 -0
  84. package/lib/subscribers/message-producer.js +60 -0
  85. package/lib/subscribers/meta-subscriber.js +69 -0
  86. package/lib/subscribers/openai/base.js +27 -1
  87. package/lib/subscribers/openai/config.js +6 -6
  88. package/lib/subscribers/openai/utils.js +9 -11
  89. package/lib/subscribers/propagation.js +43 -0
  90. package/lib/timer.js +1 -1
  91. package/lib/transaction/dt-payload.js +1 -1
  92. package/lib/transaction/handle.js +8 -9
  93. package/lib/transaction/name-state.js +11 -11
  94. package/lib/transaction/trace/segment.js +2 -3
  95. package/lib/util/attribute-types.js +1 -1
  96. package/lib/util/byte-limit.js +1 -1
  97. package/lib/util/cat.js +13 -13
  98. package/lib/util/flatten.js +2 -3
  99. package/lib/util/is-absolute-path.js +1 -1
  100. package/lib/util/is-string.js +15 -0
  101. package/lib/util/logger.js +6 -6
  102. package/lib/util/stream-sink.js +1 -1
  103. package/lib/utilization/docker-info.js +4 -3
  104. package/lib/w3c/traceparent.js +1 -1
  105. package/package.json +2 -2
  106. package/lib/instrumentation/amqplib/amqplib.js +0 -122
  107. package/lib/instrumentation/amqplib/channel-model.js +0 -124
  108. package/lib/instrumentation/amqplib/channel.js +0 -72
  109. package/lib/instrumentation/amqplib/nr-hooks.js +0 -21
  110. package/lib/instrumentation/amqplib/utils.js +0 -143
  111. package/lib/instrumentation/cassandra-driver.js +0 -131
@@ -1,122 +0,0 @@
1
- /*
2
- * Copyright 2020 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
-
8
- const {
9
- OperationSpec,
10
- params: { DatastoreParameters }
11
- } = require('../../shim/specs')
12
- const wrapModel = require('./channel-model')
13
- const { setCallback, parseConnectionArgs } = require('./utils')
14
- const wrapChannel = require('./channel')
15
- const { amqpConnection } = require('../../symbols')
16
-
17
- module.exports.instrumentPromiseAPI = instrumentChannelAPI
18
- module.exports.instrumentCallbackAPI = instrumentCallbackAPI
19
-
20
- /**
21
- * Register all the necessary instrumentation when using
22
- * promise based methods
23
- *
24
- * @param {Shim} shim instance of shim
25
- * @param {object} amqp amqplib object
26
- */
27
- function instrumentChannelAPI(shim, amqp) {
28
- instrumentAMQP(shim, amqp, true)
29
- // 👀 take note the model is channel not callback 👀
30
- const model = shim.require('./lib/channel_model')
31
- wrapModel(shim, model, true)
32
- }
33
-
34
- /**
35
- * Register all the necessary instrumentation when using
36
- * callback based methods
37
- *
38
- * @param {Shim} shim instance of shim
39
- * @param {object} amqp amqplib object
40
- */
41
- function instrumentCallbackAPI(shim, amqp) {
42
- instrumentAMQP(shim, amqp, false)
43
- // 👀 take note the model is callback not channel 👀
44
- const model = shim.require('./lib/callback_model')
45
- wrapModel(shim, model, false)
46
- }
47
-
48
- /**
49
- *
50
- * Instruments the connect method and channel prototype of amqplib
51
- *
52
- * @param {Shim} shim instance of shim
53
- * @param {object} amqp amqplib object
54
- * @param {boolean} promiseMode is this promise based?
55
- * @returns {void}
56
- */
57
- function instrumentAMQP(shim, amqp, promiseMode) {
58
- if (!amqp || !amqp.connect) {
59
- shim.logger.debug("This module is not the amqplib we're looking for.")
60
- return
61
- }
62
-
63
- if (shim.isWrapped(amqp.connect)) {
64
- shim.logger.trace('This module has already been instrumented, skipping.')
65
- return
66
- }
67
- shim.setLibrary(shim.RABBITMQ)
68
-
69
- wrapConnect(shim, amqp, promiseMode)
70
- wrapChannel(shim)
71
- }
72
-
73
- /**
74
- *
75
- * Instruments the connect method
76
- * We have to both wrap and record because
77
- * we need the host/port for all subsequent calls on the model/channel
78
- * but record only completes in an active transaction
79
- *
80
- * @param {Shim} shim instance of shim
81
- * @param {object} amqp amqplib object
82
- * @param {boolean} promiseMode is this promise based?
83
- */
84
- function wrapConnect(shim, amqp, promiseMode) {
85
- shim.wrap(amqp, 'connect', function wrapConnect(shim, connect) {
86
- return function wrappedConnect(...args) {
87
- const [connArgs] = args
88
- const params = parseConnectionArgs({ shim, connArgs })
89
- const cb = args[args.length - 1]
90
- if (!promiseMode) {
91
- args[args.length - 1] = function wrappedCallback(...cbArgs) {
92
- const [, c] = cbArgs
93
- c.connection[amqpConnection] = params
94
- return cb.apply(this, cbArgs)
95
- }
96
- }
97
-
98
- const result = connect.apply(this, args)
99
- if (promiseMode) {
100
- return result.then((c) => {
101
- c.connection[amqpConnection] = params
102
- return c
103
- })
104
- }
105
- return result
106
- }
107
- })
108
-
109
- shim.record(amqp, 'connect', function recordConnect(shim, connect, name, args) {
110
- const [connArgs] = args
111
- const params = parseConnectionArgs({ shim, connArgs })
112
- return new OperationSpec({
113
- name: 'amqplib.connect',
114
- callback: setCallback(shim, promiseMode),
115
- promise: promiseMode,
116
- parameters: new DatastoreParameters({
117
- host: params.host,
118
- port_path_or_id: params.port
119
- })
120
- })
121
- })
122
- }
@@ -1,124 +0,0 @@
1
- /*
2
- * Copyright 2024 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
- const { MessageSpec, MessageSubscribeSpec, RecorderSpec } = require('../../shim/specs')
8
- const { amqpConnection } = require('../../symbols')
9
- const CHANNEL_METHODS = [
10
- 'close',
11
- 'open',
12
- 'assertQueue',
13
- 'checkQueue',
14
- 'deleteQueue',
15
- 'bindQueue',
16
- 'unbindQueue',
17
- 'assertExchange',
18
- 'checkExchange',
19
- 'deleteExchange',
20
- 'bindExchange',
21
- 'unbindExchange',
22
- 'cancel',
23
- 'prefetch',
24
- 'recover'
25
- ]
26
- const { describeMessage, setCallback, getParametersFromMessage, TEMP_RE } = require('./utils')
27
-
28
- /**
29
- *
30
- * Instruments the relevant channel callback_model or channel_model.
31
- *
32
- * @param {Shim} shim instance of shim
33
- * @param {object} Model either channel or callback model
34
- * @param {boolean} promiseMode is this promise based?
35
- */
36
- module.exports = function wrapModel(shim, Model, promiseMode) {
37
- if (!Model.Channel?.prototype) {
38
- shim.logger.debug(
39
- `Could not get ${promiseMode ? 'promise' : 'callback'} model Channel to instrument.`
40
- )
41
- return
42
- }
43
-
44
- const proto = Model.Channel.prototype
45
- if (shim.isWrapped(proto.consume)) {
46
- shim.logger.trace(`${promiseMode ? 'promise' : 'callback'} model already instrumented.`)
47
- return
48
- }
49
-
50
- recordChannelMethods({ shim, proto, promiseMode })
51
- recordPurge({ shim, proto, promiseMode })
52
- recordGet({ shim, proto, promiseMode })
53
- recordConsume({ shim, proto, promiseMode })
54
- }
55
-
56
- /**
57
- * Record spans for common methods on channel
58
- *
59
- * @param {Channel} proto prototype of Model.Channel
60
- */
61
- function recordChannelMethods({ shim, proto, promiseMode }) {
62
- shim.record(proto, CHANNEL_METHODS, function recordChannelMethod(shim, fn, name) {
63
- return new RecorderSpec({
64
- name: 'Channel#' + name,
65
- callback: setCallback(shim, promiseMode),
66
- promise: promiseMode
67
- })
68
- })
69
- }
70
-
71
- function recordPurge({ shim, proto, promiseMode }) {
72
- shim.recordPurgeQueue(proto, 'purgeQueue', function purge(shim, fn, name, args) {
73
- let queue = args[0]
74
- if (TEMP_RE.test(queue)) {
75
- queue = null
76
- }
77
- return new MessageSpec({
78
- queue,
79
- promise: promiseMode,
80
- callback: setCallback(shim, promiseMode)
81
- })
82
- })
83
- }
84
-
85
- function recordGet({ shim, proto, promiseMode }) {
86
- shim.recordConsume(proto, 'get', function wrapGet() {
87
- const { host, port } = this?.connection?.[amqpConnection] || {}
88
- return new MessageSpec({
89
- destinationName: shim.FIRST,
90
- callback: setCallback(shim, promiseMode),
91
- promise: promiseMode,
92
- after: function handleConsumedMessage({ shim, result, args, segment }) {
93
- if (!shim.agent.config.message_tracer.segment_parameters.enabled) {
94
- shim.logger.trace('Not capturing segment parameters')
95
- return
96
- }
97
-
98
- // the message is the param when using the promised based model
99
- const message = promiseMode ? result : args?.[1]
100
- if (!message) {
101
- shim.logger.trace('No results from consume.')
102
- return null
103
- }
104
- const parameters = getParametersFromMessage({ message, host, port })
105
- shim.copySegmentParameters(segment, parameters)
106
- }
107
- })
108
- })
109
- }
110
-
111
- function recordConsume({ shim, proto, promiseMode }) {
112
- shim.recordSubscribedConsume(proto, 'consume', function consume() {
113
- const { host, port } = this?.connection?.[amqpConnection] || {}
114
- return new MessageSubscribeSpec({
115
- name: 'amqplib.Channel#consume',
116
- queue: shim.FIRST,
117
- consumer: shim.SECOND,
118
- promise: promiseMode,
119
- parameters: { host, port },
120
- callback: promiseMode ? null : shim.FOURTH,
121
- messageHandler: describeMessage({ host, port })
122
- })
123
- })
124
- }
@@ -1,72 +0,0 @@
1
- /*
2
- * Copyright 2024 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
- const { MessageSpec } = require('../../shim/specs')
8
- const { amqpConnection } = require('../../symbols')
9
- const { getParameters, TEMP_RE } = require('./utils')
10
-
11
- /**
12
- *
13
- * Instruments the sendOrEnqueue and sendMessage methods of the ampqlib channel.
14
- *
15
- * @param {Shim} shim instance of shim
16
- */
17
- module.exports = function wrapChannel(shim) {
18
- const libChannel = shim.require('./lib/channel')
19
- if (!libChannel?.Channel?.prototype) {
20
- shim.logger.debug('Could not get Channel class to instrument.')
21
- return
22
- }
23
-
24
- const proto = libChannel.Channel.prototype
25
- if (shim.isWrapped(proto.sendMessage)) {
26
- shim.logger.trace('Channel already instrumented.')
27
- return
28
- }
29
- shim.logger.trace('Instrumenting basic Channel class.')
30
-
31
- shim.wrap(proto, 'sendOrEnqueue', function wrapSendOrEnqueue(shim, fn) {
32
- if (!shim.isFunction(fn)) {
33
- return fn
34
- }
35
-
36
- return function wrappedSendOrEnqueue(...args) {
37
- const segment = shim.getSegment()
38
- const cb = args[args.length - 1]
39
- if (!shim.isFunction(cb) || !segment) {
40
- shim.logger.debug({ cb: !!cb, segment: !!segment }, 'Not binding sendOrEnqueue callback')
41
- return fn.apply(this, args)
42
- }
43
-
44
- shim.logger.trace('Binding sendOrEnqueue callback to %s', segment.name)
45
- args[args.length - 1] = shim.bindSegment(cb, segment)
46
- return fn.apply(this, args)
47
- }
48
- })
49
-
50
- shim.recordProduce(proto, 'sendMessage', recordSendMessage)
51
- }
52
-
53
- function recordSendMessage(shim, fn, n, args) {
54
- const fields = args[0]
55
- if (!fields) {
56
- return null
57
- }
58
- const isDefault = fields.exchange === ''
59
- let exchange = 'Default'
60
- if (!isDefault) {
61
- exchange = TEMP_RE.test(fields.exchange) ? null : fields.exchange
62
- }
63
- const { host, port } = this?.connection?.[amqpConnection] || {}
64
-
65
- return new MessageSpec({
66
- destinationName: exchange,
67
- destinationType: shim.EXCHANGE,
68
- routingKey: fields.routingKey,
69
- headers: fields.headers,
70
- parameters: getParameters({ parameters: Object.create(null), fields, host, port })
71
- })
72
- }
@@ -1,21 +0,0 @@
1
- /*
2
- * Copyright 2023 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
- const amqplib = require('./amqplib')
8
- const InstrumentationDescriptor = require('../../instrumentation-descriptor')
9
-
10
- module.exports = [
11
- {
12
- moduleName: 'amqplib/callback_api',
13
- type: InstrumentationDescriptor.TYPE_MESSAGE,
14
- onRequire: amqplib.instrumentCallbackAPI
15
- },
16
- {
17
- moduleName: 'amqplib',
18
- type: InstrumentationDescriptor.TYPE_MESSAGE,
19
- onRequire: amqplib.instrumentPromiseAPI
20
- }
21
- ]
@@ -1,143 +0,0 @@
1
- /*
2
- * Copyright 2024 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
- const {
8
- MessageSpec,
9
- params: { QueueMessageParameters }
10
- } = require('../../shim/specs')
11
- const TEMP_RE = /^amq\./
12
-
13
- /**
14
- * Wrapper around message handler to pass host/port
15
- *
16
- * @param {object} params to function
17
- * @param {string} params.host hostname
18
- * @param {number} params.port port
19
- * @returns {function} message handler
20
- */
21
- function describeMessage({ host, port }) {
22
- /**
23
- * Extracts the appropriate messageHandler parameters for the consume method.
24
- *
25
- * @param {Shim} shim instance of shim
26
- * @param {Array} args arguments passed to the consume method
27
- * @returns {object} message params
28
- */
29
- return function messageHandler(shim, args) {
30
- const [message] = args
31
-
32
- if (!message?.properties) {
33
- shim.logger.debug({ message }, 'Failed to find message in consume arguments.')
34
- return null
35
- }
36
-
37
- const parameters = getParametersFromMessage({ message, host, port })
38
- let exchangeName = message?.fields?.exchange || 'Default'
39
-
40
- if (TEMP_RE.test(exchangeName)) {
41
- exchangeName = null
42
- }
43
-
44
- return new MessageSpec({
45
- destinationName: exchangeName,
46
- destinationType: shim.EXCHANGE,
47
- routingKey: message?.fields?.routingKey,
48
- headers: message.properties.headers,
49
- parameters
50
- })
51
- }
52
- }
53
-
54
- /**
55
- * Sets the relevant message parameters
56
- *
57
- * @param {object} params to function
58
- * @param {object} params.parameters object used to store the message parameters
59
- * @param {object} params.fields fields from the sendMessage method
60
- * @param {string} params.host hostname
61
- * @param {number} params.port port
62
- * @returns {QueueMessageParameters} parameters updated parameters
63
- */
64
- function getParameters({ parameters, fields, host, port }) {
65
- if (fields.routingKey) {
66
- parameters.routing_key = fields.routingKey
67
- }
68
- if (fields.correlationId) {
69
- parameters.correlation_id = fields.correlationId
70
- }
71
- if (fields.replyTo) {
72
- parameters.reply_to = fields.replyTo
73
- }
74
-
75
- if (host) {
76
- parameters.host = host
77
- }
78
-
79
- if (port) {
80
- parameters.port = port
81
- }
82
-
83
- return new QueueMessageParameters(parameters)
84
- }
85
-
86
- /**
87
- * Sets the QueueMessageParameters from the amqp message
88
- *
89
- * @param {object} params to function
90
- * @param {object} params.message queue message
91
- * @param {string} params.host host
92
- * @param {number} params.port port
93
- * @returns {QueueMessageParameters} parameters from message
94
- */
95
- function getParametersFromMessage({ message, host, port }) {
96
- const parameters = Object.create(null)
97
- getParameters({ parameters, fields: message.fields, host, port })
98
- getParameters({ parameters, fields: message.properties })
99
- return parameters
100
- }
101
-
102
- /**
103
- * Helper to set the appropriate value of the callback property
104
- * in the spec. If it's a promise set to null otherwise set it to `shim.LAST`
105
- *
106
- * @param {Shim} shim instance of shim
107
- * @param {boolean} promiseMode is this promise based?
108
- * @returns {string|null} appropriate value
109
- */
110
- function setCallback(shim, promiseMode) {
111
- return promiseMode ? null : shim.LAST
112
- }
113
-
114
- /**
115
- * Parses the connection args to return host/port
116
- *
117
- * @param {string|object} connArgs connection arguments
118
- * @returns {object} {host, port }
119
- */
120
- function parseConnectionArgs({ shim, connArgs }) {
121
- const params = {}
122
- if (shim.isString(connArgs)) {
123
- connArgs = new URL(connArgs)
124
- params.host = connArgs.hostname
125
- if (connArgs.port) {
126
- params.port = parseInt(connArgs.port, 10)
127
- }
128
- } else {
129
- params.port = connArgs.port || (connArgs.protocol === 'amqp' ? 5672 : 5671)
130
- params.host = connArgs.hostname
131
- }
132
-
133
- return params
134
- }
135
-
136
- module.exports = {
137
- describeMessage,
138
- getParameters,
139
- getParametersFromMessage,
140
- parseConnectionArgs,
141
- setCallback,
142
- TEMP_RE
143
- }
@@ -1,131 +0,0 @@
1
- /*
2
- * Copyright 2020 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- 'use strict'
7
-
8
- const semver = require('semver')
9
- const { OperationSpec, QuerySpec } = require('../shim/specs')
10
-
11
- /**
12
- * Instruments the `cassandra-driver` module, function that is
13
- * passed to `onRequire` when instantiating instrumentation.
14
- *
15
- * @param {object} _agent - NewRelic agent
16
- * @param {object} cassandra - The cassandra-driver library definition
17
- * @param {string} _moduleName - String representation of require/import path
18
- * @param {object} shim - shim for instrumentation
19
- */
20
- module.exports = function initialize(_agent, cassandra, _moduleName, shim) {
21
- const cassandraVersion = shim.pkgVersion
22
-
23
- shim.setDatastore(shim.CASSANDRA)
24
-
25
- const ClientProto = cassandra.Client.prototype
26
- const RequestExecutionProto = shim.require('./lib/request-execution.js').prototype
27
-
28
- shim.recordOperation(
29
- ClientProto,
30
- ['connect', 'shutdown'],
31
- function operationSpec(shim, _fn, name) {
32
- return new OperationSpec({ callback: shim.LAST, name, promise: true })
33
- }
34
- )
35
-
36
- if (semver.satisfies(cassandraVersion, '>=4.4.0')) {
37
- shim.recordQuery(
38
- ClientProto,
39
- '_execute',
40
- new QuerySpec({
41
- query: shim.FIRST,
42
- callback: shim.LAST,
43
- promise: true
44
- })
45
- )
46
-
47
- shim.wrap(
48
- RequestExecutionProto,
49
- '_sendOnConnection',
50
- function wrapSendOnConnection(shim, _sendOnConnection) {
51
- return function wrappedSendOnConnection() {
52
- shim.captureInstanceAttributes(
53
- this._connection.address,
54
- this._connection.port,
55
- this._connection.keyspace
56
- )
57
-
58
- return _sendOnConnection.apply(this, arguments)
59
- }
60
- }
61
- )
62
- } else {
63
- shim.recordQuery(
64
- ClientProto,
65
- '_innerExecute',
66
- new QuerySpec({
67
- query: shim.FIRST,
68
- callback: shim.LAST,
69
- promise: true
70
- })
71
- )
72
-
73
- shim.wrap(RequestExecutionProto, 'start', function wrapStart(shim, start) {
74
- return function wrappedStart(...args) {
75
- const parent = shim.getSegment()
76
- const self = this
77
-
78
- /**
79
- * In older versions of cassandra-driver, we can't rely on RequestExecution._sendOnConnection,
80
- * so instead we use the callback passed to RequestExecution.start as a sort of hook point,
81
- * because we know for sure that the connection was set and in scope right before the callback
82
- * is executed.
83
- *
84
- * We also have to set the active segment to the RequestExecution.start's segment to ensure that
85
- * we're adding the connection attributes to the correct segment.
86
- *
87
- * See: https://github.com/datastax/nodejs-driver/blob/v3.4.0/lib/request-execution.js#L51
88
- */
89
- args[0] = shim.wrap(args[0], function wrapGetHostCallback(shim, getHostCallback) {
90
- return function wrappedGetHostCallback() {
91
- shim.setActiveSegment(parent)
92
-
93
- shim.captureInstanceAttributes(
94
- self._connection.address,
95
- self._connection.port,
96
- self._connection.keyspace
97
- )
98
- return getHostCallback.apply(this, arguments)
99
- }
100
- })
101
-
102
- return start.apply(this, args)
103
- }
104
- })
105
- }
106
-
107
- shim.recordBatchQuery(
108
- ClientProto,
109
- 'batch',
110
- new QuerySpec({
111
- query: findBatchQueryArg,
112
- callback: shim.LAST,
113
- promise: true
114
- })
115
- )
116
- }
117
-
118
- /**
119
- * Given the arguments for Cassandra's `batch` method, this finds the first
120
- * query in the batch.
121
- *
122
- * @param {object} _shim - shim for instrumentation
123
- * @param {Function} _batch - original batch function
124
- * @param {string} _fnName - the function name (batch)
125
- * @param {Array} args - original arguments passed to the batch function
126
- * @returns {string} The query for this batch request.
127
- */
128
- function findBatchQueryArg(_shim, _batch, _fnName, args) {
129
- const sql = (args[0] && args[0][0]) || ''
130
- return sql.query || sql
131
- }