2022-04-19 05:59:36 +00:00
|
|
|
import { Fyo } from 'fyo';
|
2022-03-09 10:54:42 +00:00
|
|
|
import { cloneDeep } from 'lodash';
|
2022-05-23 08:09:07 +00:00
|
|
|
import { DateTime } from 'luxon';
|
2022-03-18 10:09:17 +00:00
|
|
|
import {
|
|
|
|
getCountry,
|
|
|
|
getDeviceId,
|
|
|
|
getInstanceId,
|
|
|
|
getLanguage,
|
2022-05-23 08:09:07 +00:00
|
|
|
getVersion,
|
2022-03-18 10:09:17 +00:00
|
|
|
} from './helpers';
|
2022-05-23 08:09:07 +00:00
|
|
|
import { Noun, Platform, Telemetry, Verb } from './types';
|
2022-03-18 10:09:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* # Telemetry
|
2022-05-23 08:09:07 +00:00
|
|
|
* Used to check if people are using Books or not. All logging
|
|
|
|
* happens using navigator.sendBeacon
|
2022-03-18 10:09:17 +00:00
|
|
|
*
|
|
|
|
* ## `start`
|
2022-05-23 08:09:07 +00:00
|
|
|
* Used to initialize state. It should be called before any logging and after an
|
|
|
|
* instance has loaded.
|
2022-03-18 10:09:17 +00:00
|
|
|
* It is called on three events:
|
2022-05-23 08:09:07 +00:00
|
|
|
* 1. When Desk is opened, i.e. when the usage starts, this also sends a started
|
|
|
|
* log.
|
2022-03-18 10:09:17 +00:00
|
|
|
* 2. On visibility change if not started, eg: when user minimizeds Books and
|
|
|
|
* then comes back later.
|
2022-05-23 08:09:07 +00:00
|
|
|
* 3. When `log` is called, but telemetry wasn't initialized.
|
2022-03-18 10:09:17 +00:00
|
|
|
*
|
|
|
|
* ## `log`
|
2022-05-23 08:09:07 +00:00
|
|
|
* Used to log activity.
|
2022-03-18 10:09:17 +00:00
|
|
|
*
|
|
|
|
* ## `stop`
|
|
|
|
* This is to be called when a session is being stopped. It's called on two events
|
|
|
|
* 1. When the db is being changed.
|
|
|
|
* 2. When the visiblity has changed which happens when either the app is being shut or
|
|
|
|
* the app is hidden.
|
|
|
|
*/
|
2022-03-09 10:13:17 +00:00
|
|
|
|
2022-04-18 11:29:20 +00:00
|
|
|
export class TelemetryManager {
|
2022-03-14 12:56:26 +00:00
|
|
|
#url: string = '';
|
|
|
|
#token: string = '';
|
2022-03-09 10:13:17 +00:00
|
|
|
#started = false;
|
|
|
|
#telemetryObject: Partial<Telemetry> = {};
|
2022-04-19 05:59:36 +00:00
|
|
|
fyo: Fyo;
|
2022-04-18 11:29:20 +00:00
|
|
|
|
2022-04-19 05:59:36 +00:00
|
|
|
constructor(fyo: Fyo) {
|
|
|
|
this.fyo = fyo;
|
2022-04-18 11:29:20 +00:00
|
|
|
}
|
2022-03-09 10:13:17 +00:00
|
|
|
|
2022-03-18 10:09:17 +00:00
|
|
|
set platform(value: Platform) {
|
|
|
|
this.#telemetryObject.platform ||= value;
|
|
|
|
}
|
|
|
|
|
|
|
|
get hasCreds() {
|
|
|
|
return !!this.#url && !!this.#token;
|
|
|
|
}
|
|
|
|
|
|
|
|
get started() {
|
|
|
|
return this.#started;
|
|
|
|
}
|
|
|
|
|
|
|
|
get telemetryObject(): Readonly<Partial<Telemetry>> {
|
|
|
|
return cloneDeep(this.#telemetryObject);
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
async start(openCount?: number) {
|
2022-05-28 11:14:38 +00:00
|
|
|
await this.#init();
|
2022-03-09 10:13:17 +00:00
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
this.#started = true;
|
|
|
|
await this.#setCreds();
|
2022-03-14 12:56:26 +00:00
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
if (typeof openCount === 'number') {
|
|
|
|
this.#telemetryObject.openCount = openCount;
|
2022-05-28 11:14:38 +00:00
|
|
|
this.log(Verb.Opened, 'instance');
|
2022-05-23 08:09:07 +00:00
|
|
|
} else {
|
2022-05-28 11:14:38 +00:00
|
|
|
this.log(Verb.Resumed, 'instance');
|
2022-03-09 10:13:17 +00:00
|
|
|
}
|
2022-05-23 08:09:07 +00:00
|
|
|
}
|
2022-03-09 10:13:17 +00:00
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
stop() {
|
|
|
|
if (!this.started) {
|
2022-03-10 07:51:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-28 11:14:38 +00:00
|
|
|
this.log(Verb.Closed, 'instance');
|
2022-05-23 08:09:07 +00:00
|
|
|
this.#started = false;
|
|
|
|
this.#clear();
|
2022-03-09 10:13:17 +00:00
|
|
|
}
|
2022-03-09 10:54:42 +00:00
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
log(verb: Verb, noun: Noun, more?: Record<string, unknown>) {
|
2022-05-23 09:28:33 +00:00
|
|
|
if (!this.#started && this.fyo.db.isConnected) {
|
2022-05-23 08:09:07 +00:00
|
|
|
this.start().then(() => this.#sendBeacon(verb, noun, more));
|
|
|
|
return;
|
2022-03-09 11:20:48 +00:00
|
|
|
}
|
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
this.#sendBeacon(verb, noun, more);
|
2022-03-09 11:20:48 +00:00
|
|
|
}
|
|
|
|
|
2022-05-28 11:14:38 +00:00
|
|
|
async logOpened() {
|
|
|
|
await this.#init();
|
|
|
|
await this.#setCreds();
|
|
|
|
this.#sendBeacon(Verb.Opened, 'app');
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
#sendBeacon(verb: Verb, noun: Noun, more?: Record<string, unknown>) {
|
2022-05-28 11:14:38 +00:00
|
|
|
if (!this.hasCreds || this.fyo.store.skipTelemetryLogging) {
|
2022-05-23 08:09:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-03-10 09:05:47 +00:00
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
const telemetryData: Telemetry = this.#getTelemtryData(verb, noun, more);
|
2022-03-18 10:09:17 +00:00
|
|
|
const data = JSON.stringify({
|
|
|
|
token: this.#token,
|
2022-05-23 08:09:07 +00:00
|
|
|
telemetryData,
|
2022-03-18 10:09:17 +00:00
|
|
|
});
|
2022-03-10 12:06:28 +00:00
|
|
|
|
2022-03-15 10:58:43 +00:00
|
|
|
navigator.sendBeacon(this.#url, data);
|
|
|
|
}
|
|
|
|
|
2022-03-18 10:09:17 +00:00
|
|
|
async #setCreds() {
|
|
|
|
if (this.hasCreds) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-27 09:39:24 +00:00
|
|
|
const { telemetryUrl, tokenString } = await this.fyo.auth.getCreds();
|
|
|
|
this.#url = telemetryUrl;
|
|
|
|
this.#token = tokenString;
|
2022-03-18 10:09:17 +00:00
|
|
|
}
|
|
|
|
|
2022-05-28 11:14:38 +00:00
|
|
|
async #init() {
|
|
|
|
this.#telemetryObject.language ??= getLanguage(this.fyo);
|
|
|
|
this.#telemetryObject.deviceId ||= getDeviceId(this.fyo);
|
|
|
|
this.#telemetryObject.version = this.fyo.store.appVersion;
|
|
|
|
|
|
|
|
if (this.fyo.db.dbPath) {
|
|
|
|
this.#telemetryObject.country ||= getCountry(this.fyo);
|
|
|
|
this.#telemetryObject.instanceId ||= await getInstanceId(this.fyo);
|
|
|
|
this.#telemetryObject.version = await getVersion(this.fyo);
|
|
|
|
} else {
|
|
|
|
this.#telemetryObject.country ||= '';
|
|
|
|
this.#telemetryObject.instanceId ||= '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:09:07 +00:00
|
|
|
#getTelemtryData(
|
|
|
|
verb: Verb,
|
|
|
|
noun: Noun,
|
|
|
|
more?: Record<string, unknown>
|
|
|
|
): Telemetry {
|
|
|
|
return {
|
|
|
|
country: this.#telemetryObject.country!,
|
|
|
|
language: this.#telemetryObject.language!,
|
2022-05-23 09:28:33 +00:00
|
|
|
deviceId: this.#telemetryObject.deviceId!,
|
|
|
|
instanceId: this.#telemetryObject.instanceId!,
|
2022-05-23 08:09:07 +00:00
|
|
|
version: this.#telemetryObject.version!,
|
|
|
|
openCount: this.#telemetryObject.openCount!,
|
|
|
|
timestamp: DateTime.now().toMillis().toString(),
|
|
|
|
verb,
|
|
|
|
noun,
|
|
|
|
more,
|
|
|
|
};
|
2022-03-18 10:09:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#clear() {
|
|
|
|
delete this.#telemetryObject.country;
|
2022-05-23 08:09:07 +00:00
|
|
|
delete this.#telemetryObject.language;
|
2022-05-23 09:28:33 +00:00
|
|
|
delete this.#telemetryObject.deviceId;
|
|
|
|
delete this.#telemetryObject.instanceId;
|
2022-05-23 08:09:07 +00:00
|
|
|
delete this.#telemetryObject.version;
|
|
|
|
delete this.#telemetryObject.openCount;
|
2022-03-09 10:54:42 +00:00
|
|
|
}
|
2022-03-09 10:13:17 +00:00
|
|
|
}
|