Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2018-06-29 09:44:24 +00:00
commit 9b9f744a44
4 changed files with 27 additions and 50 deletions

View file

@ -199,9 +199,9 @@ class Analytics {
this._paq.push(['trackPageView']); this._paq.push(['trackPageView']);
} }
trackEvent(category, action, name) { trackEvent(category, action, name, value) {
if (this.disabled) return; if (this.disabled) return;
this._paq.push(['trackEvent', category, action, name]); this._paq.push(['trackEvent', category, action, name, value]);
} }
logout() { logout() {

View file

@ -40,16 +40,15 @@ export default class DecryptionFailureTracker {
checkInterval = null; checkInterval = null;
trackInterval = null; trackInterval = null;
// Spread the load on `Analytics` by sending at most 1 event per // Spread the load on `Analytics` by tracking at a low frequency, `TRACK_INTERVAL_MS`.
// `TRACK_INTERVAL_MS`. static TRACK_INTERVAL_MS = 60000;
static TRACK_INTERVAL_MS = 1000;
// Call `checkFailures` every `CHECK_INTERVAL_MS`. // Call `checkFailures` every `CHECK_INTERVAL_MS`.
static CHECK_INTERVAL_MS = 5000; static CHECK_INTERVAL_MS = 5000;
// Give events a chance to be decrypted by waiting `GRACE_PERIOD_MS` before moving // Give events a chance to be decrypted by waiting `GRACE_PERIOD_MS` before moving
// the failure to `failuresToTrack`. // the failure to `failuresToTrack`.
static GRACE_PERIOD_MS = 5000; static GRACE_PERIOD_MS = 60000;
constructor(fn) { constructor(fn) {
if (!fn || typeof fn !== 'function') { if (!fn || typeof fn !== 'function') {
@ -158,12 +157,16 @@ export default class DecryptionFailureTracker {
} }
/** /**
* If there is a failure that should be tracked, call the given trackDecryptionFailure * If there are failures that should be tracked, call the given trackDecryptionFailure
* function with the first failure in the FIFO of failures that should be tracked. * function with the number of failures that should be tracked.
*/ */
trackFailure() { trackFailure() {
if (this.failuresToTrack.length > 0) { if (this.failuresToTrack.length > 0) {
this.trackDecryptionFailure(this.failuresToTrack.shift()); // Remove all failures, and expose the number of failures for now.
//
// TODO: Track a histogram of error types to cardinailty to allow for
// aggregation by error type.
this.trackDecryptionFailure(this.failuresToTrack.splice(0).length);
} }
} }
} }

View file

@ -1304,9 +1304,9 @@ export default React.createClass({
} }
}); });
const dft = new DecryptionFailureTracker((failure) => { const dft = new DecryptionFailureTracker((total) => {
// TODO: Pass reason for failure as third argument to trackEvent // TODO: Pass reason for failure as third argument to trackEvent
Analytics.trackEvent('E2E', 'Decryption failure'); Analytics.trackEvent('E2E', 'Decryption failure', null, total);
}); });
// Shelved for later date when we have time to think about persisting history of // Shelved for later date when we have time to think about persisting history of

View file

