newrelic 11.13.0 → 11.15.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 (35) hide show
  1. package/NEWS.md +78 -25
  2. package/README.md +1 -1
  3. package/THIRD_PARTY_NOTICES.md +2 -2
  4. package/api.js +1 -1
  5. package/lib/errors/index.js +1 -0
  6. package/lib/instrumentation/cassandra-driver.js +3 -1
  7. package/lib/instrumentation/mongodb/common.js +46 -74
  8. package/lib/instrumentation/mongodb/v2-mongo.js +10 -6
  9. package/lib/instrumentation/mongodb/v3-mongo.js +7 -10
  10. package/lib/instrumentation/mongodb/v4-mongo.js +24 -20
  11. package/lib/instrumentation/pg.js +3 -3
  12. package/lib/instrumentation-descriptor.js +215 -0
  13. package/lib/instrumentation-tracker.js +222 -0
  14. package/lib/instrumentations.js +30 -30
  15. package/lib/llm-events/langchain/event.js +0 -2
  16. package/lib/llm-events/openai/chat-completion-summary.js +0 -1
  17. package/lib/llm-events/openai/event.js +0 -3
  18. package/lib/shim/conglomerate-shim.js +15 -14
  19. package/lib/shim/datastore-shim.js +18 -15
  20. package/lib/shim/index.js +8 -10
  21. package/lib/shim/message-shim/consume.js +1 -2
  22. package/lib/shim/message-shim/index.js +19 -39
  23. package/lib/shim/message-shim/subscribe-consume.js +3 -4
  24. package/lib/shim/promise-shim.js +32 -27
  25. package/lib/shim/shim.js +10 -16
  26. package/lib/shim/specs/wrap.js +2 -10
  27. package/lib/shim/webframework-shim/common.js +0 -20
  28. package/lib/shim/webframework-shim/index.js +18 -44
  29. package/lib/shim/webframework-shim/middleware-mounter.js +1 -9
  30. package/lib/shim/webframework-shim/middleware.js +7 -6
  31. package/lib/shimmer.js +83 -67
  32. package/lib/symbols.js +0 -2
  33. package/lib/util/idgen.js +31 -0
  34. package/package.json +6 -6
  35. package/lib/shim/constants.js +0 -42
package/NEWS.md CHANGED
@@ -1,39 +1,92 @@
1
- ### v11.13.0 (2024-03-13)
1
+ ### v11.15.0 (2024-04-09)
2
2
 
3
- #### Features
3
+ #### Bug fixes
4
4
 
