newrelic 9.7.0 → 9.7.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 +42 -18
- package/THIRD_PARTY_NOTICES.md +203 -2
- package/api.js +155 -103
- package/lib/agent.js +29 -82
- package/lib/collector/api.js +234 -201
- package/lib/config/attribute-filter.js +35 -25
- package/lib/config/default.js +45 -19
- package/lib/config/index.js +260 -199
- package/lib/environment.js +16 -12
- package/lib/errors/error-collector.js +124 -55
- package/lib/errors/index.js +59 -49
- package/lib/instrumentation/@hapi/hapi.js +56 -50
- package/lib/instrumentation/@node-redis/client.js +50 -41
- package/lib/instrumentation/amqplib.js +116 -151
- package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +193 -78
- package/lib/instrumentation/core/timers.js +106 -59
- package/lib/instrumentation/grpc-js/grpc.js +20 -23
- package/lib/instrumentation/mongodb/common.js +87 -85
- package/lib/instrumentation/redis.js +112 -90
- package/lib/instrumentation/undici.js +204 -192
- package/lib/instrumentation/{when.js → when/constants.js} +13 -10
- package/lib/instrumentation/when/contextualizer.js +168 -0
- package/lib/instrumentation/when/index.js +354 -0
- package/lib/instrumentation/when/nr-hooks.js +15 -0
- package/lib/instrumentations.js +1 -1
- package/lib/shim/shim.js +2 -0
- package/lib/shim/webframework-shim.js +19 -0
- package/lib/symbols.js +1 -0
- package/lib/system-info.js +240 -163
- package/lib/util/async-each-limit.js +30 -0
- package/lib/util/attributes.js +159 -0
- package/lib/util/code-level-metrics.js +58 -0
- package/lib/util/deep-equal.js +11 -144
- package/package.json +5 -4
- package/lib/instrumentation/promise.js +0 -572
package/lib/collector/api.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const http = require('http')
|
|
10
9
|
const CollectorResponse = require('./response')
|
|
11
10
|
const facts = require('./facts')
|
|
12
11
|
const logger = require('../logger').child({ component: 'collector_api' })
|
|
@@ -38,8 +37,8 @@ const FAILURE_DISCARD_DATA = new Set([400, 403, 404, 405, 407, 411, 413, 414, 41
|
|
|
38
37
|
const AGENT_RUN_BEHAVIOR = CollectorResponse.AGENT_RUN_BEHAVIOR
|
|
39
38
|
|
|
40
39
|
/**
|
|
41
|
-
* @param errors
|
|
42
|
-
* @param name
|
|
40
|
+
* @param {Array} errors list of errors
|
|
41
|
+
* @param {string} name collector endpoint name
|
|
43
42
|
*/
|
|
44
43
|
function dumpErrors(errors, name) {
|
|
45
44
|
let index = 1
|
|
@@ -56,7 +55,7 @@ function dumpErrors(errors, name) {
|
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
/**
|
|
59
|
-
* @param agent
|
|
58
|
+
* @param {Agent} agent New Relic agent
|
|
60
59
|
*/
|
|
61
60
|
function CollectorAPI(agent) {
|
|
62
61
|
this._agent = agent
|
|
@@ -99,7 +98,7 @@ CollectorAPI.prototype._throwCallbackError = function _throwCallbackError() {
|
|
|
99
98
|
* Updates all methods except preconnect w/ new host/port pairs sent down from server
|
|
100
99
|
* during preconnect (via redirect_host). Preconnect does not update.
|
|
101
100
|
*
|
|
102
|
-
* @param endpoint
|
|
101
|
+
* @param {string} endpoint collector name
|
|
103
102
|
*/
|
|
104
103
|
CollectorAPI.prototype._updateEndpoints = function _updateEndpoints(endpoint) {
|
|
105
104
|
logger.trace('Updating endpoints to: ', endpoint)
|
|
@@ -120,105 +119,109 @@ CollectorAPI.prototype.connect = function connect(callback) {
|
|
|
120
119
|
|
|
121
120
|
this._agent.setState('connecting')
|
|
122
121
|
|
|
123
|
-
const api = this
|
|
124
|
-
const max = BACKOFFS.length
|
|
125
|
-
const errors = []
|
|
126
|
-
let attempts = 1
|
|
127
|
-
|
|
128
|
-
const metric = this._agent.metrics.getOrCreateMetric(
|
|
129
|
-
NAMES.SUPPORTABILITY.REGISTRATION + '/Attempts'
|
|
130
|
-
)
|
|
131
|
-
|
|
132
122
|
// Reset headers map for good measure
|
|
133
123
|
if (this._reqHeadersMap) {
|
|
134
124
|
this._reqHeadersMap = null
|
|
135
125
|
}
|
|
136
126
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
*
|
|
143
|
-
* @param {Error} error
|
|
144
|
-
* @returns {boolean}
|
|
145
|
-
*/
|
|
146
|
-
function isProxyMisconfigured(error) {
|
|
147
|
-
const config = api._agent.config
|
|
148
|
-
return (
|
|
149
|
-
error &&
|
|
150
|
-
['EPROTO', 'ECONNRESET'].includes(error.code) &&
|
|
151
|
-
config.proxy_host &&
|
|
152
|
-
config.proxy_port &&
|
|
153
|
-
!config.proxy
|
|
154
|
-
)
|
|
127
|
+
const ctx = {
|
|
128
|
+
callback,
|
|
129
|
+
max: BACKOFFS.length,
|
|
130
|
+
errors: [],
|
|
131
|
+
attempts: 1
|
|
155
132
|
}
|
|
133
|
+
this._login(this._retry.bind(this, ctx))
|
|
134
|
+
}
|
|
156
135
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Checks if proxy is configured to connect via `proxy_host` and `proxy_port`
|
|
138
|
+
* and if error code is EPROTO or ECONNRESET. This is an indication their proxy
|
|
139
|
+
* server only accepts HTTP connections, and we should provide an actionable warning to
|
|
140
|
+
* fix the misconfiguration by setting `proxy` to a fully qualified URL
|
|
141
|
+
*
|
|
142
|
+
* @param {Error} error response error
|
|
143
|
+
* @returns {boolean} determines if proxy is properly configured
|
|
144
|
+
*/
|
|
145
|
+
CollectorAPI.prototype._isProxyMisconfigured = function _isProxyMisconfigured(error) {
|
|
146
|
+
const config = this._agent.config
|
|
147
|
+
return (
|
|
148
|
+
error &&
|
|
149
|
+
['EPROTO', 'ECONNRESET'].includes(error.code) &&
|
|
150
|
+
config.proxy_host &&
|
|
151
|
+
config.proxy_port &&
|
|
152
|
+
!config.proxy
|
|
153
|
+
)
|
|
154
|
+
}
|
|
163
155
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
156
|
+
/**
|
|
157
|
+
* @param {object} ctx context object to pass from parent and between recursions.
|
|
158
|
+
* @param {Error} error response error
|
|
159
|
+
* @param {http.ServerResponse} response response from collector
|
|
160
|
+
* @returns {void}
|
|
161
|
+
*/
|
|
162
|
+
CollectorAPI.prototype._retry = function _retry(ctx, error, response) {
|
|
163
|
+
const api = this
|
|
164
|
+
const metric = this._agent.metrics.getOrCreateMetric(
|
|
165
|
+
NAMES.SUPPORTABILITY.REGISTRATION + '/Attempts'
|
|
166
|
+
)
|
|
173
167
|
|
|
174
|
-
|
|
175
|
-
if (response.status === 410 || response.agentRun === AGENT_RUN_BEHAVIOR.SHUTDOWN) {
|
|
176
|
-
logger.error('The New Relic collector rejected this agent.')
|
|
177
|
-
return callback(null, CollectorResponse.fatal(response.payload))
|
|
178
|
-
} else if (response.status === 401) {
|
|
179
|
-
logger.warn(
|
|
180
|
-
error,
|
|
181
|
-
'Your license key appears to be invalid. Reattempting connection to New' +
|
|
182
|
-
' Relic. If the problem persists, please contact support@newrelic.com.' +
|
|
183
|
-
' (status code %s)',
|
|
184
|
-
response.status
|
|
185
|
-
)
|
|
186
|
-
} else if (isProxyMisconfigured(error)) {
|
|
187
|
-
logger.warn(
|
|
188
|
-
error,
|
|
189
|
-
'Your proxy server appears to be configured to accept connections over http. ' +
|
|
190
|
-
'When setting `proxy_host` and `proxy_port` New Relic attempts to connect over ' +
|
|
191
|
-
'SSL(https). If your proxy is configured to accept connections over http, try ' +
|
|
192
|
-
'setting `proxy` to a fully qualified URL(e.g http://proxy-host:8080).'
|
|
193
|
-
)
|
|
194
|
-
}
|
|
168
|
+
metric.incrementCallCount()
|
|
195
169
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
170
|
+
if (error) {
|
|
171
|
+
ctx.errors.push(error)
|
|
172
|
+
} else if (response && SUCCESS.has(response.status)) {
|
|
173
|
+
dumpErrors(ctx.errors, 'connect')
|
|
174
|
+
ctx.callback(null, CollectorResponse.success(response.payload))
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
if (!response) {
|
|
178
|
+
response = CollectorResponse.retry()
|
|
179
|
+
}
|
|
200
180
|
|
|
201
|
-
|
|
181
|
+
// Retry everything except for an explicit Disconnect response code.
|
|
182
|
+
if (response.status === 410 || response.agentRun === AGENT_RUN_BEHAVIOR.SHUTDOWN) {
|
|
183
|
+
logger.error('The New Relic collector rejected this agent.')
|
|
184
|
+
return ctx.callback(null, CollectorResponse.fatal(response.payload))
|
|
185
|
+
} else if (response.status === 401) {
|
|
186
|
+
logger.warn(
|
|
187
|
+
error,
|
|
188
|
+
'Your license key appears to be invalid. Reattempting connection to New' +
|
|
189
|
+
' Relic. If the problem persists, please contact support@newrelic.com.' +
|
|
190
|
+
' (status code %s)',
|
|
191
|
+
response.status
|
|
192
|
+
)
|
|
193
|
+
} else if (this._isProxyMisconfigured(error)) {
|
|
194
|
+
logger.warn(
|
|
202
195
|
error,
|
|
203
|
-
'
|
|
204
|
-
|
|
205
|
-
|
|
196
|
+
'Your proxy server appears to be configured to accept connections over http. ' +
|
|
197
|
+
'When setting `proxy_host` and `proxy_port` New Relic attempts to connect over ' +
|
|
198
|
+
'SSL(https). If your proxy is configured to accept connections over http, try ' +
|
|
199
|
+
'setting `proxy` to a fully qualified URL(e.g http://proxy-host:8080).'
|
|
206
200
|
)
|
|
201
|
+
}
|
|
207
202
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}, backoff.interval * TO_MILLIS)
|
|
212
|
-
timeout.unref()
|
|
203
|
+
const backoff = BACKOFFS[Math.min(ctx.attempts, ctx.max) - 1]
|
|
204
|
+
if (backoff.warn) {
|
|
205
|
+
logger.warn('No connection has been established to New Relic after %d attempts.', ctx.attempts)
|
|
213
206
|
}
|
|
214
207
|
|
|
215
|
-
|
|
208
|
+
logger.debug(
|
|
209
|
+
error,
|
|
210
|
+
'Failed to connect to New Relic after attempt %d, waiting %ds to retry.',
|
|
211
|
+
ctx.attempts,
|
|
212
|
+
backoff.interval
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
++ctx.attempts
|
|
216
|
+
const timeout = setTimeout(function again() {
|
|
217
|
+
api._login(api._retry.bind(api, ctx))
|
|
218
|
+
}, backoff.interval * TO_MILLIS)
|
|
219
|
+
timeout.unref()
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
CollectorAPI.prototype._login = function _login(callback) {
|
|
219
223
|
const methods = this._methods
|
|
220
224
|
const agent = this._agent
|
|
221
|
-
const self = this
|
|
222
225
|
|
|
223
226
|
const preconnectData = { high_security: agent.config.high_security }
|
|
224
227
|
if (agent.config.security_policies_token) {
|
|
@@ -227,56 +230,73 @@ CollectorAPI.prototype._login = function _login(callback) {
|
|
|
227
230
|
|
|
228
231
|
const payload = [preconnectData]
|
|
229
232
|
|
|
230
|
-
methods.preconnect.invoke(payload,
|
|
233
|
+
methods.preconnect.invoke(payload, this._onPreConnect.bind(this, callback))
|
|
234
|
+
}
|
|
231
235
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
/**
|
|
237
|
+
* @param {Function} callback function to run after processing response
|
|
238
|
+
* @param {Error} error response error
|
|
239
|
+
* @param {http.ServerResponse} response collector response from pre connect
|
|
240
|
+
* @returns {void}
|
|
241
|
+
*/
|
|
242
|
+
CollectorAPI.prototype._onPreConnect = function _onPreConnect(callback, error, response) {
|
|
243
|
+
const agent = this._agent
|
|
244
|
+
if (error || !SUCCESS.has(response.status)) {
|
|
245
|
+
callback(error, response)
|
|
246
|
+
return
|
|
247
|
+
}
|
|
240
248
|
|
|
241
|
-
|
|
242
|
-
|
|
249
|
+
const res = response.payload || Object.create(null)
|
|
250
|
+
this._handlePreConnectResponse(res)
|
|
251
|
+
|
|
252
|
+
const policies = res.security_policies || Object.create(null)
|
|
253
|
+
|
|
254
|
+
const laspResponse = agent.config.applyLasp(agent, policies)
|
|
255
|
+
if (laspResponse.shouldShutdownRun()) {
|
|
256
|
+
callback(null, laspResponse)
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
this._getFacts(laspResponse.payload, callback)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Checks the redirect_host and determines based on the URL if the collector
|
|
265
|
+
* needs to update the endpoint with new endpoint
|
|
266
|
+
*
|
|
267
|
+
* @param {http.ServerResponse} res collector response
|
|
268
|
+
*/
|
|
269
|
+
CollectorAPI.prototype._handlePreConnectResponse = function _handlePreConnectResponse(res) {
|
|
270
|
+
const agent = this._agent
|
|
271
|
+
|
|
272
|
+
if (!res.redirect_host) {
|
|
273
|
+
logger.error(
|
|
274
|
+
"Requesting this account's collector from %s failed; trying default.",
|
|
275
|
+
agent.config.host
|
|
276
|
+
)
|
|
277
|
+
} else {
|
|
278
|
+
const parts = res.redirect_host.split(':')
|
|
279
|
+
if (parts.length > 2) {
|
|
243
280
|
logger.error(
|
|
244
|
-
"Requesting
|
|
245
|
-
agent.config.host
|
|
281
|
+
"Requesting collector from %s returned bogus result '%s'; trying default.",
|
|
282
|
+
agent.config.host,
|
|
283
|
+
res.redirect_host
|
|
246
284
|
)
|
|
247
285
|
} else {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
res.redirect_host
|
|
254
|
-
)
|
|
255
|
-
} else {
|
|
256
|
-
logger.debug(
|
|
257
|
-
"Requesting this account's collector from %s returned %s; reconfiguring.",
|
|
258
|
-
agent.config.host,
|
|
259
|
-
res.redirect_host
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
const [host, port] = parts
|
|
263
|
-
const newEndpoint = {
|
|
264
|
-
host: host,
|
|
265
|
-
port: port || DEFAULT_PORT
|
|
266
|
-
}
|
|
286
|
+
logger.debug(
|
|
287
|
+
"Requesting this account's collector from %s returned %s; reconfiguring.",
|
|
288
|
+
agent.config.host,
|
|
289
|
+
res.redirect_host
|
|
290
|
+
)
|
|
267
291
|
|
|
268
|
-
|
|
292
|
+
const [host, port] = parts
|
|
293
|
+
const newEndpoint = {
|
|
294
|
+
host: host,
|
|
295
|
+
port: port || DEFAULT_PORT
|
|
269
296
|
}
|
|
270
|
-
}
|
|
271
297
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const laspResponse = agent.config.applyLasp(agent, policies)
|
|
275
|
-
if (laspResponse.shouldShutdownRun()) {
|
|
276
|
-
return callback(null, laspResponse)
|
|
298
|
+
this._updateEndpoints(newEndpoint)
|
|
277
299
|
}
|
|
278
|
-
|
|
279
|
-
self._getFacts(laspResponse.payload, callback)
|
|
280
300
|
}
|
|
281
301
|
}
|
|
282
302
|
|
|
@@ -298,50 +318,56 @@ CollectorAPI.prototype._getFacts = function _getFacts(lasp, callback) {
|
|
|
298
318
|
}
|
|
299
319
|
|
|
300
320
|
CollectorAPI.prototype._connect = function _connect(env, callback) {
|
|
301
|
-
const collector = this
|
|
302
321
|
const methods = this._methods
|
|
303
|
-
|
|
322
|
+
methods.connect.invoke(env, this._onConnect.bind(this, callback))
|
|
323
|
+
}
|
|
304
324
|
|
|
305
|
-
|
|
325
|
+
/**
|
|
326
|
+
*
|
|
327
|
+
* Handles the response to the connect call
|
|
328
|
+
*
|
|
329
|
+
* @param {Function} callback function to run after processing response
|
|
330
|
+
* @param {Error} error collector response error
|
|
331
|
+
* @param {http.ServerOptions} res collector response
|
|
332
|
+
*/
|
|
333
|
+
CollectorAPI.prototype._onConnect = function _onConnect(callback, error, res) {
|
|
334
|
+
const agent = this._agent
|
|
335
|
+
const methods = this._methods
|
|
306
336
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
function onConnect(error, res) {
|
|
312
|
-
if (error || !SUCCESS.has(res.status)) {
|
|
313
|
-
return callback(error, res)
|
|
314
|
-
}
|
|
337
|
+
if (error || !SUCCESS.has(res.status)) {
|
|
338
|
+
callback(error, res)
|
|
339
|
+
return
|
|
340
|
+
}
|
|
315
341
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
342
|
+
const config = res.payload
|
|
343
|
+
if (!config || !config.agent_run_id) {
|
|
344
|
+
callback(new Error('No agent run ID received from handshake.'), res)
|
|
345
|
+
return
|
|
346
|
+
}
|
|
320
347
|
|
|
321
|
-
|
|
348
|
+
agent.setState('connected')
|
|
322
349
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
350
|
+
logger.info(
|
|
351
|
+
'Connected to %s:%d with agent run ID %s.',
|
|
352
|
+
methods.connect.endpoint.host,
|
|
353
|
+
methods.connect.endpoint.port,
|
|
354
|
+
config.agent_run_id
|
|
355
|
+
)
|
|
329
356
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
357
|
+
// Log "Reporting to..." message from connect response.
|
|
358
|
+
if (config.messages) {
|
|
359
|
+
config.messages.forEach((element) => {
|
|
360
|
+
logger.info(element.message)
|
|
361
|
+
})
|
|
362
|
+
}
|
|
336
363
|
|
|
337
|
-
|
|
338
|
-
|
|
364
|
+
// Store request headers for future collector requests if they're present
|
|
365
|
+
this._reqHeadersMap = config.request_headers_map
|
|
339
366
|
|
|
340
|
-
|
|
341
|
-
|
|
367
|
+
// pass configuration data from the API so automatic reconnect works
|
|
368
|
+
agent.reconfigure(config)
|
|
342
369
|
|
|
343
|
-
|
|
344
|
-
}
|
|
370
|
+
callback(null, res)
|
|
345
371
|
}
|
|
346
372
|
|
|
347
373
|
/**
|
|
@@ -379,13 +405,15 @@ CollectorAPI.prototype.reportSettings = function reportSettings(callback) {
|
|
|
379
405
|
*
|
|
380
406
|
* @param {Array} errors The encoded errors list.
|
|
381
407
|
* @param {Function} callback The continuation / error handler.
|
|
408
|
+
* @returns {void}
|
|
382
409
|
*/
|
|
383
410
|
CollectorAPI.prototype.error_data = function errorData(errors, callback) {
|
|
384
411
|
if (!callback) {
|
|
385
412
|
this._throwCallbackError()
|
|
386
413
|
}
|
|
387
414
|
if (!errors) {
|
|
388
|
-
|
|
415
|
+
callback(new TypeError('must pass errors to send'))
|
|
416
|
+
return
|
|
389
417
|
}
|
|
390
418
|
|
|
391
419
|
this._sendData(this._methods.errors, errors, callback)
|
|
@@ -396,23 +424,27 @@ CollectorAPI.prototype.error_event_data = function errorEvents(events, callback)
|
|
|
396
424
|
this._throwCallbackError()
|
|
397
425
|
}
|
|
398
426
|
if (!events) {
|
|
399
|
-
|
|
427
|
+
callback(new TypeError('must pass errors to send'))
|
|
428
|
+
return
|
|
400
429
|
}
|
|
401
430
|
|
|
402
431
|
this._sendData(this._methods.errorEvents, events, callback)
|
|
403
432
|
}
|
|
404
433
|
|
|
405
434
|
CollectorAPI.prototype.analytic_event_data = transactionEvents
|
|
435
|
+
|
|
406
436
|
/**
|
|
407
|
-
* @param events
|
|
408
|
-
* @param callback
|
|
437
|
+
* @param {Array} events list of events to send to collector
|
|
438
|
+
* @param {Function} callback handler on response
|
|
439
|
+
* @returns {void}
|
|
409
440
|
*/
|
|
410
441
|
function transactionEvents(events, callback) {
|
|
411
442
|
if (!callback) {
|
|
412
443
|
this._throwCallbackError()
|
|
413
444
|
}
|
|
414
445
|
if (!events) {
|
|
415
|
-
|
|
446
|
+
callback(new TypeError('must pass events to send'))
|
|
447
|
+
return
|
|
416
448
|
}
|
|
417
449
|
|
|
418
450
|
this._sendData(this._methods.events, events, callback)
|
|
@@ -423,7 +455,8 @@ CollectorAPI.prototype.custom_event_data = function customEvents(events, callbac
|
|
|
423
455
|
this._throwCallbackError()
|
|
424
456
|
}
|
|
425
457
|
if (!events) {
|
|
426
|
-
|
|
458
|
+
callback(new TypeError('must pass events to send'))
|
|
459
|
+
return
|
|
427
460
|
}
|
|
428
461
|
|
|
429
462
|
this._sendData(this._methods.customEvents, events, callback)
|
|
@@ -450,7 +483,8 @@ CollectorAPI.prototype.metric_data = function metricData(metrics, callback) {
|
|
|
450
483
|
this._throwCallbackError()
|
|
451
484
|
}
|
|
452
485
|
if (!metrics) {
|
|
453
|
-
|
|
486
|
+
callback(new TypeError('must pass metrics to send'))
|
|
487
|
+
return
|
|
454
488
|
}
|
|
455
489
|
|
|
456
490
|
this._sendData(this._methods.metrics, metrics, callback)
|
|
@@ -473,7 +507,8 @@ CollectorAPI.prototype.sql_trace_data = function queryData(queries, callback) {
|
|
|
473
507
|
this._throwCallbackError()
|
|
474
508
|
}
|
|
475
509
|
if (!queries) {
|
|
476
|
-
|
|
510
|
+
callback(new TypeError('must pass queries to send'))
|
|
511
|
+
return
|
|
477
512
|
}
|
|
478
513
|
this._sendData(this._methods.queryData, queries, callback)
|
|
479
514
|
}
|
|
@@ -483,7 +518,8 @@ CollectorAPI.prototype.span_event_data = function spanEvents(events, callback) {
|
|
|
483
518
|
this._throwCallbackError()
|
|
484
519
|
}
|
|
485
520
|
if (!events) {
|
|
486
|
-
|
|
521
|
+
callback(new TypeError('must pass spans to send'))
|
|
522
|
+
return
|
|
487
523
|
}
|
|
488
524
|
this._sendData(this._methods.spanEvents, events, callback)
|
|
489
525
|
}
|
|
@@ -503,16 +539,18 @@ CollectorAPI.prototype.span_event_data = function spanEvents(events, callback) {
|
|
|
503
539
|
* @param {Function} callback The continuation / error handler.
|
|
504
540
|
*/
|
|
505
541
|
CollectorAPI.prototype.transaction_sample_data = transactionSampleData
|
|
542
|
+
|
|
506
543
|
/**
|
|
507
|
-
* @param traces
|
|
508
|
-
* @param callback
|
|
544
|
+
* @param {Array} traces list of traces to send
|
|
545
|
+
* @param {Function} callback handler on response
|
|
509
546
|
*/
|
|
510
547
|
function transactionSampleData(traces, callback) {
|
|
511
548
|
if (!callback) {
|
|
512
549
|
this._throwCallbackError()
|
|
513
550
|
}
|
|
514
551
|
if (!traces) {
|
|
515
|
-
|
|
552
|
+
callback(new TypeError('must pass traces to send'))
|
|
553
|
+
return
|
|
516
554
|
}
|
|
517
555
|
|
|
518
556
|
this._sendData(this._methods.traces, traces, callback)
|
|
@@ -527,16 +565,16 @@ function transactionSampleData(traces, callback) {
|
|
|
527
565
|
* 1. An array of logs.
|
|
528
566
|
* 2. A list of common attributes(optional).
|
|
529
567
|
*
|
|
530
|
-
* @param {Array}
|
|
531
|
-
* @param
|
|
532
|
-
* @param {Function} callback The continuation / error handler.
|
|
568
|
+
* @param {Array} logRecords The encoded log entries.
|
|
569
|
+
* @param {Function} callback The continuation / error handler.
|
|
533
570
|
*/
|
|
534
571
|
CollectorAPI.prototype.log_event_data = function logEventData(logRecords, callback) {
|
|
535
572
|
if (!callback) {
|
|
536
573
|
this._throwCallbackError()
|
|
537
574
|
}
|
|
538
575
|
if (!logRecords) {
|
|
539
|
-
|
|
576
|
+
callback(new TypeError('must pass logRecords to send'))
|
|
577
|
+
return
|
|
540
578
|
}
|
|
541
579
|
|
|
542
580
|
this._sendData(this._methods.logEvents, logRecords, callback)
|
|
@@ -546,8 +584,7 @@ CollectorAPI.prototype.log_event_data = function logEventData(logRecords, callba
|
|
|
546
584
|
* Sends no data aside from the message itself. Clears the run ID, which
|
|
547
585
|
* effectively disconnects the agent from the collector.
|
|
548
586
|
*
|
|
549
|
-
* @param Function callback Runs after the run ID has been cleared.
|
|
550
|
-
* @param callback
|
|
587
|
+
* @param {Function} callback Runs after the run ID has been cleared.
|
|
551
588
|
*/
|
|
552
589
|
CollectorAPI.prototype.shutdown = function shutdown(callback) {
|
|
553
590
|
if (!callback) {
|
|
@@ -560,8 +597,8 @@ CollectorAPI.prototype.shutdown = function shutdown(callback) {
|
|
|
560
597
|
this._methods.shutdown.invoke(null, this._reqHeadersMap, onShutdown)
|
|
561
598
|
|
|
562
599
|
/**
|
|
563
|
-
* @param error
|
|
564
|
-
* @param response
|
|
600
|
+
* @param {Error} error response error
|
|
601
|
+
* @param {http.ServerResponse} response response from collector
|
|
565
602
|
*/
|
|
566
603
|
function onShutdown(error, response) {
|
|
567
604
|
if (error) {
|
|
@@ -599,7 +636,8 @@ CollectorAPI.prototype._runLifecycle = function _runLifecycle(method, body, call
|
|
|
599
636
|
const api = this
|
|
600
637
|
method.invoke(body, this._reqHeadersMap, function standardHandler(error, response) {
|
|
601
638
|
if (error) {
|
|
602
|
-
|
|
639
|
+
callback(error)
|
|
640
|
+
return
|
|
603
641
|
}
|
|
604
642
|
|
|
605
643
|
return api._handleResponseCode(response, method.name, callback)
|
|
@@ -674,60 +712,55 @@ CollectorAPI.prototype.isConnected = function isConnected() {
|
|
|
674
712
|
return !!this._agent.config.run_id
|
|
675
713
|
}
|
|
676
714
|
|
|
715
|
+
CollectorAPI.prototype._handleResponseCode = _handleResponseCode
|
|
716
|
+
|
|
677
717
|
/**
|
|
678
718
|
* Returns appropriate CollectorResponse object according to response code.
|
|
679
719
|
*
|
|
680
|
-
* @param {
|
|
720
|
+
* @param {http.ServerResponse} response response from collector
|
|
681
721
|
* @param {number} response.status - Status code from collector response
|
|
682
722
|
* @param {object} response.payload - Parsed response body, if any
|
|
683
723
|
* @param {string} endpoint - Collector endpoint name
|
|
684
724
|
* @param {Function} cb - CollectorAPI method invocation callback
|
|
685
725
|
*/
|
|
686
|
-
CollectorAPI.prototype._handleResponseCode = _handleResponseCode
|
|
687
|
-
/**
|
|
688
|
-
* @param response
|
|
689
|
-
* @param endpoint
|
|
690
|
-
* @param cb
|
|
691
|
-
*/
|
|
692
726
|
function _handleResponseCode(response, endpoint, cb) {
|
|
693
727
|
const code = response.status
|
|
694
728
|
|
|
695
729
|
/* eslint-disable padded-blocks */
|
|
696
730
|
if (SUCCESS.has(code)) {
|
|
697
731
|
// The request was a success!
|
|
698
|
-
|
|
732
|
+
setImmediate(cb, null, CollectorResponse.success(response.payload))
|
|
699
733
|
} else if (RESTART.has(code)) {
|
|
700
734
|
// The agent needs to disconnect and restart.
|
|
701
735
|
logFailure(endpoint, code, 'Restarting')
|
|
702
|
-
|
|
736
|
+
setImmediate(cb, null, CollectorResponse.reconnect(0, null))
|
|
703
737
|
} else if (FAILURE_DISCARD_DATA.has(code)) {
|
|
704
738
|
// Something was wrong with our payload so we must delete our data.
|
|
705
739
|
logFailure(endpoint, code, 'Discarding harvest data')
|
|
706
|
-
|
|
740
|
+
setImmediate(cb, null, CollectorResponse.discard(null))
|
|
707
741
|
} else if (FAILURE_SAVE_DATA.has(code)) {
|
|
708
742
|
// Something was wrong with the request, but it wasn't our fault. We'll try again.
|
|
709
743
|
logFailure(endpoint, code, 'Retaining data for next harvest')
|
|
710
|
-
|
|
744
|
+
setImmediate(cb, null, CollectorResponse.error(response.payload))
|
|
711
745
|
} else if (code === 410) {
|
|
712
746
|
// New Relic doesn't like us and we shouldn't try to talk to them any more.
|
|
713
747
|
logFailure(endpoint, code, 'Disconnecting from New Relic')
|
|
714
748
|
|
|
715
|
-
|
|
749
|
+
this._agent.stop(function onShutdown() {
|
|
716
750
|
cb(null, CollectorResponse.fatal(response.payload))
|
|
717
751
|
})
|
|
752
|
+
} else {
|
|
753
|
+
// We're not sure what New Relic is trying to tell us. Let's get rid of our
|
|
754
|
+
// data just in case it is our fault.
|
|
755
|
+
logger.error('Agent endpoint %s returned unexpected status %s.', endpoint, code)
|
|
756
|
+
setImmediate(cb, null, CollectorResponse.discard(null))
|
|
718
757
|
}
|
|
719
|
-
/* eslint-enable padded-blocks */
|
|
720
|
-
|
|
721
|
-
// We're not sure what New Relic is trying to tell us. Let's get rid of our
|
|
722
|
-
// data just in case it is our fault.
|
|
723
|
-
logger.error('Agent endpoint %s returned unexpected status %s.', endpoint, code)
|
|
724
|
-
return setImmediate(cb, null, CollectorResponse.discard(null))
|
|
725
758
|
}
|
|
726
759
|
|
|
727
760
|
/**
|
|
728
|
-
* @param endpoint
|
|
729
|
-
* @param code
|
|
730
|
-
* @param action
|
|
761
|
+
* @param {string} endpoint called endpoint
|
|
762
|
+
* @param {string} code http status code
|
|
763
|
+
* @param {string} action describes collector action
|
|
731
764
|
*/
|
|
732
765
|
function logFailure(endpoint, code, action) {
|
|
733
766
|
logger.error('Agent endpoint %s returned %s status. %s.', endpoint, code, action)
|