@ -33,10 +33,9 @@ function createFailedDecryptionEvent() {
describe('DecryptionFailureTracker', function() { describe('DecryptionFailureTracker', function() {
it('tracks a failed decryption', function(done) { it('tracks a failed decryption', function(done) {
const failedDecryptionEvent = createFailedDecryptionEvent(); const failedDecryptionEvent = createFailedDecryptionEvent();
let trackedFailure = null;
const tracker = new DecryptionFailureTracker((failure) => { let count = 0;
trackedFailure = failure; const tracker = new DecryptionFailureTracker((total) => count += total);
});
tracker.eventDecrypted(failedDecryptionEvent); tracker.eventDecrypted(failedDecryptionEvent);
@ -46,14 +45,14 @@ describe('DecryptionFailureTracker', function() {
// Immediately track the newest failure, if there is one // Immediately track the newest failure, if there is one
tracker.trackFailure(); tracker.trackFailure();
expect(trackedFailure).toNotBe(null, 'should track a failure for an event that failed decryption'); expect(count).toNotBe(0, 'should track a failure for an event that failed decryption');
done(); done();
}); });
it('does not track a failed decryption where the event is subsequently successfully decrypted', (done) => { it('does not track a failed decryption where the event is subsequently successfully decrypted', (done) => {
const decryptedEvent = createFailedDecryptionEvent(); const decryptedEvent = createFailedDecryptionEvent();
const tracker = new DecryptionFailureTracker((failure) => { const tracker = new DecryptionFailureTracker((total) => {
expect(true).toBe(false, 'should not track an event that has since been decrypted correctly'); expect(true).toBe(false, 'should not track an event that has since been decrypted correctly');
}); });
@ -76,7 +75,7 @@ describe('DecryptionFailureTracker', function() {
const decryptedEvent2 = createFailedDecryptionEvent(); const decryptedEvent2 = createFailedDecryptionEvent();
let count = 0; let count = 0;
const tracker = new DecryptionFailureTracker((failure) => count++); const tracker = new DecryptionFailureTracker((total) => count += total);
// Arbitrary number of failed decryptions for both events // Arbitrary number of failed decryptions for both events
tracker.eventDecrypted(decryptedEvent); tracker.eventDecrypted(decryptedEvent);
@ -102,36 +101,11 @@ describe('DecryptionFailureTracker', function() {
done(); done();
}); });
it('track failures in the order they occured', (done) => {
const decryptedEvent = createFailedDecryptionEvent();
const decryptedEvent2 = createFailedDecryptionEvent();
const failures = [];
const tracker = new DecryptionFailureTracker((failure) => failures.push(failure));
// Indicate decryption
tracker.eventDecrypted(decryptedEvent);
tracker.eventDecrypted(decryptedEvent2);
// Pretend "now" is Infinity
tracker.checkFailures(Infinity);
// Simulated polling of `trackFailure`, an arbitrary number ( > 2 ) times
tracker.trackFailure();
tracker.trackFailure();
expect(failures.length).toBe(2, 'expected 2 failures to be tracked, got ' + failures.length);
expect(failures[0].failedEventId).toBe(decryptedEvent.getId(), 'the first failure should be tracked first');
expect(failures[1].failedEventId).toBe(decryptedEvent2.getId(), 'the second failure should be tracked second');
done();
});
it('should not track a failure for an event that was tracked previously', (done) => { it('should not track a failure for an event that was tracked previously', (done) => {
const decryptedEvent = createFailedDecryptionEvent(); const decryptedEvent = createFailedDecryptionEvent();
const failures = []; let count = 0;
const tracker = new DecryptionFailureTracker((failure) => failures.push(failure)); const tracker = new DecryptionFailureTracker((total) => count += total);
// Indicate decryption // Indicate decryption
tracker.eventDecrypted(decryptedEvent); tracker.eventDecrypted(decryptedEvent);
@ -146,7 +120,7 @@ describe('DecryptionFailureTracker', function() {
tracker.trackFailure(); tracker.trackFailure();
expect(failures.length).toBe(1, 'should only track a single failure per event'); expect(count).toBe(1, 'should only track a single failure per event');
done(); done();
}); });
@ -157,8 +131,8 @@ describe('DecryptionFailureTracker', function() {
const decryptedEvent = createFailedDecryptionEvent(); const decryptedEvent = createFailedDecryptionEvent();
const failures = []; let count = 0;
const tracker = new DecryptionFailureTracker((failure) => failures.push(failure)); const tracker = new DecryptionFailureTracker((total) => count += total);
// Indicate decryption // Indicate decryption
tracker.eventDecrypted(decryptedEvent); tracker.eventDecrypted(decryptedEvent);
@ -170,7 +144,7 @@ describe('DecryptionFailureTracker', function() {
tracker.trackFailure(); tracker.trackFailure();
// Simulate the browser refreshing by destroying tracker and creating a new tracker // Simulate the browser refreshing by destroying tracker and creating a new tracker
const secondTracker = new DecryptionFailureTracker((failure) => failures.push(failure)); const secondTracker = new DecryptionFailureTracker((total) => count += total);
//secondTracker.loadTrackedEventHashMap(); //secondTracker.loadTrackedEventHashMap();
@ -178,7 +152,7 @@ describe('DecryptionFailureTracker', function() {
secondTracker.checkFailures(Infinity); secondTracker.checkFailures(Infinity);
secondTracker.trackFailure(); secondTracker.trackFailure();
expect(failures.length).toBe(1, 'should track a single failure per event per session, got ' + failures.length); expect(count).toBe(1, count + ' failures tracked, should only track a single failure per event');
done(); done();
}); });