Skip to content

Commit 365ded4

Browse files
authoredFeb 13, 2024
fix: Resolve logs getting blocked when an excessive payload is encoun… (#2013)
1 parent 4daedc0 commit 365ded4

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed
 

‎lib/collector/api.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,31 @@ CollectorAPI.prototype._sendData = function _sendData(method, data, callback) {
480480
this._runLifecycle(method, data, (error, response) => {
481481
// Any runtime errors should preserve the agent run.
482482
if (error) {
483-
// TODO: log error
484-
// TODO: differentiate between network (retain) and non-network (drop).
483+
let retainData = true
484+
if (error.code && error.code === 'NR_REMOTE_METHOD_MAX_PAYLOAD_SIZE_EXCEEDED') {
485+
// We are going to drop whatever was in `data`.
486+
// The collector + aggregator system collects events into batches until
487+
// a harvest interval is reached. At that time, all collected events
488+
// are popped off the queue into an array. That array is then serialized
489+
// (and possibly compressed) before being sent. If that serialized data
490+
// exceeds our allowed limit, there isn't any way to reduce items to
491+
// send data, and requeue events, until the data meets the allowed
492+
// limit. So we are going to drop it all here, and _not_ pass an error
493+
// back to the sending routines.
494+
//
495+
// Ideally, we'd have an algorithm that:
496+
// 1. Calculates if the collected events to be sent will exceed the
497+
// allowed size
498+
// 2. If so, pop events off the to-send array and re-queues them until
499+
// the allowed size is met.
500+
// 3. If the paired down to-send array reaches one element that will
501+
// still fail, drop that item from the queue.
502+
// 4. Let the next cycle do the same thing.
503+
retainData = false
504+
return callback(null, { retainData })
505+
}
485506

486-
callback(error, { retainData: true })
507+
callback(error, { retainData })
487508

488509
return
489510
}

‎lib/collector/remote-method.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,9 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
245245
this.name,
246246
maxPayloadSize
247247
)
248-
throw new Error('Maximum payload size exceeded')
248+
const error = new Error('Maximum payload size exceeded')
249+
error.code = 'NR_REMOTE_METHOD_MAX_PAYLOAD_SIZE_EXCEEDED'
250+
throw error
249251
}
250252

251253
// If trace level is not explicitly enabled check to see if the audit log is

‎lib/config/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const configDefinition = definition()
2929
* CONSTANTS -- we gotta lotta 'em
3030
*/
3131
const AZURE_APP_NAME = 'APP_POOL_ID'
32-
const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1000000
32+
const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1_000_000
3333
const BASE_CONFIG_PATH = require.resolve('../../newrelic')
3434
const HAS_ARBITRARY_KEYS = new Set(['ignore_messages', 'expected_messages', 'labels'])
3535

‎test/unit/collector/api.test.js

+39
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
const tap = require('tap')
99

1010
const nock = require('nock')
11+
const crypto = require('crypto')
1112
const helper = require('../../lib/agent_helper')
1213
const CollectorApi = require('../../../lib/collector/api')
1314

@@ -74,6 +75,44 @@ tap.test('reportSettings', (t) => {
7475
t.end()
7576
})
7677
})
78+
79+
t.test('handles excessive payload sizes without blocking subsequent sends', (t) => {
80+
const tstamp = 1_707_756_300_000 // 2024-02-12T11:45:00.000-05:00
81+
function log(data) {
82+
return JSON.stringify({
83+
level: 30,
84+
time: tstamp,
85+
pid: 17035,
86+
hostname: 'test-host',
87+
msg: data
88+
})
89+
}
90+
91+
const kb512 = log(crypto.randomBytes(524_288).toString('base64'))
92+
const mb1 = log(crypto.randomBytes(1_048_576).toString('base64'))
93+
const toFind = log('find me')
94+
95+
let sends = 0
96+
const ncontext = nock(URL)
97+
.post(helper.generateCollectorPath('log_event_data', RUN_ID))
98+
.times(2)
99+
.reply(200)
100+
101+
agent.logs.on('finished log_event_data data send.', () => {
102+
sends += 1
103+
if (sends === 3) {
104+
t.equal(ncontext.isDone(), true)
105+
t.end()
106+
}
107+
})
108+
109+
agent.logs.add(kb512)
110+
agent.logs.send()
111+
agent.logs.add(mb1)
112+
agent.logs.send()
113+
agent.logs.add(toFind)
114+
agent.logs.send()
115+
})
77116
})
78117

79118
/**

0 commit comments

Comments
 (0)
Please sign in to comment.