newrelic 8.13.2 → 8.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.
@@ -296,7 +296,7 @@ This product includes source derived from [@grpc/grpc-js](https://github.com/grp
296
296
 
297
297
  ### @grpc/proto-loader
298
298
 
299
- This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.6.12](https://github.com/grpc/grpc-node/tree/v0.6.12)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.6.12/LICENSE):
299
+ This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.6.13](https://github.com/grpc/grpc-node/tree/v0.6.13)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.6.13/LICENSE):
300
300
 
301
301
  ```
302
302
  Apache License
@@ -1801,7 +1801,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
1801
1801
 
1802
1802
  ### @newrelic/test-utilities
1803
1803
 
1804
- This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v6.5.4](https://github.com/newrelic/node-test-utilities/tree/v6.5.4)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v6.5.4/LICENSE):
1804
+ This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v6.5.5](https://github.com/newrelic/node-test-utilities/tree/v6.5.5)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v6.5.5/LICENSE):
1805
1805
 
1806
1806
  ```
1807
1807
  Apache License
package/api.js CHANGED
@@ -27,8 +27,9 @@ const NAMES = require('./lib/metrics/names')
27
27
  * CONSTANTS
28
28
  *
29
29
  */
30
- const RUM_STUB = 'window.NREUM||(NREUM={});NREUM.info = %s;'
31
- const RUM_STUB_SHELL = `<script type='text/javascript' %s>${RUM_STUB} %s</script>`
30
+ const RUM_STUB = 'window.NREUM||(NREUM={});NREUM.info = %s; %s'
31
+ const RUM_STUB_SHELL = `<script type='text/javascript'>${RUM_STUB}</script>`
32
+ const RUM_STUB_SHELL_WITH_NONCE_PARAM = `<script type='text/javascript' %s>${RUM_STUB}</script>`
32
33
 
33
34
  // these messages are used in the _gracefail() method below in getBrowserTimingHeader
34
35
  const RUM_ISSUES = [
@@ -653,12 +654,18 @@ API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader(options)
653
654
  const tabs = config.browser_monitoring.debug ? 2 : 0
654
655
  const json = JSON.stringify(rumHash, null, tabs)
655
656
 
656
- // set nonce attribute if passed in options
657
- const nonce = options && options.nonce ? 'nonce="' + options.nonce + '"' : ''
658
- const script = options && options.hasToRemoveScriptWrapper ? RUM_STUB : RUM_STUB_SHELL
659
-
660
657
  // the complete header to be written to the browser
661
- const out = util.format(script, nonce, json, jsAgentLoader)
658
+ const out =
659
+ options && options.hasToRemoveScriptWrapper
660
+ ? util.format(RUM_STUB, json, jsAgentLoader)
661
+ : options && options.nonce
662
+ ? util.format(
663
+ RUM_STUB_SHELL_WITH_NONCE_PARAM,
664
+ 'nonce="' + options.nonce + '"',
665
+ json,
666
+ jsAgentLoader
667
+ )
668
+ : util.format(RUM_STUB_SHELL, json, jsAgentLoader)
662
669
 
663
670
  logger.trace('generating RUM header', out)
664
671
 
@@ -38,12 +38,12 @@ class LogAggregator extends EventAggregator {
38
38
 
39
39
  /**
40
40
  * Due to logging library implementation details
41
- * some log lines are already JSON. We must de-serialize
42
- * so it can be serialized in RemoteMethod. I know, this sucks.
41
+ * some "log lines" are a function that formats the
42
+ * data accordingly into an Object, I know, this sucks.
43
43
  */
44
44
  const formattedLogs = logs.map((logLine) => {
45
- if (typeof logLine === 'string') {
46
- return JSON.parse(logLine)
45
+ if (typeof logLine === 'function') {
46
+ return logLine()
47
47
  }
48
48
 
49
49
  return logLine
@@ -974,5 +974,14 @@ exports.config = () => ({
974
974
  */
975
975
  enabled: false
976
976
  }
977
- }
977
+ },
978
+
979
+ /**
980
+ * You may want more control over how your agent is configured and want to
981
+ * disallow the use of New Relic's server-side configuration for agents.
982
+ * To do so, set this to true.
983
+ *
984
+ * @env NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG
985
+ */
986
+ ignore_server_configuration: false
978
987
  })
package/lib/config/env.js CHANGED
@@ -180,7 +180,8 @@ const ENV_MAPPING = {
180
180
  local_decorating: {
181
181
  enabled: 'NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED'
182
182
  }
183
- }
183
+ },
184
+ ignore_server_configuration: 'NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG'
184
185
  }
185
186
 
186
187
  // List of environment values which are comma-delimited lists.
@@ -259,7 +260,8 @@ const BOOLEAN_VARS = new Set([
259
260
  'NEW_RELIC_APPLICATION_LOGGING_ENABLED',
260
261
  'NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED',
261
262
  'NEW_RELIC_APPLICATION_LOGGING_METRICS_ENABLED',
262
- 'NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED'
263
+ 'NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED',
264
+ 'NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG'
263
265
  ])
264
266
 
265
267
  const FLOAT_VARS = new Set(['NEW_RELIC_APDEX_T', 'NEW_RELIC_TRACER_THRESHOLD'])
@@ -275,9 +275,14 @@ Config.prototype._fromServer = function _fromServer(params, key) {
275
275
  case 'messages':
276
276
  break
277
277
 
278
- // *sigh* Xzibit, etc.
278
+ // per the spec this is the key where all server side configuration values will come from.
279
279
  case 'agent_config':
280
- this.onConnect(params[key], true)
280
+ if (this.ignore_server_configuration) {
281
+ this.logDisabled(params, key)
282
+ } else {
283
+ this.onConnect(params[key], true)
284
+ }
285
+
281
286
  break
282
287
 
283
288
  // if it's undefined or null, so be it
@@ -1307,15 +1312,6 @@ Config.prototype._canonicalize = function _canonicalize() {
1307
1312
  }
1308
1313
  }
1309
1314
 
1310
- if (isTruthular(this.ignore_server_configuration)) {
1311
- logger.warnOnce(
1312
- 'IgnoreServerConfigurationWarning',
1313
- 'The local config setting `ignore_server_configuration` has been deprecated ' +
1314
- 'and removed as of Agent v5. Please review agent documentation or contact ' +
1315
- 'New Relic support.'
1316
- )
1317
- }
1318
-
1319
1315
  if (this.license_key) {
1320
1316
  this.license_key = this.license_key.trim()
1321
1317
  }
@@ -54,7 +54,7 @@ module.exports = function initialize(agent, redis, moduleName, shim) {
54
54
  function getRedisParams(opts) {
55
55
  return {
56
56
  host: (opts.socket && opts.socket.host) || 'localhost',
57
- port_path_or_id: (opts.socket && opts.socket.path) || opts.socket.port || '6379',
57
+ port_path_or_id: (opts.socket && (opts.socket.path || opts.socket.port)) || '6379',
58
58
  database_name: opts.database || 0
59
59
  }
60
60
  }
@@ -0,0 +1,85 @@
1
+ /*
2
+ * Copyright 2022 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const recordExternal = require('../../metrics/recorders/http_external')
9
+
10
+ module.exports = function instrument(shim) {
11
+ const callStream = shim.require('./build/src/call-stream')
12
+ shim.wrap(callStream.Http2CallStream.prototype, 'start', (shim, original) => {
13
+ return function wrappedStart() {
14
+ const activeSegment = shim.getActiveSegment()
15
+ if (!activeSegment) {
16
+ return original.apply(this, arguments)
17
+ }
18
+
19
+ const channel = this.channel
20
+ const authorityName = (channel.target && channel.target.path) || channel.getDefaultAuthority
21
+
22
+ const segment = shim.createSegment({
23
+ name: `External/${authorityName}${this.methodName}`,
24
+ opaque: true,
25
+ recorder: recordExternal(authorityName, 'gRPC')
26
+ })
27
+
28
+ return shim.applySegment(callStart, segment, true, this, arguments)
29
+
30
+ function callStart() {
31
+ const args = shim.argsToArray.apply(shim, arguments)
32
+
33
+ const transaction = segment.transaction
34
+
35
+ const originalMetadata = args[0]
36
+ const nrMetadata = originalMetadata.clone()
37
+
38
+ const outboundAgentHeaders = Object.create(null)
39
+ if (shim.agent.config.distributed_tracing.enabled) {
40
+ transaction.insertDistributedTraceHeaders(outboundAgentHeaders)
41
+ Object.keys(outboundAgentHeaders).forEach((key) => {
42
+ nrMetadata.add(key, outboundAgentHeaders[key])
43
+ })
44
+ } else {
45
+ shim.logger.debug('Distributed tracing disabled by instrumentation.')
46
+ }
47
+
48
+ args[0] = nrMetadata
49
+
50
+ const originalListener = args[1]
51
+ const nrListener = Object.assign({}, originalListener)
52
+ nrListener.onReceiveStatus = (status) => {
53
+ const { code, details } = status
54
+
55
+ segment.addAttribute('grpc.statusCode', code)
56
+ segment.addAttribute('grpc.statusText', details)
57
+
58
+ // Java captures client errors based on status code
59
+ // but has specific gRPC configuration to turn off
60
+ if (code !== 0) {
61
+ // this is currently just creating an error from the details string
62
+ shim.agent.errors.add(segment.transaction, details)
63
+ }
64
+
65
+ segment.addAttribute('component', 'gRPC')
66
+
67
+ const protocol = 'grpc'
68
+
69
+ const url = `${protocol}://${authorityName}${this.methodName}`
70
+
71
+ segment.addAttribute('http.url', url)
72
+ segment.addAttribute('http.method', this.methodName)
73
+
74
+ segment.end()
75
+
76
+ originalListener && originalListener.onReceiveStatus(status)
77
+ }
78
+
79
+ args[1] = nrListener
80
+
81
+ return original.apply(this, args)
82
+ }
83
+ }
84
+ })
85
+ }
@@ -0,0 +1,19 @@
1
+ /*
2
+ * Copyright 2022 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const grpc = require('./grpc')
8
+
9
+ /**
10
+ * Need to use nr-hooks style for grpc because we're using the onResolved hook
11
+ * to register instrumentation.
12
+ */
13
+ module.exports = [
14
+ {
15
+ type: 'generic',
16
+ moduleName: '@grpc/grpc-js',
17
+ onResolved: grpc
18
+ }
19
+ ]
@@ -49,20 +49,6 @@ module.exports = function instrument(shim) {
49
49
 
50
50
  const symbols = shim.require('./lib/symbols')
51
51
 
52
- /**
53
- * Wraps the level cache so we can properly set a formatter to return the
54
- * label as level in log line instead of number
55
- */
56
- shim.wrap(levelUtils, 'genLsCache', function genLsCache(shim, genLevelsCache) {
57
- return function wrappedGenLsCache() {
58
- const args = shim.argsToArray.apply(shim, arguments)
59
- args[0][symbols.formattersSym].level = function nrLevelMapping(label) {
60
- return { level: label }
61
- }
62
- return genLevelsCache.apply(this, args)
63
- }
64
- })
65
-
66
52
  shim.wrap(tools, 'asJson', function wrapJson(shim, asJson) {
67
53
  /**
68
54
  * Wraps function in pino that is used to construct/serialize a log
@@ -75,27 +61,14 @@ module.exports = function instrument(shim) {
75
61
  * @returns {string} serialized log line
76
62
  */
77
63
  return function wrappedAsJson() {
78
- // overriding the symbol that defines the key for message(pino defaults this to `msg`)
79
- this[symbols.messageKeySym] = 'message'
80
-
81
64
  const args = shim.argsToArray.apply(shim, arguments)
82
65
 
83
- /**
84
- * changing the label from time to timestamp
85
- * and assign unix timestamp to match our specification
86
- */
87
- args[3] = `,"timestamp":${Date.now()}`
88
-
89
66
  if (isMetricsEnabled(config)) {
90
67
  const level = args[2]
91
68
  incrementLoggingLinesMetrics(levelMap[level], metrics)
92
69
  }
93
70
 
94
- if (isLogForwardingEnabled(config, agent)) {
95
- const metadata = agent.getLinkingMetadata()
96
- const chindings = this[symbols.chindingsSym]
97
- reformatLogLine(args[0], metadata, chindings)
98
- } else if (isLocalDecoratingEnabled(config)) {
71
+ if (isLocalDecoratingEnabled(config)) {
99
72
  args[1] += agent.getNRLinkingMetadata()
100
73
  }
101
74
 
@@ -107,7 +80,10 @@ module.exports = function instrument(shim) {
107
80
  const logLine = asJson.apply(this, args)
108
81
 
109
82
  if (isLogForwardingEnabled(config, agent)) {
110
- agent.logs.add(logLine)
83
+ const chindings = this[symbols.chindingsSym]
84
+ const formatLogLine = reformatLogLine({ msg: args[1], logLine, agent, chindings, levelMap })
85
+
86
+ agent.logs.add(formatLogLine)
111
87
  }
112
88
 
113
89
  return logLine
@@ -119,14 +95,18 @@ module.exports = function instrument(shim) {
119
95
  * reformats error and assigns NR context data
120
96
  * to log line
121
97
  *
98
+ * @param logLine.logLine
122
99
  * @param {object} logLine log line
123
100
  * @param {object} metadata NR context data
124
101
  * @param {string} chindings serialized string of all common log line data
102
+ * @param logLine.args
103
+ * @param logLine.agent
104
+ * @param logLine.chindings
105
+ * @param logLine.msg
106
+ * @param logLine.levelMap
125
107
  */
126
- function reformatLogLine(logLine, metadata, chindings = '') {
127
- if (logLine.err) {
128
- reformatError(logLine)
129
- }
108
+ function reformatLogLine({ logLine, msg, agent, chindings = '', levelMap }) {
109
+ const metadata = agent.getLinkingMetadata()
130
110
 
131
111
  /**
132
112
  * pino adds this already for us at times
@@ -137,7 +117,24 @@ function reformatLogLine(logLine, metadata, chindings = '') {
137
117
  delete metadata.hostname
138
118
  }
139
119
 
140
- Object.assign(logLine, metadata)
120
+ const agentMeta = Object.assign({}, { timestamp: Date.now(), message: msg }, metadata)
121
+
122
+ /**
123
+ * A function that gets executed in `_toPayloadSync` of log aggregator.
124
+ * This will parse the serialized log line and then add the relevant NR
125
+ * context metadata and rename the time/msg keys to timestamp/message
126
+ */
127
+ return function formatLogLine() {
128
+ const formattedLog = JSON.parse(logLine)
129
+ if (formattedLog.err) {
130
+ reformatError(formattedLog)
131
+ }
132
+ Object.assign(formattedLog, agentMeta)
133
+ formattedLog.level = levelMap[formattedLog.level]
134
+ delete formattedLog.time
135
+ delete formattedLog.msg
136
+ return formattedLog
137
+ }
141
138
  }
142
139
 
143
140
  /**
@@ -150,7 +147,6 @@ function reformatLogLine(logLine, metadata, chindings = '') {
150
147
  function reformatError(logLine) {
151
148
  logLine['error.message'] = truncate(logLine.err.message)
152
149
  logLine['error.stack'] = truncate(logLine.err.stack)
153
- logLine['error.class'] =
154
- logLine.err.name === 'Error' ? logLine.err.constructor.name : logLine.err.name
150
+ logLine['error.class'] = logLine.err.type
155
151
  delete logLine.err
156
152
  }
@@ -29,8 +29,8 @@ module.exports = function instrument(agent, winston, _, shim) {
29
29
  shim.wrap(winston, 'createLogger', function wrapCreate(shim, createLogger) {
30
30
  return function createWrappedLogger() {
31
31
  const args = shim.argsToArray.apply(shim, arguments)
32
- const opts = args[0]
33
- if (!shim.isObject(opts) || isStream(opts)) {
32
+ const opts = args[0] || {}
33
+ if (isStream(opts)) {
34
34
  return createLogger.apply(this, args)
35
35
  }
36
36
 
@@ -19,6 +19,7 @@ module.exports = function instrumentations() {
19
19
  'express': { type: MODULE_TYPE.WEB_FRAMEWORK },
20
20
  'fastify': { type: MODULE_TYPE.WEB_FRAMEWORK },
21
21
  'generic-pool': { type: MODULE_TYPE.GENERIC },
22
+ '@grpc/grpc-js': { module: './instrumentation/grpc-js' },
22
23
  '@hapi/hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
23
24
  'hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
24
25
  'ioredis': { type: MODULE_TYPE.DATASTORE },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "8.13.2",
3
+ "version": "8.15.0",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
@@ -160,7 +160,7 @@
160
160
  },
161
161
  "dependencies": {
162
162
  "@grpc/grpc-js": "^1.5.5",
163
- "@grpc/proto-loader": "^0.6.12",
163
+ "@grpc/proto-loader": "^0.6.13",
164
164
  "@newrelic/aws-sdk": "^4.1.1",
165
165
  "@newrelic/koa": "^6.1.1",
166
166
  "@newrelic/superagent": "^5.1.0",
@@ -180,7 +180,7 @@
180
180
  "@newrelic/eslint-config": "^0.0.3",
181
181
  "@newrelic/newrelic-oss-cli": "^0.1.2",
182
182
  "@newrelic/proxy": "^2.0.0",
183
- "@newrelic/test-utilities": "^6.5.4",
183
+ "@newrelic/test-utilities": "^6.5.5",
184
184
  "@octokit/rest": "^18.0.15",
185
185
  "@slack/bolt": "^3.7.0",
186
186
  "ajv": "^6.12.6",
@@ -199,7 +199,7 @@
199
199
  "express": "*",
200
200
  "generic-pool": "^3.6.1",
201
201
  "glob": "^7.1.2",
202
- "got": "^8.0.1",
202
+ "got": "^11.8.5",
203
203
  "husky": "^6.0.0",
204
204
  "jsdoc": "^3.6.3",
205
205
  "lint-staged": "^11.0.0",