5
- * Added AI Monitoring(AIM) for OpenAI, Amazon Bedrock, and Langchain.
6
- * To enable set `config.ai_monitoring.enabled` or `NEW_RELIC_AI_MONITORING_ENABLED` to `true`.
7
- * It is recommended for a full experience to set `config.span_events.max_samples_stored` to `10000`, `config.custom_insights_events.max_samples_stored` to `100000`, and `config.distributed_tracing.enabled` should not be set to false.
8
- * **Note**: Enabling [high-security mode](https://docs.newrelic.com/docs/apm/agents/manage-apm-agents/configuration/high-security-mode/) will disable the AIM instrumentation and events.
9
- * Added instrumentation for VectorStore.similaritySearch for langchain.js ([#2049](https://github.com/newrelic/node-newrelic/pull/2049)) ([3c50606](https://github.com/newrelic/node-newrelic/commit/3c50606a57a8dc18c91fe36e3b180bafd15a4cbc))
10
- * Added setLlmTokenCountCallback API endpoint to register a callback for calculating token count when none is provided ([#2065](https://github.com/newrelic/node-newrelic/pull/2065)) ([d2faf1a](https://github.com/newrelic/node-newrelic/commit/d2faf1a4942aacefd8b92e0bc2dc11bd8b687328))
11
- * Added token_count to LlmEmbedding and LlmChatCompletionMessage for openai ([#2061](https://github.com/newrelic/node-newrelic/pull/2061)) ([47a925e](https://github.com/newrelic/node-newrelic/commit/47a925eccce8e5b5d682b46277bbef5191f8b553))
12
- * Added tool_id to langchain error event ([#2064](https://github.com/newrelic/node-newrelic/pull/2064)) ([793abe8](https://github.com/newrelic/node-newrelic/commit/793abe8c9854b80fb1cf42f839a7db6a646cdc0b))
5
+ * Fixed instrumenting the same module installed in different locations ([#2104](https://github.com/newrelic/node-newrelic/pull/2104)) ([88bdace](https://github.com/newrelic/node-newrelic/commit/88bdace6489c7d258ed3200f1550367f35824bc1))
13
6
 
14
- #### Miscellaneous chores
15
-
16
- * Added flag for verbosity during docs publishing ([#2060](https://github.com/newrelic/node-newrelic/pull/2060)) ([fe0d41a](https://github.com/newrelic/node-newrelic/commit/fe0d41a86cba8da6173f5935e61c62b7dca75344))
17
- * Added some delays to docs publishing ([#2062](https://github.com/newrelic/node-newrelic/pull/2062)) ([a602fd4](https://github.com/newrelic/node-newrelic/commit/a602fd48e929437e4bc933c4ce276989013c53f1))
18
- * Changed casing of OpenAI in vendor property ([#2068](https://github.com/newrelic/node-newrelic/pull/2068)) ([64b4ca2](https://github.com/newrelic/node-newrelic/commit/64b4ca2750c9de8d9028fef515c15019e358a5d9))
19
- * Changed token_count to only use tokenCountCallback ([#2070](https://github.com/newrelic/node-newrelic/pull/2070)) ([66f94b0](https://github.com/newrelic/node-newrelic/commit/66f94b05aa7018af6fa1db1d2d87de9013f23a5b))
20
- * Removed langchain_instrumentation feature flag as the instrumentation is feature complete ([#2073](https://github.com/newrelic/node-newrelic/pull/2073)) ([925a463](https://github.com/newrelic/node-newrelic/commit/925a463c708b29c78567aecf78ac89ac226b7995))
21
- * updated @newrelic/aws-sdk and @newrelic/koa to latest ([#2074](https://github.com/newrelic/node-newrelic/pull/2074)) ([0747ca4](https://github.com/newrelic/node-newrelic/commit/0747ca4f0f6615e1fbfcc734a36059960facf23e))
22
-
23
- ### v11.12.0 (2024-03-04)
7
+ #### Code refactoring
24
8
 
25
- #### Features
26
-
27
- * Added instrumentation for `chain.stream` for langchain js. ([#2052](https://github.com/newrelic/node-newrelic/pull/2052)) ([03abfce](https://github.com/newrelic/node-newrelic/commit/03abfce666d3c48abd0994c44817bb5cbe8655a9))
9
+ * **mongodb:** Removed instrumentation that handles connecting via unix domain socket. ([#2129](https://github.com/newrelic/node-newrelic/pull/2129)) ([808323f](https://github.com/newrelic/node-newrelic/commit/808323f0832952870fd1e94474b3fd3e0ab1b8c4))
10
+ * Updated shim classes to no longer construct specs. ([#2096](https://github.com/newrelic/node-newrelic/pull/2096)) ([158c295](https://github.com/newrelic/node-newrelic/commit/158c29566f6a5993ec77f84aeaa266ceab0bf4f0))
28
11
 
29
12
  #### Miscellaneous chores
30
13
 
31
- * Added @azure/openai and @langchain/community/llms/bedrock as tracking packages so we can measure usage with angler ([#2053](https://github.com/newrelic/node-newrelic/pull/2053)) ([4830ea3](https://github.com/newrelic/node-newrelic/commit/4830ea3285726f8cc8fb60820c4cf2d3790e5250))
14
+ * **deps-dev:** Bumped express from 4.18.2 to 4.19.2 ([#2101](https://github.com/newrelic/node-newrelic/pull/2101)) ([639cb78](https://github.com/newrelic/node-newrelic/commit/639cb785dff7568ad227091512013c2dfb81e5f9))
15
+ * **deps:** Updated @newrelic/security-agent to v1.1.1 ([#2092](https://github.com/newrelic/node-newrelic/pull/2092)) ([3272aa3](https://github.com/newrelic/node-newrelic/commit/3272aa3da2260ce18c71c24608ffdda512ca6817))
16
+ * Fixed incorrect pinning of @elastic/transport ([#2120](https://github.com/newrelic/node-newrelic/pull/2120)) ([7b5bdaa](https://github.com/newrelic/node-newrelic/commit/7b5bdaac1b1081636636cd7ca7c6b484f5251f76))
17
+ * Removed scrollbar styling in generated API docs ([#2091](https://github.com/newrelic/node-newrelic/pull/2091)) ([cb0fa11](https://github.com/newrelic/node-newrelic/commit/cb0fa11c81290bb93cb30e974fdb1ece82a1e80e))
18
+ * Removed transaction_id and legacy token count attributes from llm events for openai and langchain ([#2093](https://github.com/newrelic/node-newrelic/pull/2093)) ([df2a0fd](https://github.com/newrelic/node-newrelic/commit/df2a0fd7c99a7bbf024c1e33c7fdff512b45c970))
32
19
 
33
20
  #### Tests
34
21
 
35
- * Updated aws-sdk branch to main as the necessary code was merged. ([#2051](https://github.com/newrelic/node-newrelic/pull/2051)) ([1e52a5c](https://github.com/newrelic/node-newrelic/commit/1e52a5cd7a8acc8970dbdc6b1bf774c06aa6f5fb))
22
+ * Updated test/integration/core/dns reverse test to remove flakiness ([#2121](https://github.com/newrelic/node-newrelic/pull/2121)) ([c32cb27](https://github.com/newrelic/node-newrelic/commit/c32cb2739ece3adcf5bd42e646071b3f59e691ba))
23
+ * Updated elastic tests to skip broken version ([#2119](https://github.com/newrelic/node-newrelic/pull/2119)) ([5d0d1bb](https://github.com/newrelic/node-newrelic/commit/5d0d1bb4994b41d43ab9b4eb110fea036ac307bc))
24
+
25
+ #### Continuous integration
36
26
 
27
+ * Removed usage of `use_new_release` from prepare release workflow ([#2124](https://github.com/newrelic/node-newrelic/pull/2124)) ([007ddb4](https://github.com/newrelic/node-newrelic/commit/007ddb4dce6cf5ab463a1868fe4cfa203d3e9ff2))
28
+ * Updated `prepare-release.js` to not require changelog.json ([#2106](https://github.com/newrelic/node-newrelic/pull/2106)) ([328a570](https://github.com/newrelic/node-newrelic/commit/328a570bbe9f359d23a21317ccd8a8bc52b473b4))
29
+ * Updated prepare release to provide a drop down for release type ([#2133](https://github.com/newrelic/node-newrelic/pull/2133)) ([846269b](https://github.com/newrelic/node-newrelic/commit/846269bb256f287c5fb9be32bdb62e9786e3cfe4))
30
+ * Updated versioned security agent workflow ([#2100](https://github.com/newrelic/node-newrelic/pull/2100)) ([f787b15](https://github.com/newrelic/node-newrelic/commit/f787b15f94c416d547af1ab4b2d7c31665b417b7))
31
+ * Fixed typo in constant name for prepare release script ([#2094](https://github.com/newrelic/node-newrelic/pull/2094)) ([3b887d9](https://github.com/newrelic/node-newrelic/commit/3b887d96c70a2cc5e3833cdc8b65de99b643f7a1))
32
+
33
+ ### v11.14.0 (2024-03-20)
34
+
35
+ #### Features
36
+
37
+ * Added `guid` attribute to `TransactionError` events ([#2079](https://github.com/newrelic/node-newrelic/pull/2079)) ([3468fb1](https://github.com/newrelic/node-newrelic/commit/3468fb14635b10c30a9a814dc0d084aeacfd9e10))
38
+ * Added instrumentation for `initializeUnorderedBulkOp`, and `initializeOrderedBulkOp` in mongodb 4+ ([#2086](https://github.com/newrelic/node-newrelic/pull/2086)) ([666ae6e](https://github.com/newrelic/node-newrelic/commit/666ae6ea4be8167748e31fe9b1d086aee5d0135d))
39
+ * Added support for Mongo v5+ ([#2085](https://github.com/newrelic/node-newrelic/pull/2085)) ([00f6feb](https://github.com/newrelic/node-newrelic/commit/00f6febb4893ed2abe902644514af3ab629cdbc1))
40
+
41
+ #### Security improvements
42
+
43
+ * **deps:** bump follow-redirects from 1.15.5 to 1.15.6 ([#2078](https://github.com/newrelic/node-newrelic/pull/2078)) ([aa86482](https://github.com/newrelic/node-newrelic/commit/aa86482738ba6b17bf6c2c7362931a3ad57736dd))
44
+
45
+ #### Documentation
46
+
47
+ * Changed bug bounty URL ([#2081](https://github.com/newrelic/node-newrelic/pull/2081)) ([f4586d7](https://github.com/newrelic/node-newrelic/commit/f4586d71cbe9c886181fbfe4b414cf0f9d630873))
48
+
49
+ #### Miscellaneous chores
50
+
51
+ * Added instrumentation tracking class ([#2084](https://github.com/newrelic/node-newrelic/pull/2084)) ([07d7e7d](https://github.com/newrelic/node-newrelic/commit/07d7e7d50edf9cd8a1cd1b465b24bc589409c5dc))
52
+ * **deps:** pin @newrelic/security-agent to 1.0.1 ([#2089](https://github.com/newrelic/node-newrelic/pull/2089)) ([e133c76](https://github.com/newrelic/node-newrelic/commit/e133c76a34f7d2af16610f00958651a6cff8824d))
53
+
54
+ ### v11.13.0 (2024-03-13)
55
+
56
+ #### Features
57
+
58
+ * Added AI Monitoring(AIM) for OpenAI, Amazon Bedrock, and Langchain.
59
+ * To enable set `config.ai_monitoring.enabled` or `NEW_RELIC_AI_MONITORING_ENABLED` to `true`.
60
+ * It is recommended for a full experience to set `config.span_events.max_samples_stored` to `10000`, `config.custom_insights_events.max_samples_stored` to `100000`, and `config.distributed_tracing.enabled` should not be set to false.
61
+ * **Note**: Enabling [high-security mode](https://docs.newrelic.com/docs/apm/agents/manage-apm-agents/configuration/high-security-mode/) will disable the AIM instrumentation and events.
62
+ * Added instrumentation for VectorStore.similaritySearch for langchain.js ([#2049](https://github.com/newrelic/node-newrelic/pull/2049)) ([3c50606](https://github.com/newrelic/node-newrelic/commit/3c50606a57a8dc18c91fe36e3b180bafd15a4cbc))
63
+ * Added setLlmTokenCountCallback API endpoint to register a callback for calculating token count when none is provided ([#2065](https://github.com/newrelic/node-newrelic/pull/2065)) ([d2faf1a](https://github.com/newrelic/node-newrelic/commit/d2faf1a4942aacefd8b92e0bc2dc11bd8b687328))
64
+ * Added token_count to LlmEmbedding and LlmChatCompletionMessage for openai ([#2061](https://github.com/newrelic/node-newrelic/pull/2061)) ([47a925e](https://github.com/newrelic/node-newrelic/commit/47a925eccce8e5b5d682b46277bbef5191f8b553))
65
+ * Added tool_id to langchain error event ([#2064](https://github.com/newrelic/node-newrelic/pull/2064)) ([793abe8](https://github.com/newrelic/node-newrelic/commit/793abe8c9854b80fb1cf42f839a7db6a646cdc0b))
66
+
67
+ #### Miscellaneous chores
68
+
69
+ * Added flag for verbosity during docs publishing ([#2060](https://github.com/newrelic/node-newrelic/pull/2060)) ([fe0d41a](https://github.com/newrelic/node-newrelic/commit/fe0d41a86cba8da6173f5935e61c62b7dca75344))
70
+ * Added some delays to docs publishing ([#2062](https://github.com/newrelic/node-newrelic/pull/2062)) ([a602fd4](https://github.com/newrelic/node-newrelic/commit/a602fd48e929437e4bc933c4ce276989013c53f1))
71
+ * Changed casing of OpenAI in vendor property ([#2068](https://github.com/newrelic/node-newrelic/pull/2068)) ([64b4ca2](https://github.com/newrelic/node-newrelic/commit/64b4ca2750c9de8d9028fef515c15019e358a5d9))
72
+ * Changed token_count to only use tokenCountCallback ([#2070](https://github.com/newrelic/node-newrelic/pull/2070)) ([66f94b0](https://github.com/newrelic/node-newrelic/commit/66f94b05aa7018af6fa1db1d2d87de9013f23a5b))
73
+ * Removed langchain_instrumentation feature flag as the instrumentation is feature complete ([#2073](https://github.com/newrelic/node-newrelic/pull/2073)) ([925a463](https://github.com/newrelic/node-newrelic/commit/925a463c708b29c78567aecf78ac89ac226b7995))
74
+ * updated @newrelic/aws-sdk and @newrelic/koa to latest ([#2074](https://github.com/newrelic/node-newrelic/pull/2074)) ([0747ca4](https://github.com/newrelic/node-newrelic/commit/0747ca4f0f6615e1fbfcc734a36059960facf23e))
75
+
76
+ ### v11.12.0 (2024-03-04)
77
+
78
+ #### Features
79
+
80
+ * Added instrumentation for `chain.stream` for langchain js. ([#2052](https://github.com/newrelic/node-newrelic/pull/2052)) ([03abfce](https://github.com/newrelic/node-newrelic/commit/03abfce666d3c48abd0994c44817bb5cbe8655a9))
81
+
82
+ #### Miscellaneous chores
83
+
84
+ * Added @azure/openai and @langchain/community/llms/bedrock as tracking packages so we can measure usage with angler ([#2053](https://github.com/newrelic/node-newrelic/pull/2053)) ([4830ea3](https://github.com/newrelic/node-newrelic/commit/4830ea3285726f8cc8fb60820c4cf2d3790e5250))
85
+
86
+ #### Tests
87
+
88
+ * Updated aws-sdk branch to main as the necessary code was merged. ([#2051](https://github.com/newrelic/node-newrelic/pull/2051)) ([1e52a5c](https://github.com/newrelic/node-newrelic/commit/1e52a5cd7a8acc8970dbdc6b1bf774c06aa6f5fb))
89
+
37
90
  ### v11.11.0 (2024-02-27)
38
91
 
39
92
  #### Features
package/README.md CHANGED
@@ -234,7 +234,7 @@ If you have any questions, or to execute our corporate CLA, required if your con
234
234
 
235
235
  As noted in our [security policy](../../security/policy), New Relic is committed to the privacy and security of our customers and their data. We believe that providing coordinated disclosure by security researchers and engaging with the security community are important means to achieve our security goals.
236
236
 
237
- If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through [HackerOne](https://hackerone.com/newrelic).
237
+ If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through [our bug bounty program](https://docs.newrelic.com/docs/security/security-privacy/information-security/report-security-vulnerabilities/).
238
238
 
239
239
  If you would like to contribute to this project, review [these guidelines](./CONTRIBUTING.md).
240
240
 
@@ -712,7 +712,7 @@ This product includes source derived from [@newrelic/aws-sdk](https://github.com
712
712
 
713
713
  ### @newrelic/koa
714
714
 
715
- This product includes source derived from [@newrelic/koa](https://github.com/newrelic/node-newrelic-koa) ([v9.0.0](https://github.com/newrelic/node-newrelic-koa/tree/v9.0.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-koa/blob/v9.0.0/LICENSE):
715
+ This product includes source derived from [@newrelic/koa](https://github.com/newrelic/node-newrelic-koa) ([v9.1.0](https://github.com/newrelic/node-newrelic-koa/tree/v9.1.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-koa/blob/v9.1.0/LICENSE):
716
716
 
717
717
  ```
718
718
  Apache License
@@ -951,7 +951,7 @@ SOFTWARE.
951
951
 
952
952
  ### @newrelic/security-agent
953
953
 
954
- This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v1.0.1](https://github.com/newrelic/csec-node-agent/tree/v1.0.1)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v1.0.1/LICENSE):
954
+ This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v1.1.1](https://github.com/newrelic/csec-node-agent/tree/v1.1.1)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v1.1.1/LICENSE):
955
955
 
956
956
  ```
957
957
  ## New Relic Software License v1.0
package/api.js CHANGED
@@ -26,7 +26,7 @@ const {
26
26
  const LlmFeedbackMessage = require('./lib/llm-events/feedback-message')
27
27
 
28
28
  const ATTR_DEST = require('./lib/config/attribute-filter').DESTINATIONS
29
- const MODULE_TYPE = require('./lib/shim/constants').MODULE_TYPE
29
+ const MODULE_TYPE = require('./lib/instrumentation-descriptor').TYPES
30
30
  const NAMES = require('./lib/metrics/names')
31
31
  const obfuscate = require('./lib/util/sql/obfuscate')
32
32
  const { DESTINATIONS } = require('./lib/config/attribute-filter')
@@ -240,6 +240,7 @@ function _getErrorEventIntrinsicAttrs(transaction, errorClass, message, expected
240
240
  }
241
241
 
242
242
  attributes['nr.transactionGuid'] = transaction.id
243
+ attributes.guid = transaction.id
243
244
 
244
245
  if (transaction.port) {
245
246
  attributes.port = transaction.port
@@ -28,7 +28,9 @@ module.exports = function initialize(_agent, cassandra, _moduleName, shim) {
28
28
  shim.recordOperation(
29
29
  ClientProto,
30
30
  ['connect', 'shutdown'],
31
- new OperationSpec({ callback: shim.LAST })
31
+ function operationSpec(shim, _fn, name) {
32
+ return new OperationSpec({ callback: shim.LAST, name })
33
+ }
32
34
  )
33
35
 
34
36
  if (semver.satisfies(cassandraVersion, '>=4.4.0')) {
@@ -11,7 +11,6 @@ const {
11
11
  } = require('../../shim/specs')
12
12
  const { CURSOR_OPS, COLLECTION_OPS, DB_OPS } = require('./constants')
13
13
  const common = module.exports
14
- common.NR_ATTRS = Symbol('NR_ATTRS')
15
14
 
16
15
  /**
17
16
  * Instruments all methods from constants.CURSOR_OPS on a given
@@ -23,12 +22,9 @@ common.NR_ATTRS = Symbol('NR_ATTRS')
23
22
  common.instrumentCursor = function instrumentCursor(shim, Cursor) {
24
23
  if (Cursor && Cursor.prototype) {
25
24
  const proto = Cursor.prototype
26
- for (let i = 0; i < CURSOR_OPS.length; i++) {
27
- shim.recordQuery(proto, CURSOR_OPS[i], common.makeQueryDescFunc(shim, CURSOR_OPS[i]))
28
- }
29
-
30
- shim.recordQuery(proto, 'each', common.makeQueryDescFunc(shim, 'each'))
31
- shim.recordOperation(proto, 'pipe', new OperationSpec({ opaque: true }))
25
+ shim.recordQuery(proto, CURSOR_OPS, common.makeQueryDescFunc)
26
+ shim.recordQuery(proto, 'each', common.makeQueryDescFunc)
27
+ shim.recordOperation(proto, 'pipe', new OperationSpec({ opaque: true, name: 'pipe' }))
32
28
  }
33
29
  }
34
30
 
@@ -42,9 +38,7 @@ common.instrumentCursor = function instrumentCursor(shim, Cursor) {
42
38
  common.instrumentCollection = function instrumentCollection(shim, Collection) {
43
39
  if (Collection && Collection.prototype) {
44
40
  const proto = Collection.prototype
45
- for (let i = 0; i < COLLECTION_OPS.length; i++) {
46
- shim.recordQuery(proto, COLLECTION_OPS[i], common.makeQueryDescFunc(shim, COLLECTION_OPS[i]))
47
- }
41
+ shim.recordQuery(proto, COLLECTION_OPS, common.makeQueryDescFunc)
48
42
  }
49
43
  }
50
44
 
@@ -72,9 +66,20 @@ common.instrumentBulkOperation = function instrumentBulkOperation(shim, BulkOper
72
66
  common.instrumentDb = function instrumentDb(shim, Db) {
73
67
  if (Db && Db.prototype) {
74
68
  const proto = Db.prototype
75
- shim.recordOperation(proto, DB_OPS, new OperationSpec({ callback: shim.LAST, opaque: true }))
69
+ shim.recordOperation(proto, DB_OPS, function makeOperationDescFunc(shim, _fn, methodName) {
70
+ return new OperationSpec({
71
+ callback: shim.LAST,
72
+ opaque: true,
73
+ promise: true,
74
+ name: methodName
75
+ })
76
+ })
76
77
  // link to client.connect(removed in v4.0)
77
- shim.recordOperation(Db, 'connect', new OperationSpec({ callback: shim.LAST }))
78
+ shim.recordOperation(
79
+ Db,
80
+ 'connect',
81
+ new OperationSpec({ callback: shim.LAST, promise: true, name: 'connect' })
82
+ )
78
83
  }
79
84
  }
80
85
 
@@ -82,29 +87,26 @@ common.instrumentDb = function instrumentDb(shim, Db) {
82
87
  * Sets up the desc for all instrumented query methods
83
88
  *
84
89
  * @param {Shim} shim instance of shim
85
- * @param {string} methodName name of method getting executed
86
- * @returns {object} query spec
90
+ * @param {Function} _fn function getting instrumented
91
+ * @param {string} methodName name of function
92
+ * @returns {QuerySpec} query spec
87
93
  */
88
- common.makeQueryDescFunc = function makeQueryDescFunc(shim, methodName) {
94
+ common.makeQueryDescFunc = function makeQueryDescFunc(shim, _fn, methodName) {
89
95
  if (methodName === 'each') {
90
- return function eachDescFunc() {
91
- const parameters = getInstanceAttributeParameters(shim, this)
92
- return new QuerySpec({ query: methodName, parameters, rowCallback: shim.LAST, opaque: true })
93
- }
94
- }
95
-
96
- return function queryDescFunc() {
97
- // segment name does not actually use query string
98
- // method name is set as query so the query parser has access to the op name
99
96
  const parameters = getInstanceAttributeParameters(shim, this)
100
- return new QuerySpec({
101
- query: methodName,
102
- parameters,
103
- promise: true,
104
- callback: shim.LAST,
105
- opaque: true
106
- })
97
+ return new QuerySpec({ query: methodName, parameters, rowCallback: shim.LAST, opaque: true })
107
98
  }
99
+
100
+ // segment name does not actually use query string
101
+ // method name is set as query so the query parser has access to the op name
102
+ const parameters = getInstanceAttributeParameters(shim, this)
103
+ return new QuerySpec({
104
+ query: methodName,
105
+ parameters,
106
+ promise: true,
107
+ callback: shim.LAST,
108
+ opaque: true
109
+ })
108
110
  }
109
111
 
110
112
  /**
@@ -133,7 +135,7 @@ common.makeBulkDescFunc = function makeBulkDescFunc(shim) {
133
135
  *
134
136
  * @param {Shim} shim instance of shim
135
137
  * @param {object} instrumenter instance of mongo APM class
136
- * @param {object} [options={}] provide command names to skip updating host/port as they are unrelated to the active query. This is only in v3 because after every command is runs `endSessions` which runs on the admin database
138
+ * @param {object} [options] provide command names to skip updating host/port as they are unrelated to the active query. This is only in v3 because after every command is runs `endSessions` which runs on the admin database
137
139
  */
138
140
  common.captureAttributesOnStarted = function captureAttributesOnStarted(
139
141
  shim,
@@ -152,13 +154,10 @@ common.captureAttributesOnStarted = function captureAttributesOnStarted(
152
154
  if (connId) {
153
155
  // used in v3 when connection is a cluster pool
154
156
  if (typeof connId === 'number') {
155
- setHostPort(shim, evnt.address, evnt.databaseName, this.$MongoClient)
157
+ setHostPort(shim, evnt.address, evnt.databaseName)
156
158
  // used in v3 when connection is to 1 host
157
159
  } else if (typeof connId === 'string') {
158
160
  setHostPort(shim, connId, evnt.databaseName)
159
- // v2 contains `domainSocket`, get socket connection from `host`
160
- } else if (connId.domainSocket) {
161
- shim.captureInstanceAttributes('localhost', connId.host, evnt.databaseName)
162
161
  // v2 remote connection get `host` `port` from respective properties
163
162
  } else {
164
163
  shim.captureInstanceAttributes(connId.host, connId.port, evnt.databaseName)
@@ -169,37 +168,14 @@ common.captureAttributesOnStarted = function captureAttributesOnStarted(
169
168
 
170
169
  /**
171
170
  * Extracts the host and port from a connection string
172
- * This also handles if connection string is a domain socket
173
- * Mongo sticks the path to the domain socket in the "host" slot, but we
174
- * want it in the "port", so if we have a domain socket we need to change
175
- * the order of our parameters.
176
171
  *
177
172
  * @param {Shim} shim instance of shim
178
173
  * @param {string} connStr mongo connection string
179
174
  * @param {string} db database name
180
- * @param {object} client mongo client instance
181
175
  */
182
- function setHostPort(shim, connStr, db, client) {
176
+ function setHostPort(shim, connStr, db) {
183
177
  const parts = common.parseAddress(connStr)
184
- // in v3 when running with a cluster of socket connections
185
- // the address is `undefined:undefined`. we will instead attempt
186
- // to get connection details from the client symbol NR_ATTRS
187
- // added in `lib/instrumentation/mongodb/v3-mongo` when a client connects
188
- // with a URL string
189
- if (parts.includes('undefined')) {
190
- try {
191
- const attrs = client[common.NR_ATTRS]
192
- const socket = decodeURIComponent(attrs.split(',')[0].split('mongodb://')[1])
193
- shim.captureInstanceAttributes('localhost', socket, db)
194
- } catch (err) {
195
- shim.logger.debug(err, 'Could not extract host/port from mongo command')
196
- }
197
- // connected using domain socket but the "host"(e.g: /path/to/mongo-socket-port.sock)
198
- } else if (parts.length && parts[0][0] === '/') {
199
- shim.captureInstanceAttributes('localhost', parts[0], db)
200
- } else {
201
- shim.captureInstanceAttributes(parts[0], parts[1], db)
202
- }
178
+ shim.captureInstanceAttributes(parts[0], parts[1], db)
203
179
  }
204
180
 
205
181
  /**
@@ -214,7 +190,6 @@ function setHostPort(shim, connStr, db, client) {
214
190
  */
215
191
  function getInstanceAttributeParameters(shim, mongo) {
216
192
  let params
217
-
218
193
  if (mongo?.s?.topology) {
219
194
  shim.logger.trace('Adding datastore instance attributes from mongo.s.db + mongo.s.topology')
220
195
  const databaseName = mongo?.s?.db?.databaseName || mongo?.s?.namespace?.db || null
@@ -224,6 +199,10 @@ function getInstanceAttributeParameters(shim, mongo) {
224
199
  const databaseName = mongo?.s?.db?.databaseName || null
225
200
  const hosts = mongo.s.db.s.client.s.options.hosts
226
201
  params = getParametersFromHosts(hosts, databaseName)
202
+ } else if (mongo?.s?.db?.client?.topology) {
203
+ const databaseName = mongo?.s?.namespace?.db
204
+ const topology = mongo.s.db.client.topology
205
+ params = getParametersFromTopology(topology, databaseName)
227
206
  } else {
228
207
  shim.logger.trace('Could not find datastore instance attributes.')
229
208
  params = new DatastoreParameters()
@@ -240,13 +219,8 @@ function getInstanceAttributeParameters(shim, mongo) {
240
219
  * @returns {object} db params
241
220
  */
242
221
  function getParametersFromHosts(hosts, database) {
243
- let [{ host, port }] = hosts
244
- const [{ socketPath }] = hosts
222
+ const [{ host, port }] = hosts
245
223
 
246
- if (socketPath) {
247
- port = socketPath
248
- host = 'localhost'
249
- }
250
224
  return new DatastoreParameters({
251
225
  host,
252
226
  port_path_or_id: port,
@@ -272,15 +246,13 @@ function getParametersFromTopology(conf, database) {
272
246
  ;[{ host, port }] = conf.s.options.servers
273
247
  }
274
248
 
275
- // host is a domain socket. set host as localhost and use the domain
276
- // socket host as the port
277
- if (host && host.endsWith('.sock')) {
278
- port = host
279
- host = 'localhost'
249
+ // hosts is an array but we will always pull the first for consistency
250
+ if (conf?.s?.options?.hosts?.length) {
251
+ ;[{ host, port }] = conf.s.options.hosts
280
252
  }
281
253
 
282
254
  return new DatastoreParameters({
283
- host: host,
255
+ host,
284
256
  port_path_or_id: port,
285
257
  database_name: database
286
258
  })
@@ -38,7 +38,7 @@ module.exports = function instrument(shim, mongodb) {
38
38
  const recordDesc = {
39
39
  Gridstore: {
40
40
  isQuery: false,
41
- makeDescFunc: function makeGridDesc(opName) {
41
+ makeDescFunc: function makeGridDesc(shim, fn, opName) {
42
42
  return new OperationSpec({ name: 'GridFS-' + opName, callback: shim.LAST })
43
43
  }
44
44
  },
@@ -50,8 +50,8 @@ module.exports = function instrument(shim, mongodb) {
50
50
  Collection: { isQuery: true, makeDescFunc: makeQueryDescFunc },
51
51
  Db: {
52
52
  isQuery: false,
53
- makeDescFunc: function makeDbDesc() {
54
- return new OperationSpec({ callback: shim.LAST })
53
+ makeDescFunc: function makeDbDesc(shim, fn, method) {
54
+ return new OperationSpec({ callback: shim.LAST, name: method })
55
55
  }
56
56
  }
57
57
  }
@@ -95,10 +95,10 @@ module.exports = function instrument(shim, mongodb) {
95
95
  const { isQuery, makeDescFunc } = recordDesc[objectName]
96
96
  const proto = object.prototype
97
97
  if (isQuery) {
98
- shim.recordQuery(proto, method, makeDescFunc(shim, method))
98
+ shim.recordQuery(proto, method, makeDescFunc)
99
99
  } else if (isQuery === false) {
100
100
  // could be unset
101
- shim.recordOperation(proto, method, makeDescFunc(shim, method))
101
+ shim.recordOperation(proto, method, makeDescFunc)
102
102
  } else {
103
103
  shim.logger.trace('No wrapping method found for %s', objectName)
104
104
  }
@@ -108,7 +108,11 @@ module.exports = function instrument(shim, mongodb) {
108
108
  // the cursor object implements Readable stream and internally calls nextObject on
109
109
  // each read, in which case we do not want to record each nextObject() call
110
110
  if (/Cursor$/.test(objectName)) {
111
- shim.recordOperation(object.prototype, 'pipe', new OperationSpec({ opaque: true }))
111
+ shim.recordOperation(
112
+ object.prototype,
113
+ 'pipe',
114
+ new OperationSpec({ opaque: true, name: 'pipe' })
115
+ )
112
116
  }
113
117
  }
114
118
  }
@@ -11,15 +11,15 @@ const {
11
11
  instrumentBulkOperation,
12
12
  instrumentCollection,
13
13
  instrumentCursor,
14
- instrumentDb,
15
- NR_ATTRS
14
+ instrumentDb
16
15
  } = require('./common')
17
16
 
18
17
  /**
19
18
  * parser used to grab the collection and operation
20
19
  * on every mongo operation
21
20
  *
22
- * @param {object} operation
21
+ * @param {object} operation mongodb operation
22
+ * @returns {object} { operation, collection } parsed operation and collection
23
23
  */
24
24
  function queryParser(operation) {
25
25
  let collection = this.collectionName || 'unknown'
@@ -40,15 +40,12 @@ function queryParser(operation) {
40
40
  * to a Symbol on the MongoClient to be used later to extract the host/port in cases where the topology
41
41
  * is a cluster of domain sockets
42
42
  *
43
- * @param {Shim} shim
43
+ * @param {Shim} shim instance of shim
44
44
  * @param {object} mongodb resolved package
45
45
  */
46
46
  function instrumentClient(shim, mongodb) {
47
- shim.recordOperation(mongodb.MongoClient, 'connect', function wrappedConnect(shim, _, __, args) {
48
- // Add the connection url to the MongoClient to retrieve later in the `lib/instrumentation/mongo/common`
49
- // captureAttributesOnStarted listener
50
- this[NR_ATTRS] = args[0]
51
- return new RecorderSpec({ callback: shim.LAST })
47
+ shim.recordOperation(mongodb.MongoClient, 'connect', function wrappedConnect(shim) {
48
+ return new RecorderSpec({ callback: shim.LAST, name: 'connect' })
52
49
  })
53
50
  }
54
51
 
@@ -61,7 +58,7 @@ function instrumentClient(shim, mongodb) {
61
58
  * as well as sets up a listener for when commands start to properly
62
59
  * add necessary attributes to segments
63
60
  *
64
- * @param {Shim} shim
61
+ * @param {Shim} shim instance of shim
65
62
  * @param {object} mongodb resolved package
66
63
  */
67
64
  module.exports = function instrument(shim, mongodb) {
@@ -6,20 +6,30 @@
6
6
  'use strict'
7
7
 
8
8
  const { OperationSpec } = require('../../shim/specs')
9
- const { instrumentCollection, instrumentCursor, instrumentDb, parseAddress } = require('./common')
9
+ const {
10
+ instrumentBulkOperation,
11
+ instrumentCollection,
12
+ instrumentCursor,
13
+ instrumentDb,
14
+ parseAddress
15
+ } = require('./common')
10
16
 
11
17
  /**
12
18
  * parser used to grab the collection and operation
13
19
  * from a running query
14
20
  *
15
- * @param {object} operation
21
+ * @param {object} operation mongodb operation
22
+ * @returns {object} { operation, collection } parsed operation and collection
16
23
  */
17
24
  function queryParser(operation) {
18
25
  let collection = this.collectionName || 'unknown'
19
26
 
20
27
  // cursor methods have collection on namespace.collection
21
- if (this.namespace && this.namespace.collection) {
28
+ if (this?.namespace?.collection) {
22
29
  collection = this.namespace.collection
30
+ // (un)ordered bulk operations have collection on different key
31
+ } else if (this?.s?.collection?.collectionName) {
32
+ collection = this.s.collection.collectionName
23
33
  }
24
34
 
25
35
  return { operation, collection }
@@ -30,23 +40,15 @@ function queryParser(operation) {
30
40
  * update host, port and database_name
31
41
  * on segment attributes
32
42
  *
33
- * @param {Shim} shim
34
- * @param {CommandStartedEvent} evnt
43
+ * @param {Shim} shim instance of shim
44
+ * @param {CommandStartedEvent} evnt mongodb event
35
45
  */
36
46
  function cmdStartedHandler(shim, evnt) {
37
47
  if (evnt.connectionId) {
38
- let [host, port] = parseAddress(evnt.address)
39
-
40
- // connection via socket get port from 1st host
41
- // socketPath property
42
- // which looks like mongodb:///tmp/mongodb-27017.sock"
43
- if (['undefined'].includes(host, port)) {
44
- host = 'localhost'
45
- const hosts = this.s.options.hosts
46
- if (hosts && hosts.length && hosts[0].socketPath) {
47
- port = hosts[0].socketPath
48
- }
49
- } else if (['127.0.0.1', '::1', '[::1]'].includes(host)) {
48
+ const address = parseAddress(evnt.address)
49
+ let [host] = address
50
+ const [, port] = address
51
+ if (['127.0.0.1', '::1', '[::1]'].includes(host)) {
50
52
  host = 'localhost'
51
53
  }
52
54
 
@@ -59,12 +61,13 @@ function cmdStartedHandler(shim, evnt) {
59
61
  * enable APM(monitorCommands) and add the
60
62
  * `commandStarted` listener
61
63
  *
62
- * @param {Shim} shim
64
+ * @param {Shim} shim instance of shim
65
+ * @returns {OperationSpec} spec to capture connect method
63
66
  */
64
67
  function wrapConnect(shim) {
65
68
  this.monitorCommands = true
66
69
  this.on('commandStarted', cmdStartedHandler.bind(this, shim))
67
- return new OperationSpec({ callback: shim.LAST })
70
+ return new OperationSpec({ callback: shim.LAST, name: 'connect' })
68
71
  }
69
72
 
70
73
  /**
@@ -73,7 +76,7 @@ function wrapConnect(shim) {
73
76
  * so we can properly update the segment attributes with a more accurate
74
77
  * host/port/database name
75
78
  *
76
- * @param {Shim} shim
79
+ * @param {Shim} shim instance of shim
77
80
  * @param {MongoClient} MongoClient reference
78
81
  */
79
82
  function instrumentMongoClient(shim, MongoClient) {
@@ -88,4 +91,5 @@ module.exports = function instrument(shim, mongodb) {
88
91
  instrumentCursor(shim, mongodb.AggregationCursor)
89
92
  instrumentCollection(shim, mongodb.Collection)
90
93
  instrumentDb(shim, mongodb.Db)
94
+ instrumentBulkOperation(shim, shim.require('./lib/bulk/common'))
91
95
  }
@@ -6,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const { nrEsmProxy } = require('../symbols')
9
- const { RecorderSpec, QuerySpec } = require('../shim/specs')
9
+ const { RecorderSpec, QuerySpec, ClassWrapSpec } = require('../shim/specs')
10
10
  const DatastoreParameters = require('../shim/specs/params/datastore')
11
11
 
12
12
  function getQuery(shim, original, name, args) {
@@ -58,12 +58,12 @@ module.exports = function initialize(agent, pgsql, moduleName, shim) {
58
58
  // wrapping for native
59
59
  function instrumentPGNative(pg) {
60
60
  shim.wrapReturn(pg, 'Client', clientFactoryWrapper)
61
- shim.wrapClass(pg, 'Pool', { post: poolPostConstructor, es6: true })
61
+ shim.wrapClass(pg, 'Pool', new ClassWrapSpec({ post: poolPostConstructor, es6: true }))
62
62
  }
63
63
 
64
64
  function poolPostConstructor(shim) {
65
65
  if (!shim.isWrapped(this.Client)) {
66
- shim.wrapClass(this, 'Client', clientPostConstructor)
66
+ shim.wrapClass(this, 'Client', new ClassWrapSpec({ post: clientPostConstructor }))
67
67
  }
68
68
  }
69
69