Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6915 - Telemetry daily frequency #7095

Merged
merged 17 commits into from
Jun 1, 2021
10 changes: 6 additions & 4 deletions scripts/get_users_meta_docs.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env node

const inquirer = require('inquirer');
const PouchDB = require('pouchdb-core');
const fs = require('fs');
Expand Down Expand Up @@ -86,7 +88,7 @@ const actionQuestions = [{
}
docs.forEach(doc => console.log(JSON.stringify(doc, null, 2) + ','));
} else if (i === 0) {
console.log('\x1b[31m%s\x1b[0m', `There are no documents of type ${type}`);
console.error('\x1b[31m%s\x1b[0m', `There are no documents of type ${type}`);
break;
} else {
console.log('{}]');
Expand All @@ -100,7 +102,7 @@ const actionQuestions = [{
let docIndex = 0;

if (docs.length === 0) {
console.log('\x1b[31m%s\x1b[0m', `There are no documents of type ${type}`);
console.error('\x1b[31m%s\x1b[0m', `There are no documents of type ${type}`);
} else {
console.log(JSON.stringify(docs[docIndex], null, 2));

Expand All @@ -125,7 +127,7 @@ const actionQuestions = [{

console.log(JSON.stringify(docs[docIndex], null, 2));
if (printMessage) {
console.log('\x1b[31m%s\x1b[0m', `No next document. This is the last one.`);
console.error('\x1b[31m%s\x1b[0m', `No next document. This is the last one.`);
}
} else if (response.action === 'save_current') {
const filePath = path.join(path.resolve(__dirname), docs[docIndex]._id + '.json');
Expand Down Expand Up @@ -154,6 +156,6 @@ const actionQuestions = [{
}
}
} catch(err) {
console.log(err);
console.error(err);
}
})();
31 changes: 22 additions & 9 deletions webapp/src/ts/services/telemetry.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SessionService } from '@mm-services/session.service';
providedIn: 'root'
})
/**
* TelemetryService: Records, aggregates, and submits telemetry data
* TelemetryService: Records, aggregates, and submits telemetry data.
*/
export class TelemetryService {
// Intentionally scoped to the whole browser (for this domain). We can then tell if multiple users use the same device
Expand Down Expand Up @@ -54,7 +54,12 @@ export class TelemetryService {
return uniqueDeviceId;
}

private getLastAggregatedDate() {
/**
* Returns the time in milliseconds (since Unix epoch) when the first telemetry record was created
*
* This date is computed and stored when we call this method for the first time and after every aggregation.
*/
private getFirstAggregatedDate() {
dianabarsan marked this conversation as resolved.
Show resolved Hide resolved
let date = parseInt(window.localStorage.getItem(this.LAST_AGGREGATED_DATE_KEY));

if (!date) {
Expand All @@ -73,11 +78,17 @@ export class TelemetryService {
});
}

// moment when the aggregation starts (the beginning of the current day)
private aggregateStartsAt() {
return moment().startOf('day');
}

// if there is telemetry data from previous days, aggregation is performed and the data destroyed
private submitIfNeeded(db) {
const monthStart = moment().startOf('month');
const dbDate = moment(this.getLastAggregatedDate());
const startOf = this.aggregateStartsAt();
const dbDate = moment(this.getFirstAggregatedDate());

if (dbDate.isBefore(monthStart)) {
if (dbDate.isBefore(startOf)) {
return this
.aggregate(db)
.then(() => this.reset(db));
Expand All @@ -97,6 +108,7 @@ export class TelemetryService {
'telemetry',
metadata.year,
metadata.month,
metadata.day,
metadata.user,
metadata.deviceId,
].join('-');
Expand All @@ -109,7 +121,7 @@ export class TelemetryService {
this.dbService.get().query('medic-client/doc_by_type', { key: ['form'], include_docs: true })
])
.then(([ddoc, formResults]) => {
const date = moment(this.getLastAggregatedDate());
const date = moment(this.getFirstAggregatedDate());
mrsarm marked this conversation as resolved.
Show resolved Hide resolved
const version = (ddoc.deploy_info && ddoc.deploy_info.version) || 'unknown';
const forms = formResults.rows.reduce((keyToVersion, row) => {
keyToVersion[row.doc.internalId] = row.doc._rev;
Expand All @@ -120,6 +132,7 @@ export class TelemetryService {
return {
year: date.year(),
month: date.month() + 1,
day: date.date(),
user: this.sessionService.userCtx().name,
deviceId: this.getUniqueDeviceId(),
versions: {
Expand Down Expand Up @@ -225,7 +238,7 @@ export class TelemetryService {
* metric_b: { sum: -16, min: -4, max: -4, count: 4, sumsqr: 64 }
* }
*
* See: https://wiki.apache.org/couchdb/Built-In_Reduce_Functions#A_stats
* See: https://docs.couchdb.org/en/stable/ddocs/ddocs.html#_stats
*
* This single month aggregate document is of type 'telemetry', and is
* stored in the user's meta DB (which replicates up to the main server)
Expand Down Expand Up @@ -255,14 +268,14 @@ export class TelemetryService {
let db;
this.queue = this.queue
.then(() => db = this.getDb())
.then(() => this.storeIt(db, key, value))
.then(() => this.submitIfNeeded(db))
.then(() => db = this.getDb()) // db is fetched again in case submitIfNeeded dropped the old reference
.then(() => this.storeIt(db, key, value))
.catch(err => console.error('Error in telemetry service', err))
.finally(() => {
if (!db || db._destroyed || db._closed) {
return;
}

try {
db.close();
} catch (err) {
Expand Down
Loading