/
telemetry.ts
67 lines (58 loc) · 2.01 KB
/
telemetry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import originalFetch from 'isomorphic-unfetch';
import retry from 'fetch-retry';
import { nanoid } from 'nanoid';
import type { Options, TelemetryData } from './types';
import { getAnonymousProjectId } from './anonymous-id';
import { set as saveToCache } from './event-cache';
const URL = process.env.STORYBOOK_TELEMETRY_URL || 'https://storybook.js.org/event-log';
const fetch = retry(originalFetch);
let tasks: Promise<any>[] = [];
// getStorybookMetadata -> packagejson + Main.js
// event specific data: sessionId, ip, etc..
// send telemetry
const sessionId = nanoid();
export async function sendTelemetry(
data: TelemetryData,
options: Partial<Options> = { retryDelay: 1000, immediate: false }
) {
// We use this id so we can de-dupe events that arrive at the index multiple times due to the
// use of retries. There are situations in which the request "5xx"s (or times-out), but
// the server actually gets the request and stores it anyway.
// flatten the data before we send it
const { eventType, payload, metadata, ...rest } = data;
const context = options.stripMetadata
? {}
: {
anonymousId: getAnonymousProjectId(),
inCI: Boolean(process.env.CI),
isTTY: process.stdout.isTTY,
};
const eventId = nanoid();
const body = { ...rest, eventType, eventId, sessionId, metadata, payload, context };
let request: Promise<any>;
try {
request = fetch(URL, {
method: 'POST',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
retries: 3,
retryOn: [503, 504],
retryDelay: (attempt: number) =>
2 ** attempt *
(typeof options?.retryDelay === 'number' && !Number.isNaN(options?.retryDelay)
? options.retryDelay
: 1000),
});
tasks.push(request);
if (options.immediate) {
await Promise.all(tasks);
} else {
await request;
}
await saveToCache(eventType, body);
} catch (err) {
//
} finally {
tasks = tasks.filter((task) => task !== request);
}
}