@aicore/core-analytics-client-lib 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/analytics.min.js.map +1 -0
- package/package.json +5 -1
- package/src/analytics.js +230 -0
- package/src/client-schema.md +78 -0
package/README.md
CHANGED
|
@@ -24,9 +24,9 @@ Embed the script in your HTML file :
|
|
|
24
24
|
```html
|
|
25
25
|
<html lang="en">
|
|
26
26
|
<script type="module">
|
|
27
|
-
// For production use cases, use url: https://unpkg.com
|
|
27
|
+
// For production use cases, use url: https://unpkg.com/@aicore/core-analytics-client-lib/dist/analytics.min.js
|
|
28
28
|
// The below url is for development purposes only.
|
|
29
|
-
import {initSession} from "https://unpkg.com
|
|
29
|
+
import {initSession} from "https://unpkg.com/@aicore/core-analytics-client-lib/src/analytics.js";
|
|
30
30
|
initSession("accountID", "appName");
|
|
31
31
|
</script>
|
|
32
32
|
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sourceRoot":"src/analytics.js","sources":["src/analytics.js"],"names":["let","accountID","appName","userID","sessionID","postIntervalSeconds","granularitySec","postURL","DEFAULT_GRANULARITY_IN_SECONDS","DEFAULT_RETRY_TIME_IN_SECONDS","DEFAULT_POST_INTERVAL_SECONDS","USERID_LOCAL_STORAGE_KEY","POST_LARGE_DATA_THRESHOLD_BYTES","currentAnalyticsEvent","IS_NODE_ENV","window","DEFAULT_BASE_URL","granularityTimer","postTimer","currentQuantisedTime","Error","_createAnalyticsEvent","schemaVersion","uuid","unixTimestampUTC","Date","numEventsTotal","events","_validateCurrentState","getCurrentAnalyticsEvent","JSON","parse","stringify","_getOrCreateUserID","localUserID","localStorage","getItem","crypto","randomUUID","setItem","_getOrCreateSessionID","localSessionID","sessionStorage","Math","random","toString","substr","_setupIDs","_retryPost","eventToSend","backoffCount","console","log","setTimeout","_postCurrentAnalyticsEvent","textToSend","length","warn","fetch","method","headers","Content-Type","body","then","res","status","error","catch","_setupTimers","clearInterval","setInterval","initSession","accountIDInit","appNameInit","postIntervalSecondsInit","granularitySecInit","postBaseURLInit","_ensureAnalyticsEventExists","eventType","category","subCategory","time","valueCount","_validateEvent","count","value","_updateExistingAnalyticsEvent","index","newValue","storedValueIsCount","newValueCount","storedValueObject","analyticsEvent","eventCategory","eventCount","eventValue","timeArray","push"],"mappings":"AAKAA,IAAIC,UAAWC,QAASC,OAAQC,UAAWC,oBAAqBC,eAAgBC,QAChF,MAAMC,+BAAiC,EACjCC,8BAAgC,GAChCC,8BAAgC,IAChCC,yBAA2B,0BAC3BC,gCAAkC,IACxCZ,IAAIa,sBAAwB,KAC5B,MAAMC,YAAiC,oBAAXC,OAC5Bf,IAAIgB,iBAAmB,4BAEnBC,iBACAC,UACAC,qBAAuB,EAE3B,GAAGL,YACC,MAAM,IAAIM,MAAM,+CAGpB,SAASC,wBACL,MAAO,CACHC,cAAe,EACfrB,UAAWA,UACXC,QAASA,QACTqB,KAAMpB,OACNC,UAAWA,UACXE,eAAgBA,eAChBkB,kBAAmB,IAAIC,KACvBC,eAAgB,EAChBC,OAAQ,IAIhB,SAASC,wBACL,IAAIf,sBACA,MAAM,IAAIO,MAAM,4DAIxB,SAASS,2BAGL,OAFAD,wBAEOE,KAAKC,MAAMD,KAAKE,UAAUnB,wBAGrC,SAASoB,qBACLjC,IAAIkC,EAAcC,aAAaC,QAAQzB,0BAKvC,OAJIuB,IACAA,EAAcG,OAAOC,aACrBH,aAAaI,QAAQ5B,yBAA0BuB,IAE5CA,EAGX,SAASM,wBACLxC,IAAIyC,EAAiBC,eAAeN,QAAQzB,0BAK5C,OAJI8B,IACAA,EAAiBE,KAAKC,SAASC,SAAS,IAAIC,OAAO,EAAG,IACtDJ,eAAeH,QAAQ5B,yBAA0B8B,IAE9CA,EAGX,SAASM,YACL5C,OAAS8B,qBACT7B,UAAYoC,wBAGhB,SAASQ,WAAWC,GAChBA,EAAYC,cAAgBD,EAAYC,cAAgB,GAAK,EAC7DC,QAAQC,2DACJ3C,8BAAgCwC,EAAYC,mBAChDG,WAAW,KACPC,2BAA2BL,IACI,IAAhCxC,8BAAuCwC,EAAYC,cAG1D,SAASI,2BAA2BL,GAKhC,IAGIM,EAPAN,IACAA,EAAcpC,sBACdA,sBAAwBQ,yBAEM,IAA/B4B,EAAYvB,kBAGX6B,EAAazB,KAAKE,UAAUiB,IAClBO,OAAS5C,iCACnBuC,QAAQM,gEAAgEF,EAAWC;2EAGvFzC,OAAO2C,MAAMnD,QAAS,CAClBoD,OAAQ,OACRC,QAAS,CAACC,eAAgB,oBAC1BC,KAAMP,IACPQ,KAAKC,IACc,MAAfA,EAAIC,SAGW,MAAfD,EAAIC,OACHjB,WAAWC,GAEXE,QAAQe,MAAM,6FAEnBC,MAAMH,IACLb,QAAQe,MAAMF,GACdhB,WAAWC,MAInB,SAASmB,eACFnD,mBACCoD,cAAcpD,kBACdA,iBAAmB,MAEvBA,iBAAmBqD,YAAY,KAC3BnD,sBAA8Cb,gBAChC,IAAfA,gBAEAY,YACCmD,cAAcnD,WACdA,UAAY,MAEhBA,UAAYoD,YAAYhB,2BAAgD,IAApBjD,qBAcxD,SAASkE,YAAYC,EAAeC,EAAaC,EAAyBC,EAAoBC,GAC1F,IAAIJ,IAAkBC,EAClB,MAAM,IAAIrD,MAAM,6CAEpBnB,UAAYuE,EACZtE,QAAUuE,EACVpE,oBAAsBqE,GAA2BhE,8BACjDJ,eAAiBqE,GAAsBnE,+BACvCD,SAAWqE,GAAmB5D,kBAAoB,UAClD+B,YACAlC,sBAAwBQ,wBACxB+C,eAGJ,SAASS,4BAA4BC,EAAWC,EAAUC,GACtDhF,IAAI2B,EAASd,sBAAsBc,OACnCA,EAAOmD,GAAanD,EAAOmD,IAAc,GACzCnD,EAAOmD,GAAWC,GAAYpD,EAAOmD,GAAWC,IAAa,GAC7DpD,EAAOmD,GAAWC,GAAUC,GAAerD,EAAOmD,GAAWC,GAAUC,IAAgB,CACnFC,KAAM,GACNC,WAAY,IAIpB,SAASC,eAAeL,EAAWC,EAAUC,EAAaI,EAAOC,GAE7D,GADAzD,yBACIkD,IAAcC,IAAaC,EAC3B,MAAM,IAAI5D,MAAM,gDAEpB,GAAoB,iBAAX,GAAuBgE,EAAO,EACnC,MAAM,IAAIhE,MAAM,iBAEpB,GAAoB,iBAAX,EACL,MAAM,IAAIA,MAAM,iBAIxB,SAASkE,8BAA8BC,EAAOT,EAAWC,EAAUC,EAAaI,EAAOI,GACnFxF,IAAI2B,EAASd,sBAAsBc,OACnC,IAAM8D,EAA+F,iBAAnE9D,EAAOmD,GAAWC,GAAUC,GAAyB,WAAEO,GACzF,GAAGE,GAAmC,IAAbD,EACrB7D,EAAOmD,GAAWC,GAAUC,GAAyB,WAAEO,IAAUH,OAC9D,GAAGK,GAAmC,IAAbD,EAAe,CAC3CxF,IAAI0F,EAAgB,GACpBA,EAAcF,GAAYJ,EAC1BM,EAAc,GAAK/D,EAAOmD,GAAWC,GAAUC,GAAyB,WAAEO,GAC1E5D,EAAOmD,GAAWC,GAAUC,GAAyB,WAAEO,GAASG,OAC7D,IAAID,EAAmB,CAC1BzF,IAAI2F,EAAoBhE,EAAOmD,GAAWC,GAAUC,GAAyB,WAAEO,GAC/EI,EAAkBH,IAAaG,EAAkBH,IAAa,GAAKJ,EAEvEvE,sBAAsBa,gBAAkB,EAY5C,SAASkE,eAAed,EAAWe,EAAeb,EAAac,EAAW,EAAGC,EAAW,GACpFZ,eAAeL,EAAWe,EAAeb,EAAac,EAAYC,GAClElB,4BAA4BC,EAAWe,EAAeb,GACtDhF,IAAI2B,EAASd,sBAAsBc,OACnC3B,IAAIgG,EAAYrE,EAAOmD,GAAWe,GAAeb,GAAmB,KAEpE,IADgC,EAAjBgB,EAAUxC,OAAUwC,EAAUA,EAAUxC,OAAO,GAAK,QACnDrC,qBAahBmE,8BADwB3D,EAAOmD,GAAWe,GAAeb,GAAyB,WAAExB,OAAQ,EAC3CsB,EAAWe,EAAeb,EAAac,EAAYC,OAbpG,CAEI,GADApE,EAAOmD,GAAWe,GAAeb,GAAmB,KAAEiB,KAAK9E,sBAC3C,IAAb4E,EACCpE,EAAOmD,GAAWe,GAAeb,GAAyB,WAAEiB,KAAKH,OAC9D,CACH9F,IAAIkF,EAAa,GACjBA,EAAWa,GAAcD,EACzBnE,EAAOmD,GAAWe,GAAeb,GAAyB,WAAEiB,KAAKf,GAErErE,sBAAsBa,gBAAkB,UAQ5C6C,YACA1C,yBACA+D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aicore/core-analytics-client-lib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Analytics client library for https://github.com/aicore/Core-Analytics-Server",
|
|
5
5
|
"main": "dist/analytics.min.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"minify": "echo creating minified package dist/analytics.min.js && mkdir -p dist && uglifyjs src/analytics.js --compress --mangle -o dist/analytics.min.js -c -m --source-map \"root='src/analytics.js',url='analytics.min.js.map'\"",
|
|
31
31
|
"release": "npm run patchVersion && npm run minify"
|
|
32
32
|
},
|
|
33
|
+
"files": [
|
|
34
|
+
"src",
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
33
37
|
"repository": {
|
|
34
38
|
"type": "git",
|
|
35
39
|
"url": "git+https://github.com/aicore/core-analytics-client-lib.git"
|
package/src/analytics.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// GNU AGPL-3.0 License Copyright (c) 2021 - present core.ai . All rights reserved.
|
|
2
|
+
|
|
3
|
+
// jshint ignore: start
|
|
4
|
+
/*global localStorage, sessionStorage, crypto*/
|
|
5
|
+
|
|
6
|
+
let accountID, appName, userID, sessionID, postIntervalSeconds, granularitySec, postURL;
|
|
7
|
+
const DEFAULT_GRANULARITY_IN_SECONDS = 3;
|
|
8
|
+
const DEFAULT_RETRY_TIME_IN_SECONDS = 30;
|
|
9
|
+
const DEFAULT_POST_INTERVAL_SECONDS = 600; // 10 minutes
|
|
10
|
+
const USERID_LOCAL_STORAGE_KEY = 'aicore.analytics.userID';
|
|
11
|
+
const POST_LARGE_DATA_THRESHOLD_BYTES = 10000;
|
|
12
|
+
let currentAnalyticsEvent = null;
|
|
13
|
+
const IS_NODE_ENV = (typeof window === 'undefined');
|
|
14
|
+
let DEFAULT_BASE_URL = "https://analytics.core.ai";
|
|
15
|
+
|
|
16
|
+
let granularityTimer;
|
|
17
|
+
let postTimer;
|
|
18
|
+
let currentQuantisedTime = 0;
|
|
19
|
+
|
|
20
|
+
if(IS_NODE_ENV){
|
|
21
|
+
throw new Error("Node environment is not currently supported");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function _createAnalyticsEvent() {
|
|
25
|
+
return {
|
|
26
|
+
schemaVersion: 1,
|
|
27
|
+
accountID: accountID,
|
|
28
|
+
appName: appName,
|
|
29
|
+
uuid: userID,
|
|
30
|
+
sessionID: sessionID,
|
|
31
|
+
granularitySec: granularitySec,
|
|
32
|
+
unixTimestampUTC: +new Date(),
|
|
33
|
+
numEventsTotal: 0,
|
|
34
|
+
events: {}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _validateCurrentState() {
|
|
39
|
+
if(!currentAnalyticsEvent){
|
|
40
|
+
throw new Error("Please call initSession before using any analytics event");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getCurrentAnalyticsEvent() {
|
|
45
|
+
_validateCurrentState();
|
|
46
|
+
// return a clone
|
|
47
|
+
return JSON.parse(JSON.stringify(currentAnalyticsEvent));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function _getOrCreateUserID() {
|
|
51
|
+
let localUserID = localStorage.getItem(USERID_LOCAL_STORAGE_KEY);
|
|
52
|
+
if(!localUserID){
|
|
53
|
+
localUserID = crypto.randomUUID();
|
|
54
|
+
localStorage.setItem(USERID_LOCAL_STORAGE_KEY, localUserID);
|
|
55
|
+
}
|
|
56
|
+
return localUserID;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function _getOrCreateSessionID() {
|
|
60
|
+
let localSessionID = sessionStorage.getItem(USERID_LOCAL_STORAGE_KEY);
|
|
61
|
+
if(!localSessionID){
|
|
62
|
+
localSessionID = Math.random().toString(36).substr(2, 10);
|
|
63
|
+
sessionStorage.setItem(USERID_LOCAL_STORAGE_KEY, localSessionID);
|
|
64
|
+
}
|
|
65
|
+
return localSessionID;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function _setupIDs() {
|
|
69
|
+
userID = _getOrCreateUserID();
|
|
70
|
+
sessionID = _getOrCreateSessionID();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function _retryPost(eventToSend) {
|
|
74
|
+
eventToSend.backoffCount = (eventToSend.backoffCount || 0) + 1;
|
|
75
|
+
console.log(`Failed to call core analytics server. Will retry in ${
|
|
76
|
+
DEFAULT_RETRY_TIME_IN_SECONDS * eventToSend.backoffCount}s: `);
|
|
77
|
+
setTimeout(()=>{
|
|
78
|
+
_postCurrentAnalyticsEvent(eventToSend);
|
|
79
|
+
}, DEFAULT_RETRY_TIME_IN_SECONDS * 1000 * eventToSend.backoffCount);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function _postCurrentAnalyticsEvent(eventToSend) {
|
|
83
|
+
if(!eventToSend){
|
|
84
|
+
eventToSend = currentAnalyticsEvent;
|
|
85
|
+
currentAnalyticsEvent = _createAnalyticsEvent();
|
|
86
|
+
}
|
|
87
|
+
if(eventToSend.numEventsTotal === 0 ){
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
let textToSend = JSON.stringify(eventToSend);
|
|
91
|
+
if(textToSend.length > POST_LARGE_DATA_THRESHOLD_BYTES){
|
|
92
|
+
console.warn(`Analytics event generated is very large at greater than ${textToSend.length}B. This
|
|
93
|
+
typically means that you may be sending too many value events? .`);
|
|
94
|
+
}
|
|
95
|
+
window.fetch(postURL, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: {'Content-Type': 'application/json'},
|
|
98
|
+
body: textToSend
|
|
99
|
+
}).then(res=>{
|
|
100
|
+
if(res.status === 200){
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if(res.status !== 400){ // we don't retry bad requests
|
|
104
|
+
_retryPost(eventToSend);
|
|
105
|
+
} else {
|
|
106
|
+
console.error("Bad Request, this is most likely a problem with the library, update to latest version.");
|
|
107
|
+
}
|
|
108
|
+
}).catch(res => {
|
|
109
|
+
console.error(res);
|
|
110
|
+
_retryPost(eventToSend);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function _setupTimers() {
|
|
115
|
+
if(granularityTimer){
|
|
116
|
+
clearInterval(granularityTimer);
|
|
117
|
+
granularityTimer = null;
|
|
118
|
+
}
|
|
119
|
+
granularityTimer = setInterval(()=>{
|
|
120
|
+
currentQuantisedTime = currentQuantisedTime + granularitySec;
|
|
121
|
+
}, granularitySec*1000);
|
|
122
|
+
|
|
123
|
+
if(postTimer){
|
|
124
|
+
clearInterval(postTimer);
|
|
125
|
+
postTimer = null;
|
|
126
|
+
}
|
|
127
|
+
postTimer = setInterval(_postCurrentAnalyticsEvent, postIntervalSeconds*1000);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Initialize the analytics session
|
|
132
|
+
* @param accountIDInit Your analytics account id as configured in the server or core.ai analytics
|
|
133
|
+
* @param appNameInit The app name to log the events against.
|
|
134
|
+
* @param postIntervalSecondsInit Optional: This defines the interval between sending analytics events to the server.
|
|
135
|
+
* Default is 10 minutes
|
|
136
|
+
* @param granularitySecInit Optional: The smallest time period under which the events can be distinguished. Multiple
|
|
137
|
+
* events happening during this time period is aggregated to a count. The default granularity is 3 Seconds, which means
|
|
138
|
+
* that any events that happen within 3 seconds cannot be distinguished in ordering.
|
|
139
|
+
* @param postBaseURLInit Optional: Provide your own analytics server address if you self-hosted the server
|
|
140
|
+
*/
|
|
141
|
+
function initSession(accountIDInit, appNameInit, postIntervalSecondsInit, granularitySecInit, postBaseURLInit) {
|
|
142
|
+
if(!accountIDInit || !appNameInit){
|
|
143
|
+
throw new Error("accountID and appName must exist for init");
|
|
144
|
+
}
|
|
145
|
+
accountID = accountIDInit;
|
|
146
|
+
appName = appNameInit;
|
|
147
|
+
postIntervalSeconds = postIntervalSecondsInit || DEFAULT_POST_INTERVAL_SECONDS;
|
|
148
|
+
granularitySec = granularitySecInit || DEFAULT_GRANULARITY_IN_SECONDS;
|
|
149
|
+
postURL = (postBaseURLInit || DEFAULT_BASE_URL) + "/ingest";
|
|
150
|
+
_setupIDs();
|
|
151
|
+
currentAnalyticsEvent = _createAnalyticsEvent();
|
|
152
|
+
_setupTimers();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function _ensureAnalyticsEventExists(eventType, category, subCategory) {
|
|
156
|
+
let events = currentAnalyticsEvent.events;
|
|
157
|
+
events[eventType] = events[eventType] || {};
|
|
158
|
+
events[eventType][category] = events[eventType][category] || {};
|
|
159
|
+
events[eventType][category][subCategory] = events[eventType][category][subCategory] || {
|
|
160
|
+
time: [], // quantised time
|
|
161
|
+
valueCount: [] // value and count array, If a single value, then it is count, else object {"val1":count1, ...}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function _validateEvent(eventType, category, subCategory, count, value) {
|
|
166
|
+
_validateCurrentState();
|
|
167
|
+
if(!eventType || !category || !subCategory){
|
|
168
|
+
throw new Error("missing eventType or category or subCategory");
|
|
169
|
+
}
|
|
170
|
+
if(typeof(count)!== 'number' || count <0){
|
|
171
|
+
throw new Error("invalid count");
|
|
172
|
+
}
|
|
173
|
+
if(typeof(value)!== 'number'){
|
|
174
|
+
throw new Error("invalid value");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function _updateExistingAnalyticsEvent(index, eventType, category, subCategory, count, newValue) {
|
|
179
|
+
let events = currentAnalyticsEvent.events;
|
|
180
|
+
const storedValueIsCount = typeof(events[eventType][category][subCategory]["valueCount"][index]) === 'number';
|
|
181
|
+
if(storedValueIsCount && newValue === 0){
|
|
182
|
+
events[eventType][category][subCategory]["valueCount"][index] += count;
|
|
183
|
+
} else if(storedValueIsCount && newValue !== 0){
|
|
184
|
+
let newValueCount = {};
|
|
185
|
+
newValueCount[newValue] = count;
|
|
186
|
+
newValueCount[0] = events[eventType][category][subCategory]["valueCount"][index];
|
|
187
|
+
events[eventType][category][subCategory]["valueCount"][index] = newValueCount;
|
|
188
|
+
} else if(!storedValueIsCount){
|
|
189
|
+
let storedValueObject = events[eventType][category][subCategory]["valueCount"][index];
|
|
190
|
+
storedValueObject[newValue] = (storedValueObject[newValue] || 0) + count;
|
|
191
|
+
}
|
|
192
|
+
currentAnalyticsEvent.numEventsTotal += 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Register an analytics event. The events will be aggregated and send to the analytics server periodically.
|
|
197
|
+
* @param eventType - String, required
|
|
198
|
+
* @param eventCategory - String, required
|
|
199
|
+
* @param subCategory - String, required
|
|
200
|
+
* @param eventCount (Optional) : A non-negative number indicating the number of times the event (or an event with a
|
|
201
|
+
* particular value if a value is specified) happened. defaults to 1.
|
|
202
|
+
* @param eventValue (Optional) : A number value associated with the event. defaults to 0
|
|
203
|
+
*/
|
|
204
|
+
function analyticsEvent(eventType, eventCategory, subCategory, eventCount=1, eventValue=0) {
|
|
205
|
+
_validateEvent(eventType, eventCategory, subCategory, eventCount, eventValue);
|
|
206
|
+
_ensureAnalyticsEventExists(eventType, eventCategory, subCategory);
|
|
207
|
+
let events = currentAnalyticsEvent.events;
|
|
208
|
+
let timeArray = events[eventType][eventCategory][subCategory]["time"];
|
|
209
|
+
let lastTime = timeArray.length>0? timeArray[timeArray.length-1] : null;
|
|
210
|
+
if(lastTime !== currentQuantisedTime){
|
|
211
|
+
events[eventType][eventCategory][subCategory]["time"].push(currentQuantisedTime);
|
|
212
|
+
if(eventValue===0){
|
|
213
|
+
events[eventType][eventCategory][subCategory]["valueCount"].push(eventCount);
|
|
214
|
+
} else {
|
|
215
|
+
let valueCount = {};
|
|
216
|
+
valueCount[eventValue] = eventCount;
|
|
217
|
+
events[eventType][eventCategory][subCategory]["valueCount"].push(valueCount);
|
|
218
|
+
}
|
|
219
|
+
currentAnalyticsEvent.numEventsTotal += 1;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
let modificationIndex = events[eventType][eventCategory][subCategory]["valueCount"].length -1;
|
|
223
|
+
_updateExistingAnalyticsEvent(modificationIndex, eventType, eventCategory, subCategory, eventCount, eventValue);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export {
|
|
227
|
+
initSession,
|
|
228
|
+
getCurrentAnalyticsEvent,
|
|
229
|
+
analyticsEvent
|
|
230
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Client schema
|
|
2
|
+
The `analytics client js lib` client periodically sends data to the analytics backend as JSON aggregated over a time period. The JSON format is as follows:
|
|
3
|
+
|
|
4
|
+
schema:
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"schemaVersion" : 1,
|
|
8
|
+
"appName" : "app1",
|
|
9
|
+
"uuid": "u1",
|
|
10
|
+
"sessionID": "s1",
|
|
11
|
+
"granularitySec" : 3,
|
|
12
|
+
"unixTimestampUTC" : 1643043376,
|
|
13
|
+
"numEventsTotal": 25,
|
|
14
|
+
"events":{
|
|
15
|
+
"eventType":{
|
|
16
|
+
"category":{
|
|
17
|
+
"subCategory": {
|
|
18
|
+
"t": [0,3],
|
|
19
|
+
"v": [1,[1,3]],
|
|
20
|
+
"c": [23,2]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
## Fileds for schema version:1
|
|
29
|
+
1. `schemaVersion` : The version number for schema followed by the client. Currently, only 1 schema exists.
|
|
30
|
+
1. `appName`: The application name for which the event is being raised.
|
|
31
|
+
2. `uuid`: The unique id for the user. or the string `default` if there is no UUID/anonymous analytics is used from client.
|
|
32
|
+
3. `sessionID`: The unique session-id autogenerated by the client lib for each session. Will be reset for every session.
|
|
33
|
+
4. `granularitySec`: The minimum granularity for event recording in seconds. Repeating events within the same granularity window will be aggregated and only the count will be increased.
|
|
34
|
+
5. `unixTimestampUTC`: The start Unix time from which the client time is being recorded.
|
|
35
|
+
5. `numEventsTotal`: The sum total of all events raised from the client. This aggregates all count values `c`
|
|
36
|
+
6. `events` : A map of events that took place from `unixTimestamp`. The keys are nested in order `eventType` > `category` > `subCategory`
|
|
37
|
+
* Within a subcategory, `t` array specifies the `time window` in seconds from the `unixTimestamp` for which the current event is raised.
|
|
38
|
+
* `v` array specifies the `values` if any that are logged as part of the event. If no value is specified, the default value `1` is used. If multiple values are logged within the same window, it is logged as an array.
|
|
39
|
+
* `c` array specifies the `count` of events that happened within the time window. For Eg. in the above schema, the event that started in window 0 repeated 23 counts within the window with the default value(1).
|
|
40
|
+
|
|
41
|
+
## sample analytics event
|
|
42
|
+
Schema
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"schemaVersion" : 1,
|
|
46
|
+
"appName" : "brackets",
|
|
47
|
+
"uuid": "u1",
|
|
48
|
+
"sessionID": "s1",
|
|
49
|
+
"granularitySec" : 3,
|
|
50
|
+
"unixTimestampUTC" : 1643043376,
|
|
51
|
+
"numEventsTotal" : 5,
|
|
52
|
+
"events":{
|
|
53
|
+
"platform":{
|
|
54
|
+
"os":{
|
|
55
|
+
"win": {
|
|
56
|
+
"t": [0],
|
|
57
|
+
"v": [1],
|
|
58
|
+
"c": [1]
|
|
59
|
+
}
|
|
60
|
+
}, "performance":{
|
|
61
|
+
"fileOpenTimeMs": {
|
|
62
|
+
"t": [0,3,6],
|
|
63
|
+
"v": [102, [50,34], 200],
|
|
64
|
+
"c": [1,2,1]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
The above event raises two event types :
|
|
73
|
+
1. (platform, os, win)
|
|
74
|
+
2. (platform, performance, fileOpenTimeMs)
|
|
75
|
+
* at time `1643043376 + 0`, a value of `102` is registered.
|
|
76
|
+
* at time `1643043376 + 3000`, two values `[50,34]` are registered.
|
|
77
|
+
* at time `1643043376 + 6000`, a value of 200 is registered.
|
|
78
|
+
|