From 4eb7a2cd8e8b081ec8eceedcf51cac579ae60761 Mon Sep 17 00:00:00 2001 From: maxbittker Date: Mon, 14 Nov 2016 16:07:39 -0800 Subject: [PATCH] feat: maxEventsPerPage config option --- docs/config.rst | 6 +++++- src/raven.js | 17 ++++++++++++++++ test/raven.test.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/config.rst b/docs/config.rst index 65fed4b1e3a7..bd66d4cabbb0 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -299,7 +299,6 @@ Those configuration options are documented below: If set to `true`, Raven.js outputs some light debugging information onto the console. - .. describe:: instrument Enables/disables instrumentation of globals. Possible values are: @@ -314,6 +313,11 @@ Those configuration options are documented below: 'tryCatch': true, // Instruments timers and event targets } +.. describe:: maxEventsPerPage + + By default, Raven captures as many events as possible. If you want to reduce this number, you can change + it by setting `maxEventsPerPage`. The counter will automatically restart on every page change. + Putting it all together ----------------------- diff --git a/src/raven.js b/src/raven.js index 4d35c28ca4d2..27cc67760576 100644 --- a/src/raven.js +++ b/src/raven.js @@ -81,6 +81,7 @@ function Raven() { this._keypressTimeout; this._location = _window.location; this._lastHref = this._location && this._location.href; + this._sentEvents = 0; this._resetBackoff(); // eslint-disable-next-line guard-for-in @@ -875,6 +876,9 @@ Raven.prototype = { var parsedTo = parseUrl(to); var parsedFrom = parseUrl(from); + // refresh max events count + this._sentEvents = 0; + // because onpopstate only tells you the "new" (to) value of location.href, and // not the previous (from) value, we need to track the value of the current URL // state ourselves @@ -1255,6 +1259,9 @@ Raven.prototype = { return function(/* state, title, url */) { var url = arguments.length > 2 ? arguments[2] : undefined; + // refresh max events count + self._sentEvents = 0; + // url argument is optional if (url) { // coerce to string (this is what pushState does) @@ -1699,6 +1706,14 @@ Raven.prototype = { return; } + // Check if the request should be filtered due to max events per page + if ( + globalOptions.maxEventsPerPage && + this._sentEvents >= globalOptions.maxEventsPerPage + ) { + return; + } + // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests), // so drop requests until "cool-off" period has elapsed. if (this._shouldBackoff()) { @@ -1706,6 +1721,8 @@ Raven.prototype = { return; } + this._sentEvents++; // failed events count towards maxEvents + if (typeof globalOptions.sampleRate === 'number') { if (Math.random() < globalOptions.sampleRate) { this._sendProcessedPayload(data); diff --git a/test/raven.test.js b/test/raven.test.js index 46214a01c717..b145eb1ae38b 100644 --- a/test/raven.test.js +++ b/test/raven.test.js @@ -2174,6 +2174,57 @@ describe('Raven (public API)', function() { }); }); }); + + describe('maxEventsPerPage', function(){ + it('allows many events when maxEventsPerPage is undefined', function () { + var stub = this.sinon.stub(Raven,'_sendProcessedPayload') + this.sinon.spy(stub) + + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + + assert.equal(Raven._sendProcessedPayload.callCount, 5); + }); + + it('should only allow up to maxEventsPerPage requests', function () { + var stub = this.sinon.stub(Raven,'_sendProcessedPayload') + this.sinon.spy(stub) + + Raven._globalOptions.maxEventsPerPage = 3; + + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + + assert.equal(Raven._sendProcessedPayload.callCount, 3); + }); + + it('should reset maxErrors on SPA page change', function () { + var stub = this.sinon.stub(Raven,'_sendProcessedPayload') + this.sinon.spy(stub) + + Raven._globalOptions.maxEventsPerPage = 3; + + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + + assert.equal(Raven._sendProcessedPayload.callCount, 3); + + Raven._captureUrlChange('/foo', '/bar'); + + Raven.captureException(new Error('foo')) + Raven.captureException(new Error('foo')) + + assert.equal(Raven._sendProcessedPayload.callCount, 5); + }); + }); }); describe('.wrap', function() {