// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import LocalConfig from '@assets/config'; import Store from '@store/store'; import { saveToTelemetryServer, getDeviceInfo, setTraceRecord, } from './telemetry_utils'; class Telemetry { constructor() { this.appStartTime = 0; this.reactInitializedStartTime = 0; this.reactInitializedEndTime = 0; this.metrics = []; this.currentMetrics = {}; this.pendingSinceLaunchMetrics = []; } setAppStartTime(startTime) { this.appStartTime = startTime; } reset() { this.metrics = []; this.currentMetrics = {}; this.pendingSinceLaunchMetrics = []; } canSendTelemetry() { const {config} = Store.redux.getState().entities.general; return Boolean(!__DEV__ && config.EnableDiagnostics === 'true' && LocalConfig.TelemetryEnabled); } start(names = [], time = 0) { if (this.canSendTelemetry()) { const d = new Date(); const startTime = d.getTime(); names.forEach((name) => { this.currentMetrics[name] = { name, startTime: time || startTime, }; }); } } end(names = []) { if (this.canSendTelemetry()) { const d = new Date(); const endTime = d.getTime(); names.forEach((name) => { const finalMetric = this.currentMetrics[name]; if (finalMetric && finalMetric.startTime > 0) { this.metrics.push({ ...finalMetric, endTime, }); Reflect.deleteProperty(this.currentMetrics, name); } }); } } include(metrics = []) { if (this.canSendTelemetry()) { metrics.forEach((metric) => { this.metrics.push({ name: metric.name, startTime: metric.startTime, endTime: metric.endTime, }); }); } } startSinceLaunch(names = []) { if (this.canSendTelemetry()) { const d = new Date(); const endTime = d.getTime(); names.forEach((name) => { if (!this.appStartTime) { this.pendingSinceLaunchMetrics.push({ name, endTime, }); return; } this.metrics.push({ name, startTime: this.appStartTime, endTime, }); }); } } remove(names = []) { names.forEach((name) => { const currentMetric = this.currentMetrics[name]; if (currentMetric) { Reflect.deleteProperty(this.currentMetrics, name); } }); } async save() { if (!this.canSendTelemetry()) { return; } this.pendingSinceLaunchMetrics.forEach((pendingMetric) => { this.metrics.push({ ...pendingMetric, startTime: this.appStartTime, }); }); if (this.metrics.length === 0) { return; } const metrics = this.metrics.filter((m) => m.endTime && m.startTime).map((metric) => { const {name, startTime, endTime} = metric; let dur; if (endTime && startTime) { dur = (endTime - startTime) * 1000; } return setTraceRecord({ name, time: startTime * 1000, dur, }); }); const {config} = Store.redux.getState().entities.general; const deviceInfo = getDeviceInfo(); deviceInfo.server_version = config.Version; saveToTelemetryServer({trace_events: metrics, device_info: deviceInfo}); this.reset(); } } const telemetry = new Telemetry(); export default telemetry;