mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-20 06:29:53 +01:00
pad_utils: Rate limit identical warnDeprecated
calls
This commit is contained in:
parent
908175d1ca
commit
cfb68e5725
2 changed files with 32 additions and 0 deletions
|
@ -93,6 +93,9 @@ const padutils = {
|
||||||
* Prints a warning message followed by a stack trace (to make it easier to figure out what code
|
* Prints a warning message followed by a stack trace (to make it easier to figure out what code
|
||||||
* is using the deprecated function).
|
* is using the deprecated function).
|
||||||
*
|
*
|
||||||
|
* Identical deprecation warnings (as determined by the stack trace, if available) are rate
|
||||||
|
* limited to avoid log spam.
|
||||||
|
*
|
||||||
* Most browsers include UI widget to examine the stack at the time of the warning, but this
|
* Most browsers include UI widget to examine the stack at the time of the warning, but this
|
||||||
* includes the stack in the log message for a couple of reasons:
|
* includes the stack in the log message for a couple of reasons:
|
||||||
* - This makes it possible to see the stack if the code runs in Node.js.
|
* - This makes it possible to see the stack if the code runs in Node.js.
|
||||||
|
@ -106,6 +109,18 @@ const padutils = {
|
||||||
const err = new Error();
|
const err = new Error();
|
||||||
if (Error.captureStackTrace) Error.captureStackTrace(err, padutils.warnDeprecated);
|
if (Error.captureStackTrace) Error.captureStackTrace(err, padutils.warnDeprecated);
|
||||||
err.name = '';
|
err.name = '';
|
||||||
|
// Rate limit identical deprecation warnings (as determined by the stack) to avoid log spam.
|
||||||
|
if (typeof err.stack === 'string') {
|
||||||
|
if (padutils.warnDeprecated._rl == null) {
|
||||||
|
padutils.warnDeprecated._rl =
|
||||||
|
{prevs: new Map(), now: () => Date.now(), period: 10 * 60 * 1000};
|
||||||
|
}
|
||||||
|
const rl = padutils.warnDeprecated._rl;
|
||||||
|
const now = rl.now();
|
||||||
|
const prev = rl.prevs.get(err.stack);
|
||||||
|
if (prev != null && now - prev < rl.period) return;
|
||||||
|
rl.prevs.set(err.stack, now);
|
||||||
|
}
|
||||||
if (err.stack) args.push(err.stack);
|
if (err.stack) args.push(err.stack);
|
||||||
(padutils.warnDeprecated.logger || console).warn(...args);
|
(padutils.warnDeprecated.logger || console).warn(...args);
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe(__filename, function () {
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
warnDeprecated.logger = backups.logger;
|
warnDeprecated.logger = backups.logger;
|
||||||
|
delete warnDeprecated._rl; // Reset internal rate limiter state.
|
||||||
});
|
});
|
||||||
|
|
||||||
it('includes the stack', async function () {
|
it('includes the stack', async function () {
|
||||||
|
@ -22,5 +23,21 @@ describe(__filename, function () {
|
||||||
warnDeprecated();
|
warnDeprecated();
|
||||||
assert(got.includes(__filename));
|
assert(got.includes(__filename));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('rate limited', async function () {
|
||||||
|
let got = 0;
|
||||||
|
warnDeprecated.logger = {warn: () => ++got};
|
||||||
|
warnDeprecated(); // Initialize internal rate limiter state.
|
||||||
|
const {period} = warnDeprecated._rl;
|
||||||
|
got = 0;
|
||||||
|
const testCases = [[0, 1], [0, 1], [period - 1, 1], [period, 2]];
|
||||||
|
for (const [now, want] of testCases) { // In a loop so that the stack trace is the same.
|
||||||
|
warnDeprecated._rl.now = () => now;
|
||||||
|
warnDeprecated();
|
||||||
|
assert.equal(got, want);
|
||||||
|
}
|
||||||
|
warnDeprecated(); // Should have a different stack trace.
|
||||||
|
assert.equal(got, testCases[testCases.length - 1][1] + 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue