Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / helpers / metrics.ts
blobd0ea0f74d8cbc999b8f57b2e3d9a0e591f8ec89a
1 import { getSilentApi } from '@proton/shared/lib/api/helpers/customConfig';
3 import { metrics } from '../api/metrics';
4 import type { TelemetryReport } from '../api/telemetry';
5 import { sendMultipleTelemetryData, sendTelemetryData } from '../api/telemetry';
6 import type { METRICS_LOG } from '../constants';
7 import { SECOND } from '../constants';
8 import type { Api } from '../interfaces';
9 import { wait } from './promise';
11 // Make the metrics false by default to avoid (rare) cases where we could have sendMetricReport or sendTelemetryReport
12 // before setting this metricsEnabled value with the user setting.
13 // In that scenario we would send something but the user might not want this.
14 let metricsEnabled = false;
16 /**
17  * Delay an operation by a random number of seconds between 1 second and the specified
18  * number of seconds. If none is provided, the default is 180 seconds, i.e. 3 minutes
19  */
20 export const randomDelay = async (delayInSeconds: number = 180) => {
21     await wait(SECOND * Math.floor(delayInSeconds * Math.random() + 1));
24 /**
25  * Send metrics report (/metrics endpoint)
26  */
27 export const sendMetricsReport = async (api: Api, Log: METRICS_LOG, Title?: string, Data?: any) => {
28     if (!metricsEnabled) {
29         return;
30     }
31     // We delay sending the metrics report because this helper is used in some privacy-sensitive
32     // use-cases, e.g. encrypted search, in which we don't want the server to be able to use the
33     // metric report as a distinguisher to correlate user actions, e.g. performing an encrypted
34     // search and fetching an email shortly after
35     await randomDelay();
36     void api(metrics({ Log, Title, Data }));
39 interface SendTelemetryReportArgs extends TelemetryReport {
40     api: Api;
41     silence?: boolean;
44 /**
45  * Send a telemetry report (/data/v1/stats endpoint)
46  */
47 export const sendTelemetryReport = async ({
48     api,
49     measurementGroup,
50     event,
51     values,
52     dimensions,
53     silence = true,
54 }: SendTelemetryReportArgs) => {
55     const possiblySilentApi = silence ? getSilentApi(api) : api;
57     if (!metricsEnabled) {
58         return;
59     }
61     try {
62         void (await possiblySilentApi(
63             sendTelemetryData({
64                 MeasurementGroup: measurementGroup,
65                 Event: event,
66                 Values: values,
67                 Dimensions: dimensions,
68             })
69         ));
70     } catch {
71         // fail silently
72     }
75 interface SendMultipleTelemetryReportsArgs {
76     api: Api;
77     reports: TelemetryReport[];
78     silence?: boolean;
81 /**
82  * Send multiple telemetry reports (/data/v1/stats/multiple endpoint)
83  */
84 export const sendMultipleTelemetryReports = async ({
85     api,
86     reports,
87     silence = true,
88 }: SendMultipleTelemetryReportsArgs) => {
89     const possiblySilentApi = silence ? getSilentApi(api) : api;
91     if (!metricsEnabled) {
92         return;
93     }
95     try {
96         void (await possiblySilentApi(sendMultipleTelemetryData({ reports })));
97     } catch {
98         // fail silently
99     }
102 export const setMetricsEnabled = (enabled: boolean) => {
103     metricsEnabled = enabled;