Reduce analytics calls

This commit is contained in:
Sidharth Vinod
2022-09-15 12:04:46 +05:30
parent bff3c95c7c
commit 1b1ed01156
3 changed files with 75 additions and 15 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
import { writable, get, derived } from 'svelte/store';
import { persist, localStorage } from './persist';
import { saveStatistics } from './stats';
import { saveStatistics, countLines } from './stats';
import { serializeState, deserializeState } from './serde';
import { cmdKey } from './util';
import mermaid from 'mermaid';
@@ -121,8 +121,8 @@ export const updateCode = (
resetPanZoom = false
}: { updateDiagram?: boolean; resetPanZoom?: boolean } = {}
): void => {
const lines = countLines(code);
saveStatistics(code);
const lines = (code.match(/\n/g) || '').length + 1;
if (lines > 50 && !prompted && get(stateStore).autoSync) {
const turnOff = confirm(
+19
View File
@@ -0,0 +1,19 @@
import { describe, it, expect } from 'vitest';
import { detectType } from './stats';
describe('diagram detection', () => {
it('should detect diagrams correctly', () => {
expect(
detectType(`%%{{
graph`)
).toBe('graph');
expect(detectType(`gitGraph`)).toBe('gitGraph');
expect(
detectType(`%%{{
flowChart
graph`)
).toBe('flowChart');
expect(detectType(`loki -> thor`)).toBe(undefined);
});
});
+53 -12
View File
@@ -1,6 +1,5 @@
import { browser } from '$app/environment';
import type { AnalyticsInstance } from 'analytics';
export let analytics: AnalyticsInstance;
export const initAnalytics = async (): Promise<void> => {
@@ -28,27 +27,69 @@ export const initAnalytics = async (): Promise<void> => {
}
};
const detectType = (text: string): string => {
return text
export const detectType = (text: string): string => {
const possibleDiagramTypes = [
'classDiagram',
'erDiagram',
'flowChart',
'gantt',
'gitGraph',
'graph',
'journey',
'pie',
'stateDiagram'
];
const firstLine = text
.replace(/^\s*%%.*\n/g, '\n')
.trimStart()
.split(' ')[0];
.split(' ')[0]
.toLowerCase();
const detectedDiagram = possibleDiagramTypes.find((d) => firstLine.includes(d.toLowerCase()));
return detectedDiagram;
};
export const countLines = (code: string): number => {
return (code.match(/\n/g) || '').length + 1;
};
export const saveStatistics = (graph: string): void => {
const graphType = detectType(graph);
console.debug(`ga: send event: render ${graphType}`);
logEvent('render', { graphType });
const length = countLines(graph);
logEvent('render', { graphType, length });
};
// manual debounce to only send analytics event every 5 seconds if same event is repeated frequently.
const minutesToMilliSeconds = (minutes: number): number => {
return minutes * 60_000;
};
const defaultDelay = minutesToMilliSeconds(1);
const delaysPerEvent = {
render: minutesToMilliSeconds(5),
panZoom: minutesToMilliSeconds(10),
copyClipboard: defaultDelay,
download: defaultDelay,
copyMarkdown: defaultDelay,
loadGist: defaultDelay,
loadSampleDiagram: defaultDelay,
renderDiagram: defaultDelay,
history: defaultDelay,
migration: defaultDelay,
themeChange: defaultDelay
};
export type AnalyticsEvent = keyof typeof delaysPerEvent;
const timeouts: Record<string, number> = {};
export const logEvent = (name: string, data?: unknown): void => {
if (analytics) {
// manual debounce to reduce the number of events sent to analytics
export const logEvent = (name: AnalyticsEvent, data?: unknown): void => {
if (!analytics) {
return;
}
const key = data ? JSON.stringify({ name, data }) : name;
if (timeouts[key] === undefined) {
void analytics.track(name, data);
} else {
clearTimeout(timeouts[key]);
}
timeouts[key] = window.setTimeout(() => {
void analytics.track(name, data);
}, 5000);
}
delete timeouts[key];
}, delaysPerEvent[name]);
};