import config, { ConfigKeys, TelemetrySetting } from '@/config'; import frappe from 'frappe'; import { cloneDeep } from 'lodash'; import { getCounts, getDeviceId, getInstanceId, getLocale } from './helpers'; import { Noun, Telemetry, Verb } from './types'; class TelemetryManager { #started = false; #telemetryObject: Partial = {}; start() { this.#telemetryObject.locale = getLocale(); this.#telemetryObject.deviceId ||= getDeviceId(); this.#telemetryObject.instanceId ||= getInstanceId(); this.#telemetryObject.openTime ||= new Date().valueOf(); this.#telemetryObject.timeline ??= []; this.#telemetryObject.errors ??= {}; this.#started = true; } getCanLog(): boolean { const telemetrySetting = config.get(ConfigKeys.Telemetry) as string; return telemetrySetting === TelemetrySetting.allow; } log(verb: Verb, noun: Noun, more?: Record) { if (!this.#started) { this.start(); } if (!this.getCanLog()) { return; } const time = new Date().valueOf(); if (this.#telemetryObject.timeline === undefined) { this.#telemetryObject.timeline = []; } this.#telemetryObject.timeline.push({ time, verb, noun, more }); } error(name: string) { if (this.#telemetryObject.errors === undefined) { this.#telemetryObject.errors = {}; } this.#telemetryObject.errors[name] ??= 0; this.#telemetryObject.errors[name] += 1; } async setCount() { this.#telemetryObject.counts = this.getCanLog() ? await getCounts() : {}; } stop() { // Will set ids if not set. this.start(); //@ts-ignore this.#telemetryObject.version = frappe.store.appVersion ?? ''; this.#telemetryObject.closeTime = new Date().valueOf(); const telemetryObject = this.#telemetryObject; this.#started = false; this.#telemetryObject = {}; if (config.get(ConfigKeys.Telemetry) === TelemetrySetting.dontLogAnything) { return ''; } return JSON.stringify(telemetryObject); } get telemetryObject(): Readonly> { return cloneDeep(this.#telemetryObject); } } export default new TelemetryManager();