newrelic 7.3.1 → 7.5.2
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/NEWS.md +64 -0
- package/README.md +17 -2
- package/THIRD_PARTY_NOTICES.md +62 -2
- package/lib/collector/api.js +24 -0
- package/lib/collector/facts.js +2 -0
- package/lib/config/index.js +23 -23
- package/lib/grpc/connection.js +23 -12
- package/lib/instrumentation/core/async_hooks.js +4 -0
- package/lib/instrumentation/core/http-outbound.js +2 -3
- package/lib/instrumentation/core/http.js +1 -2
- package/lib/instrumentation/fastify.js +1 -1
- package/lib/instrumentation/mongodb.js +1 -1
- package/lib/shim/shim.js +0 -19
- package/lib/spans/create-span-event-aggregator.js +14 -38
- package/lib/util/cat.js +3 -4
- package/package.json +8 -6
package/NEWS.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
### v7.5.2 (2021-07-07)
|
|
2
|
+
|
|
3
|
+
* Fixed bug where promise-based cursor methods would not properly measure the duration of execution.
|
|
4
|
+
|
|
5
|
+
### v7.5.1 (2021-06-21)
|
|
6
|
+
|
|
7
|
+
* Fixed loading config from the main module's directory. Thank you @alexpls for the contribution.
|
|
8
|
+
|
|
9
|
+
* Moved all integration tests that required secrets to the smoke folder.
|
|
10
|
+
|
|
11
|
+
* Fixed LASP/CSP tests so they don't skip on runs where secrets are available.
|
|
12
|
+
|
|
13
|
+
* Modified self-signed SSL cert to use 'localhost' instead of 'ssl.lvh.me' for SSL testing.
|
|
14
|
+
|
|
15
|
+
* Removed unnecessary trace observer configuration validation for host and port.
|
|
16
|
+
|
|
17
|
+
### v7.5.0 (2021-06-01)
|
|
18
|
+
|
|
19
|
+
* Added default support for config files with a 'cjs' extension (`newrelic.cjs`) in addition to `newrelic.js`.
|
|
20
|
+
|
|
21
|
+
Thank you to @Maddemacher for the contribution!
|
|
22
|
+
|
|
23
|
+
* Added ability to specify a custom config file name with the `NEW_RELIC_CONFIG_FILENAME` environment variable.
|
|
24
|
+
|
|
25
|
+
Thank you to @Maddemacher for the contribution!
|
|
26
|
+
|
|
27
|
+
* Fixed issue when using the 'new_promise_tracking' feature flag where segment mapping may not get cleaned up for promises which never resolve but have all references removed (and thus get cleaned up by GC).
|
|
28
|
+
|
|
29
|
+
Adds segment cleanup on 'destroy' when using 'new_promise_tracking' feature flag in addition to the existing 'promiseResolve' hook. Unfortunately, preventing leaks for this edge-case does come with additional overhead due to adding another hook. Memory gains from feature flag usage should still be worth the trade-off and reduced garbage collection may offset perf/CPU impacts or event still result in net gain, depending on the application.
|
|
30
|
+
|
|
31
|
+
* Bumped `@newrelic/test-utilities` to ^5.1.0.
|
|
32
|
+
|
|
33
|
+
* Replaced deprecated `util.isArray` with `Array.isArray`.
|
|
34
|
+
|
|
35
|
+
* Removed unused `listenerCount` method on `Shim`.
|
|
36
|
+
|
|
37
|
+
* Properly bootstraped husky as a `prepare` script.
|
|
38
|
+
|
|
39
|
+
* Removed commented-out console log from fastify instrumentation.
|
|
40
|
+
|
|
41
|
+
### v7.4.0 (2021-05-11)
|
|
42
|
+
|
|
43
|
+
* Updated third party notices and manifest for husky and lint-staged.
|
|
44
|
+
|
|
45
|
+
* Updated redis versioned tests to use unique DB indexes per file to avoid collisions and flushing of in-progress tests.
|
|
46
|
+
|
|
47
|
+
* Pinned hapi 17 versioned tests to only minor/patch versions within 17.x.
|
|
48
|
+
|
|
49
|
+
* Bumped timeout for redis versioned tests.
|
|
50
|
+
|
|
51
|
+
* Wired up husky + lint staged to execute linting on all changed files in pre-commit hook.
|
|
52
|
+
|
|
53
|
+
* Handled a proxy misconfiguration of collector and log an actionable warning message.
|
|
54
|
+
|
|
55
|
+
* Added `flaky_code` and `success_delay_ms` handling of flaky grpc connections to infinite tracing.
|
|
56
|
+
|
|
57
|
+
* Added resources to README to highlight external modules that customers should be aware of and possibly use for their applications.
|
|
58
|
+
|
|
59
|
+
* Logged all New Relic metadata env vars at startup.
|
|
60
|
+
|
|
61
|
+
* Fixed images for improved reader experience.
|
|
62
|
+
|
|
63
|
+
Thank you to @henryjw for the contribution.
|
|
64
|
+
|
|
1
65
|
### v7.3.1 (2021-04-14)
|
|
2
66
|
|
|
3
67
|
* Fixed issue with 'new_promise_tracking' feature flag functionality where segments for ended transactions would get propagated in certain cases by promises that had no continuations scheduled (via await or manually).
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ To use New Relic's Node.js agent entails these three steps, which are described
|
|
|
52
52
|
/* ... the rest of your program ... */
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
If you're compiling your JavaScript and can't control the final `require` order, the Node
|
|
55
|
+
If you're compiling your JavaScript and can't control the final `require` order, the Node.js agent will work with node's `-r/--require` flag.
|
|
56
56
|
|
|
57
57
|
$ node -r newrelic your-program.js
|
|
58
58
|
$ node --require newrelic your-program.js
|
|
@@ -61,11 +61,26 @@ If you're compiling your JavaScript and can't control the final `require` order,
|
|
|
61
61
|
|
|
62
62
|
For more information on getting started, [check the Node.js docs](https://docs.newrelic.com/docs/agents/nodejs-agent/getting-started/introduction-new-relic-nodejs).
|
|
63
63
|
|
|
64
|
+
### External Modules
|
|
65
|
+
|
|
66
|
+
There are several modules that can be installed and configured to accompany the Node.js agent:
|
|
67
|
+
|
|
68
|
+
* [@newrelic/apollo-server-plugin](https://github.com/newrelic/newrelic-node-apollo-server-plugin): New Relic's official Apollo Server plugin for use with the Node.js agent.
|
|
69
|
+
* [@newrelic/winston-enricher](https://github.com/newrelic/newrelic-winston-logenricher-node): Provides distributed trace and span information output as JSON-formatted log messages. This is most commonly used with the New Relic Logs product.
|
|
70
|
+
* [@newrelic/mysql](https://github.com/newrelic/node-newrelic-mysql)(**Experimental**): Standalone instrumentation for [mysql2](https://github.com/sidorares/node-mysql2#readme) and [mysql2/promise](https://github.com/sidorares/node-mysql2/blob/master/documentation/Promise-Wrapper.md) as well as the same instrumentation for [mysql](https://github.com/mysqljs/mysql#readme) within the Node.js agent.
|
|
71
|
+
|
|
72
|
+
There are several modules included within the Node.js agent to add more instrumentation for 3rd party modules:
|
|
73
|
+
|
|
74
|
+
* [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk): Provides instrumentation for the [AWS SDK](https://www.npmjs.com/package/aws-sdk) npm package.
|
|
75
|
+
* [@newrelic/koa](https://github.com/newrelic/node-newrelic-koa): Provides instrumentation for [koa](https://koajs.com/), [koa-router](https://github.com/ZijianHe/koa-router), [@koa/router](https://github.com/koajs/router), and [koa-route](https://github.com/koajs/route) npm packages.
|
|
76
|
+
* [@newrelic/superagent](https://github.com/newrelic/node-newrelic-superagent): Provides instrumentation for [superagent](https://github.com/visionmedia/superagent) npm package.
|
|
77
|
+
* [@newrelic/native-metrics](https://github.com/newrelic/node-native-metrics): Provides hooks into the native v8 layer of Node.js to provide metrics to the Node.js agent.
|
|
78
|
+
|
|
64
79
|
## Usage
|
|
65
80
|
|
|
66
81
|
### Using the API
|
|
67
82
|
|
|
68
|
-
The `newrelic` module returns an object with the Node agent's API methods attached.
|
|
83
|
+
The `newrelic` module returns an object with the Node.js agent's API methods attached.
|
|
69
84
|
|
|
70
85
|
```js
|
|
71
86
|
const newrelic = require('newrelic')
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -49,7 +49,9 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
|
|
|
49
49
|
* [glob](#glob)
|
|
50
50
|
* [got](#got)
|
|
51
51
|
* [http-errors](#http-errors)
|
|
52
|
+
* [husky](#husky)
|
|
52
53
|
* [jsdoc](#jsdoc)
|
|
54
|
+
* [lint-staged](#lint-staged)
|
|
53
55
|
* [memcached](#memcached)
|
|
54
56
|
* [minami](#minami)
|
|
55
57
|
* [mongodb](#mongodb)
|
|
@@ -1927,7 +1929,7 @@ SOFTWARE.
|
|
|
1927
1929
|
|
|
1928
1930
|
### commander
|
|
1929
1931
|
|
|
1930
|
-
This product includes source derived from [commander](https://github.com/tj/commander.js) ([v7.
|
|
1932
|
+
This product includes source derived from [commander](https://github.com/tj/commander.js) ([v7.2.0](https://github.com/tj/commander.js/tree/v7.2.0)), distributed under the [MIT License](https://github.com/tj/commander.js/blob/v7.2.0/LICENSE):
|
|
1931
1933
|
|
|
1932
1934
|
```
|
|
1933
1935
|
(The MIT License)
|
|
@@ -2016,7 +2018,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
2016
2018
|
|
|
2017
2019
|
### fastify
|
|
2018
2020
|
|
|
2019
|
-
This product includes source derived from [fastify](https://github.com/fastify/fastify) ([v2.
|
|
2021
|
+
This product includes source derived from [fastify](https://github.com/fastify/fastify) ([v2.15.3](https://github.com/fastify/fastify/tree/v2.15.3)), distributed under the [MIT License](https://github.com/fastify/fastify/blob/v2.15.3/LICENSE):
|
|
2020
2022
|
|
|
2021
2023
|
```
|
|
2022
2024
|
MIT License
|
|
@@ -2139,6 +2141,35 @@ THE SOFTWARE.
|
|
|
2139
2141
|
|
|
2140
2142
|
```
|
|
2141
2143
|
|
|
2144
|
+
### husky
|
|
2145
|
+
|
|
2146
|
+
This product includes source derived from [husky](https://github.com/typicode/husky) ([v6.0.0](https://github.com/typicode/husky/tree/v6.0.0)), distributed under the [MIT License](https://github.com/typicode/husky/blob/v6.0.0/LICENSE):
|
|
2147
|
+
|
|
2148
|
+
```
|
|
2149
|
+
MIT License
|
|
2150
|
+
|
|
2151
|
+
Copyright (c) 2021 typicode
|
|
2152
|
+
|
|
2153
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2154
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2155
|
+
in the Software without restriction, including without limitation the rights
|
|
2156
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2157
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2158
|
+
furnished to do so, subject to the following conditions:
|
|
2159
|
+
|
|
2160
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2161
|
+
copies or substantial portions of the Software.
|
|
2162
|
+
|
|
2163
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2164
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2165
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2166
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2167
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2168
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2169
|
+
SOFTWARE.
|
|
2170
|
+
|
|
2171
|
+
```
|
|
2172
|
+
|
|
2142
2173
|
### jsdoc
|
|
2143
2174
|
|
|
2144
2175
|
This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v3.6.3](https://github.com/jsdoc/jsdoc/tree/v3.6.3)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v3.6.3/LICENSE.md):
|
|
@@ -2249,6 +2280,35 @@ https://github.com/jmblog/color-themes-for-google-code-prettify
|
|
|
2249
2280
|
|
|
2250
2281
|
```
|
|
2251
2282
|
|
|
2283
|
+
### lint-staged
|
|
2284
|
+
|
|
2285
|
+
This product includes source derived from [lint-staged](https://github.com/okonet/lint-staged) ([v11.0.0](https://github.com/okonet/lint-staged/tree/v11.0.0)), distributed under the [MIT License](https://github.com/okonet/lint-staged/blob/v11.0.0/LICENSE):
|
|
2286
|
+
|
|
2287
|
+
```
|
|
2288
|
+
The MIT License (MIT)
|
|
2289
|
+
|
|
2290
|
+
Copyright (c) 2016 Andrey Okonetchnikov
|
|
2291
|
+
|
|
2292
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2293
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2294
|
+
in the Software without restriction, including without limitation the rights
|
|
2295
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2296
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2297
|
+
furnished to do so, subject to the following conditions:
|
|
2298
|
+
|
|
2299
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2300
|
+
copies or substantial portions of the Software.
|
|
2301
|
+
|
|
2302
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2303
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2304
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2305
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2306
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2307
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2308
|
+
SOFTWARE.
|
|
2309
|
+
|
|
2310
|
+
```
|
|
2311
|
+
|
|
2252
2312
|
### memcached
|
|
2253
2313
|
|
|
2254
2314
|
This product includes source derived from [memcached](https://github.com/3rd-Eden/node-memcached) ([v2.2.2](https://github.com/3rd-Eden/node-memcached/tree/v2.2.2)), distributed under the [MIT License](https://github.com/3rd-Eden/node-memcached/blob/v2.2.2/LICENSE):
|
package/lib/collector/api.js
CHANGED
|
@@ -117,6 +117,22 @@ CollectorAPI.prototype.connect = function connect(callback) {
|
|
|
117
117
|
this._reqHeadersMap = null
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Checks if proxy is configured to connect via `proxy_host` and `proxy_port`
|
|
122
|
+
* and if error code is EPROTO or ECONNRESET. This is an indication their proxy
|
|
123
|
+
* server only accepts HTTP connections, and we should provide an actionable warning to
|
|
124
|
+
* fix the misconfiguration by setting `proxy` to a fully qualified URL
|
|
125
|
+
*
|
|
126
|
+
* @param {Error} error
|
|
127
|
+
* @returns {Boolean}
|
|
128
|
+
*/
|
|
129
|
+
function isProxyMisconfigured(error) {
|
|
130
|
+
const config = api._agent.config
|
|
131
|
+
return error &&
|
|
132
|
+
['EPROTO', 'ECONNRESET'].includes(error.code) &&
|
|
133
|
+
config.proxy_host && config.proxy_port && !config.proxy
|
|
134
|
+
}
|
|
135
|
+
|
|
120
136
|
function retry(error, response) {
|
|
121
137
|
metric.incrementCallCount()
|
|
122
138
|
|
|
@@ -142,6 +158,14 @@ CollectorAPI.prototype.connect = function connect(callback) {
|
|
|
142
158
|
' (status code %s)',
|
|
143
159
|
response.status
|
|
144
160
|
)
|
|
161
|
+
} else if (isProxyMisconfigured(error)) {
|
|
162
|
+
logger.warn(
|
|
163
|
+
error,
|
|
164
|
+
'Your proxy server appears to be configured to accept connections over http. ' +
|
|
165
|
+
'When setting `proxy_host` and `proxy_port` New Relic attempts to connect over ' +
|
|
166
|
+
'SSL(https). If your proxy is configured to accept connections over http, try ' +
|
|
167
|
+
'setting `proxy` to a fully qualified URL(e.g http://proxy-host:8080).'
|
|
168
|
+
)
|
|
145
169
|
}
|
|
146
170
|
|
|
147
171
|
let backoff = BACKOFFS[Math.min(attempts, max) - 1]
|
package/lib/collector/facts.js
CHANGED
package/lib/config/index.js
CHANGED
|
@@ -32,14 +32,6 @@ const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1000000
|
|
|
32
32
|
const DEFAULT_CONFIG_PATH = require.resolve('./default')
|
|
33
33
|
const SPAN_EVENT_LIMIT = 1000
|
|
34
34
|
const BASE_CONFIG_PATH = require.resolve('../../newrelic')
|
|
35
|
-
const DEFAULT_FILENAME = 'newrelic.js'
|
|
36
|
-
const CONFIG_FILE_LOCATIONS = [
|
|
37
|
-
process.env.NEW_RELIC_HOME,
|
|
38
|
-
process.cwd(),
|
|
39
|
-
process.env.HOME,
|
|
40
|
-
path.join(__dirname, '../../../..') // above node_modules
|
|
41
|
-
]
|
|
42
|
-
|
|
43
35
|
const HAS_ARBITRARY_KEYS = new Set([
|
|
44
36
|
'ignore_messages',
|
|
45
37
|
'expected_messages',
|
|
@@ -54,10 +46,22 @@ const exists = fs.existsSync || path.existsSync
|
|
|
54
46
|
let logger = null // Lazy-loaded in `initialize`.
|
|
55
47
|
let _configInstance = null
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
const getConfigFileNames = () => [
|
|
50
|
+
process.env.NEW_RELIC_CONFIG_FILENAME,
|
|
51
|
+
'newrelic.js',
|
|
52
|
+
'newrelic.cjs'
|
|
53
|
+
].filter(Boolean)
|
|
54
|
+
|
|
55
|
+
const getConfigFileLocations = () => [
|
|
56
|
+
process.env.NEW_RELIC_HOME,
|
|
57
|
+
process.cwd(),
|
|
58
|
+
process.env.HOME,
|
|
59
|
+
path.join(__dirname, '../../../..'), // above node_modules
|
|
60
|
+
// the REPL has no main module
|
|
61
|
+
process.mainModule && process.mainModule.filename
|
|
62
|
+
? path.dirname(process.mainModule.filename)
|
|
63
|
+
: undefined
|
|
64
|
+
].filter(Boolean)
|
|
61
65
|
|
|
62
66
|
function isTruthular(setting) {
|
|
63
67
|
if (setting == null) {
|
|
@@ -89,19 +93,15 @@ function fromObjectList(setting) {
|
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
function _findConfigFile() {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
for (var i = 0; i < CONFIG_FILE_LOCATIONS.length; i++) {
|
|
97
|
-
candidate = CONFIG_FILE_LOCATIONS[i]
|
|
98
|
-
if (!candidate) continue
|
|
96
|
+
const configFileCandidates = getConfigFileLocations().reduce((files, configPath) => {
|
|
97
|
+
const configFiles = getConfigFileNames().map(filename =>
|
|
98
|
+
path.join(path.resolve(configPath), filename)
|
|
99
|
+
)
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
return files.concat(configFiles)
|
|
102
|
+
}, [])
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
}
|
|
104
|
+
return configFileCandidates.find(exists)
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
function Config(config) {
|
package/lib/grpc/connection.js
CHANGED
|
@@ -11,6 +11,12 @@ const logger = require('../logger').child({component: 'grpc_connection'})
|
|
|
11
11
|
const EventEmitter = require('events')
|
|
12
12
|
const NAMES = require('../metrics/names')
|
|
13
13
|
const util = require('util')
|
|
14
|
+
const GRPC_TEST_META = {
|
|
15
|
+
flaky: 'NEWRELIC_GRPCCONNECTION_METADATA_FLAKY',
|
|
16
|
+
delay: 'NEWRELIC_GRPCCONNECTION_METADATA_DELAY',
|
|
17
|
+
flaky_code: 'NEWRELIC_GRPCCONNECTION_METADATA_FLAKY_CODE',
|
|
18
|
+
success_delay_ms: 'NEWRELIC_GRPCCONNECTION_METADATA_SUCCESS_DELAY_MS'
|
|
19
|
+
}
|
|
14
20
|
|
|
15
21
|
const connectionStates = require('./connection/states')
|
|
16
22
|
|
|
@@ -163,22 +169,27 @@ class GrpcConnection extends EventEmitter {
|
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
171
|
|
|
166
|
-
|
|
167
|
-
// pass to server via meta-data.
|
|
168
|
-
const flaky = parseInt(env.NEWRELIC_GRPCCONNECTION_METADATA_FLAKY, 10)
|
|
169
|
-
const delay = parseInt(env.NEWRELIC_GRPCCONNECTION_METADATA_DELAY, 10)
|
|
170
|
-
if (flaky) {
|
|
171
|
-
logger.trace('Adding flaky metadata: %s', flaky)
|
|
172
|
-
metadata.add('flaky', flaky)
|
|
173
|
-
}
|
|
174
|
-
if (delay) {
|
|
175
|
-
logger.trace('Adding delay metadata: %s', delay)
|
|
176
|
-
metadata.add('delay',delay)
|
|
177
|
-
}
|
|
172
|
+
this._setTestMetadata(metadata, env)
|
|
178
173
|
|
|
179
174
|
return metadata
|
|
180
175
|
}
|
|
181
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Adds test metadata used to simulate connectivity issues
|
|
179
|
+
* when appropriate env vars are set
|
|
180
|
+
*
|
|
181
|
+
* @param {Metadata} metadata
|
|
182
|
+
*/
|
|
183
|
+
_setTestMetadata(metadata, env) {
|
|
184
|
+
for (const [key, envVar] of Object.entries(GRPC_TEST_META)) {
|
|
185
|
+
const value = parseInt(env[envVar], 10)
|
|
186
|
+
if (value) {
|
|
187
|
+
logger.trace('Adding %s metadata: %s', key, value)
|
|
188
|
+
metadata.add(key, value)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
182
193
|
/**
|
|
183
194
|
* Disconnects from gRPC endpoint and schedules establishing a new connection.
|
|
184
195
|
* @param {number} reconnectDelayMs number of milliseconds to wait before reconnecting.
|
|
@@ -191,6 +191,10 @@ function getPromiseResolveStyleHooks(segmentMap, agent, shim) {
|
|
|
191
191
|
if (hookSegment === null) {
|
|
192
192
|
shim.setActiveSegment(hookSegment)
|
|
193
193
|
}
|
|
194
|
+
},
|
|
195
|
+
destroy: function destroyHandler(id) {
|
|
196
|
+
// Clean up any unresolved promises that have been destroyed.
|
|
197
|
+
segmentMap.delete(id)
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
|
|
@@ -10,7 +10,6 @@ var urltils = require('../../util/urltils')
|
|
|
10
10
|
var hashes = require('../../util/hashes')
|
|
11
11
|
var logger = require('../../logger').child({component: 'outbound'})
|
|
12
12
|
var shimmer = require('../../shimmer')
|
|
13
|
-
var util = require('util')
|
|
14
13
|
var url = require('url')
|
|
15
14
|
var copy = require('../../util/copy')
|
|
16
15
|
|
|
@@ -110,7 +109,7 @@ module.exports = function instrumentOutbound(agent, opts, makeRequest) {
|
|
|
110
109
|
logger.trace('CAT disabled, not adding headers!')
|
|
111
110
|
}
|
|
112
111
|
|
|
113
|
-
if (
|
|
112
|
+
if (Array.isArray(opts.headers)) {
|
|
114
113
|
opts.headers = opts.headers.slice()
|
|
115
114
|
Array.prototype.push.apply(
|
|
116
115
|
opts.headers,
|
|
@@ -203,7 +202,7 @@ function handleResponse(segment, hostname, req, res) {
|
|
|
203
202
|
// Add response attributes for spans
|
|
204
203
|
segment.addSpanAttribute('http.statusCode', res.statusCode)
|
|
205
204
|
segment.addSpanAttribute('http.statusText', res.statusMessage)
|
|
206
|
-
|
|
205
|
+
|
|
207
206
|
// If CAT is enabled, grab those headers!
|
|
208
207
|
const agent = segment.transaction.agent
|
|
209
208
|
if (
|
|
@@ -11,7 +11,6 @@ const recordWeb = require('../../metrics/recorders/http')
|
|
|
11
11
|
const hashes = require('../../util/hashes')
|
|
12
12
|
const cat = require('../../util/cat')
|
|
13
13
|
const instrumentOutbound = require('./http-outbound')
|
|
14
|
-
const util = require('util')
|
|
15
14
|
const url = require('url')
|
|
16
15
|
const urltils = require('../../util/urltils')
|
|
17
16
|
const properties = require('../../util/properties')
|
|
@@ -606,7 +605,7 @@ function parseSyntheticsHeader(header, encKey, trustedIds) {
|
|
|
606
605
|
return
|
|
607
606
|
}
|
|
608
607
|
|
|
609
|
-
if (!
|
|
608
|
+
if (!Array.isArray(synthData)) {
|
|
610
609
|
logger.trace(
|
|
611
610
|
'Synthetics data is not an array: %s (%s)',
|
|
612
611
|
synthData,
|
|
@@ -288,7 +288,7 @@ function makeQueryDescFunc(shim, methodName) {
|
|
|
288
288
|
// segment name does not actually use query string
|
|
289
289
|
// method name is set as query so the query parser has access to the op name
|
|
290
290
|
const parameters = getInstanceAttributeParameters(shim, this)
|
|
291
|
-
return {query: methodName, parameters, callback: shim.LAST}
|
|
291
|
+
return {query: methodName, parameters, promise: true, callback: shim.LAST}
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
package/lib/shim/shim.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
const arity = require('../util/arity')
|
|
9
9
|
const constants = require('./constants')
|
|
10
|
-
const events = require('events')
|
|
11
10
|
const hasOwnProperty = require('../util/properties').hasOwn
|
|
12
11
|
const logger = require('../logger').child({component: 'Shim'})
|
|
13
12
|
const path = require('path')
|
|
@@ -127,7 +126,6 @@ Shim.prototype.isNull = isNull
|
|
|
127
126
|
Shim.prototype.toArray = toArray
|
|
128
127
|
Shim.prototype.argsToArray = argsToArray
|
|
129
128
|
Shim.prototype.normalizeIndex = normalizeIndex
|
|
130
|
-
Shim.prototype.listenerCount = listenerCount
|
|
131
129
|
Shim.prototype.once = once
|
|
132
130
|
|
|
133
131
|
Shim.prototype.setInternalProperty = setInternalProperty
|
|
@@ -1695,23 +1693,6 @@ function normalizeIndex(arrayLength, idx) {
|
|
|
1695
1693
|
return (idx < 0 || idx >= arrayLength) ? null : idx
|
|
1696
1694
|
}
|
|
1697
1695
|
|
|
1698
|
-
/**
|
|
1699
|
-
* Retrieves the number of listeners for the given event.
|
|
1700
|
-
*
|
|
1701
|
-
* @memberof Shim.prototype
|
|
1702
|
-
*
|
|
1703
|
-
* @param {object} emitter - The emitter to count the listeners on.
|
|
1704
|
-
* @param {string} event - The event to count.
|
|
1705
|
-
*
|
|
1706
|
-
* @return {number} The number of listeners on the given event for this emitter.
|
|
1707
|
-
*/
|
|
1708
|
-
function listenerCount(emitter, evnt) {
|
|
1709
|
-
if (events.EventEmitter.listenerCount) {
|
|
1710
|
-
return events.EventEmitter.listenerCount(emitter, evnt)
|
|
1711
|
-
}
|
|
1712
|
-
return emitter.listeners(evnt).length
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
1696
|
/**
|
|
1716
1697
|
* Wraps a function such that it will only be executed once.
|
|
1717
1698
|
*
|
|
@@ -11,22 +11,31 @@ const SpanEventAggregator = require('./span-event-aggregator')
|
|
|
11
11
|
const StreamingSpanEventAggregator = require('./streaming-span-event-aggregator')
|
|
12
12
|
|
|
13
13
|
function createSpanEventAggregator(config, collector, metrics) {
|
|
14
|
+
const trace_observer = config.infinite_tracing.trace_observer
|
|
15
|
+
|
|
14
16
|
let shouldCreateStreaming = false
|
|
15
|
-
if (
|
|
17
|
+
if (trace_observer.host) {
|
|
16
18
|
// TODO: ideally this validation and configuration clearing would happen
|
|
17
19
|
// in the config. Since we don't currently have a way to generate
|
|
18
20
|
// support metrics in the config, keeping this related logic together here.
|
|
19
21
|
// If logic happened prior, could merely check for existence of trace_observer.host.
|
|
20
|
-
shouldCreateStreaming = validateInfiniteTracing(
|
|
22
|
+
shouldCreateStreaming = validateInfiniteTracing()
|
|
21
23
|
|
|
22
24
|
if (!shouldCreateStreaming) {
|
|
23
25
|
// Explicitly disable for any downstream consumers
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
trace_observer.host = ''
|
|
27
|
+
trace_observer.port = ''
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
if (shouldCreateStreaming) {
|
|
32
|
+
trace_observer.host = trace_observer.host.trim()
|
|
33
|
+
|
|
34
|
+
if (typeof trace_observer.port !== 'string') {
|
|
35
|
+
trace_observer.port = String(trace_observer.port)
|
|
36
|
+
}
|
|
37
|
+
trace_observer.port = trace_observer.port.trim()
|
|
38
|
+
|
|
30
39
|
return createStreamingAggregator(config, collector, metrics)
|
|
31
40
|
}
|
|
32
41
|
|
|
@@ -71,7 +80,7 @@ function createStandardAggregator(config, collector, metrics) {
|
|
|
71
80
|
return aggregator
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
function validateInfiniteTracing(
|
|
83
|
+
function validateInfiniteTracing() {
|
|
75
84
|
// TODO: Remove semver check when Node 10 support dropped.
|
|
76
85
|
if (!psemver.satisfies('>=10.10.0')) {
|
|
77
86
|
logger.warn(
|
|
@@ -80,40 +89,7 @@ function validateInfiniteTracing(trace_observer) {
|
|
|
80
89
|
return false
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
trace_observer.host = trace_observer.host.trim()
|
|
84
|
-
|
|
85
|
-
if (!validateHostName(trace_observer.host)) {
|
|
86
|
-
logger.warn('Infinite tracing disabled: invalid infinite_tracing.trace_observer.host value')
|
|
87
|
-
|
|
88
|
-
return false
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (typeof trace_observer.port !== 'string') {
|
|
92
|
-
trace_observer.port = String(trace_observer.port)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
trace_observer.port = trace_observer.port.trim()
|
|
96
|
-
|
|
97
|
-
if (!validatePortValue(trace_observer.port)) {
|
|
98
|
-
logger.warn('Infinite tracing disabled: invalid infinite_tracing.trace_observer.port value')
|
|
99
|
-
|
|
100
|
-
return false
|
|
101
|
-
}
|
|
102
|
-
|
|
103
92
|
return true
|
|
104
93
|
}
|
|
105
94
|
|
|
106
|
-
function validateHostName(host) {
|
|
107
|
-
// Regular expression for validating a hostname
|
|
108
|
-
const hostReg = /(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)/
|
|
109
|
-
|
|
110
|
-
return hostReg.test(host)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function validatePortValue(port) {
|
|
114
|
-
if (port.length === 0) return false
|
|
115
|
-
|
|
116
|
-
return !isNaN(port)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
95
|
module.exports = createSpanEventAggregator
|
package/lib/util/cat.js
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var logger = require('../logger').child({component: 'cat'})
|
|
8
|
+
const hashes = require('./hashes')
|
|
9
|
+
const logger = require('../logger').child({component: 'cat'})
|
|
11
10
|
|
|
12
11
|
module.exports.handleCatHeaders = handleCatHeaders
|
|
13
12
|
module.exports.parsedHeadersToTrans = parsedHeadersToTrans
|
|
@@ -43,7 +42,7 @@ function parsedHeadersToTrans(parsedCatId, externalTrans, transaction) {
|
|
|
43
42
|
transaction.incomingCatId = parsedCatId
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
if (
|
|
45
|
+
if (Array.isArray(externalTrans)) {
|
|
47
46
|
transaction.referringTransactionGuid = externalTrans[0]
|
|
48
47
|
if (typeof externalTrans[2] === 'string') {
|
|
49
48
|
transaction.tripId = externalTrans[2]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.2",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"contributors": [
|
|
@@ -120,16 +120,15 @@
|
|
|
120
120
|
"scripts": {
|
|
121
121
|
"bench": "node ./bin/run-bench.js",
|
|
122
122
|
"ca-gen": "./bin/update-ca-bundle.sh",
|
|
123
|
-
"clean": "./bin/clean.sh",
|
|
124
123
|
"docker-env": "./bin/docker-env-vars.sh",
|
|
125
124
|
"docs": "npm ci && jsdoc -c ./jsdoc-conf.json --private -r .",
|
|
126
125
|
"integration": "npm run prepare-test && npm run sub-install && time tap --no-esm test/integration/**/**/*.tap.js --timeout=180 --no-coverage",
|
|
127
|
-
"prepare-test": "npm
|
|
126
|
+
"prepare-test": "npm run ca-gen && npm run ssl && npm run docker-env",
|
|
128
127
|
"lint": "eslint ./*.js lib test bin",
|
|
129
128
|
"public-docs": "npm ci && jsdoc -c ./jsdoc-conf.json --tutorials examples/shim api.js lib/shim/ lib/transaction/handle.js && cp examples/shim/*.png out/",
|
|
130
129
|
"publish-docs": "./bin/publish-docs.sh",
|
|
131
130
|
"services": "./bin/docker-services.sh",
|
|
132
|
-
"smoke": "npm run
|
|
131
|
+
"smoke": "npm run ssl && time tap test/smoke/**/**/*.tap.js --timeout=180 --no-coverage",
|
|
133
132
|
"ssl": "./bin/ssl.sh",
|
|
134
133
|
"sub-install": "node test/bin/install_sub_deps",
|
|
135
134
|
"test": "npm run integration && npm run unit",
|
|
@@ -137,7 +136,8 @@
|
|
|
137
136
|
"update-cross-agent-tests": "./bin/update-cats.sh",
|
|
138
137
|
"versioned-tests": "./bin/run-versioned-tests.sh",
|
|
139
138
|
"update-changelog-version": "node ./bin/update-changelog-version",
|
|
140
|
-
"versioned": "npm run prepare-test && time ./bin/run-versioned-tests.sh"
|
|
139
|
+
"versioned": "npm run prepare-test && time ./bin/run-versioned-tests.sh",
|
|
140
|
+
"prepare": "husky install"
|
|
141
141
|
},
|
|
142
142
|
"bin": {
|
|
143
143
|
"newrelic-naming-rules": "./bin/test-naming-rules.js"
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
},
|
|
162
162
|
"devDependencies": {
|
|
163
163
|
"@newrelic/proxy": "^2.0.0",
|
|
164
|
-
"@newrelic/test-utilities": "^5.
|
|
164
|
+
"@newrelic/test-utilities": "^5.1.0",
|
|
165
165
|
"@octokit/rest": "^18.0.15",
|
|
166
166
|
"JSV": "~4.0.2",
|
|
167
167
|
"architect": "*",
|
|
@@ -176,7 +176,9 @@
|
|
|
176
176
|
"glob": "^7.1.2",
|
|
177
177
|
"got": "^8.0.1",
|
|
178
178
|
"http-errors": "^1.7.3",
|
|
179
|
+
"husky": "^6.0.0",
|
|
179
180
|
"jsdoc": "^3.6.3",
|
|
181
|
+
"lint-staged": "^11.0.0",
|
|
180
182
|
"memcached": ">=0.2.8",
|
|
181
183
|
"minami": "^1.1.1",
|
|
182
184
|
"mongodb": "^3.3.3",
|