-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtelemetrySubmitter.ts
More file actions
150 lines (131 loc) · 5.8 KB
/
Copy pathtelemetrySubmitter.ts
File metadata and controls
150 lines (131 loc) · 5.8 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import { ITelemetryCacheSync } from '../../storages/types';
import { submitterFactory, firstPushWindowDecorator } from './submitter';
import { TelemetryConfigStatsPayload, TelemetryConfigStats } from './types';
import { CONSUMER_MODE, CONSUMER_ENUM, STANDALONE_MODE, CONSUMER_PARTIAL_MODE, STANDALONE_ENUM, CONSUMER_PARTIAL_ENUM, OPTIMIZED, DEBUG, NONE, DEBUG_ENUM, OPTIMIZED_ENUM, NONE_ENUM, CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../../utils/constants';
import { SDK_READY, SDK_READY_FROM_CACHE } from '../../readiness/constants';
import { ISettings } from '../../types';
import SplitIO from '../../../types/splitio';
import { base } from '../../utils/settingsValidation';
import { usedKeysMap } from '../../utils/inputValidation/apiKey';
import { timer } from '../../utils/timeTracker/timer';
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
import { objectAssign } from '../../utils/lang/objectAssign';
import { ISplitFiltersValidation } from '../../dtos/types';
import { checkIfServerSide } from '../../utils/key';
const OPERATION_MODE_MAP = {
[STANDALONE_MODE]: STANDALONE_ENUM,
[CONSUMER_MODE]: CONSUMER_ENUM,
[CONSUMER_PARTIAL_MODE]: CONSUMER_PARTIAL_ENUM
} as Record<ISettings['mode'], (0 | 1 | 2)>;
const IMPRESSIONS_MODE_MAP = {
[OPTIMIZED]: OPTIMIZED_ENUM,
[DEBUG]: DEBUG_ENUM,
[NONE]: NONE_ENUM
} as Record<ISettings['sync']['impressionsMode'], (0 | 1 | 2)>;
const USER_CONSENT_MAP = {
[CONSENT_UNKNOWN]: 1,
[CONSENT_GRANTED]: 2,
[CONSENT_DECLINED]: 3
} as Record<SplitIO.ConsentStatus, number>;
function getActiveFactories() {
return Object.keys(usedKeysMap).length;
}
function getRedundantActiveFactories() {
return Object.keys(usedKeysMap).reduce((acum, sdkKey) => {
return acum + usedKeysMap[sdkKey] - 1;
}, 0);
}
function getTelemetryFlagSetsStats(splitFiltersValidation: ISplitFiltersValidation) {
// Group every configured flag set in an unique array called originalSets
let flagSetsTotal = 0;
splitFiltersValidation.validFilters.forEach((filter: SplitIO.SplitFilter) => {
if (filter.type === 'bySet') flagSetsTotal += filter.values.length;
});
const flagSetsValid = splitFiltersValidation.groupedFilters.bySet.length;
const flagSetsIgnored = flagSetsTotal - flagSetsValid;
return { flagSetsTotal, flagSetsIgnored };
}
export function getTelemetryConfigStats(mode: SplitIO.SDKMode, storageType: string): TelemetryConfigStats {
return {
oM: OPERATION_MODE_MAP[mode], // @ts-ignore lower case of storage type
st: storageType.toLowerCase(),
aF: getActiveFactories(),
rF: getRedundantActiveFactories(),
};
}
/**
* Converts data from telemetry cache and settings into /metrics/config request payload.
*/
export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, settings: ISettings) {
return {
name: 'telemetry config',
isEmpty() { return false; },
clear() { },
pop(): TelemetryConfigStatsPayload {
const { urls, scheduler } = settings;
const isServerSide = checkIfServerSide(settings);
const { flagSetsTotal, flagSetsIgnored } = getTelemetryFlagSetsStats(settings.sync.__splitFiltersValidation);
return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
sE: settings.streamingEnabled,
rR: {
sp: scheduler.featuresRefreshRate / 1000,
se: isServerSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
ms: isServerSide ? undefined : scheduler.segmentsRefreshRate / 1000,
im: scheduler.impressionsRefreshRate / 1000,
ev: scheduler.eventsPushRate / 1000,
te: scheduler.telemetryRefreshRate / 1000,
}, // refreshRates
uO: {
s: urls.sdk !== base.urls.sdk,
e: urls.events !== base.urls.events,
a: urls.auth !== base.urls.auth,
st: urls.streaming !== base.urls.streaming,
t: urls.telemetry !== base.urls.telemetry,
}, // urlOverrides
iQ: scheduler.impressionsQueueSize,
eQ: scheduler.eventsQueueSize,
iM: IMPRESSIONS_MODE_MAP[settings.sync.impressionsMode],
iL: settings.impressionListener ? true : false,
hP: false, // @TODO proxy not supported
tR: telemetry.getTimeUntilReady() as number,
tC: telemetry.getTimeUntilReadyFromCache(),
nR: telemetry.getNonReadyUsage(),
t: telemetry.popTags(),
i: settings.integrations && settings.integrations.map(int => int.type),
uC: settings.userConsent ? USER_CONSENT_MAP[settings.userConsent] : 0,
fsT: flagSetsTotal,
fsI: flagSetsIgnored
});
}
};
}
/**
* Submitter that periodically posts telemetry data
*/
export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
const { storage: { telemetry }, platform: { now } } = params;
if (!telemetry || !now) return; // No submitter created if telemetry cache is not defined
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness, sdkReadinessManager } = params;
const stopTimer = timer(now);
const submitter = firstPushWindowDecorator(
submitterFactory(
log, splitApi.postMetricsUsage,
telemetry,
telemetryRefreshRate, undefined, 0, true
),
telemetryRefreshRate
);
readiness.gate.once(SDK_READY_FROM_CACHE, () => {
telemetry.recordTimeUntilReadyFromCache(stopTimer());
});
sdkReadinessManager.incInternalReadyCbCount();
readiness.gate.once(SDK_READY, () => {
telemetry.recordTimeUntilReady(stopTimer());
// Post config data when the SDK is ready and if the telemetry submitter was started
if (submitter.isRunning()) {
const postMetricsConfigTask = submitterFactory(log, splitApi.postMetricsConfig, telemetryCacheConfigAdapter(telemetry, settings), 0, undefined, 0, true);
postMetricsConfigTask.execute();
}
});
return submitter;
}