@aicore/core-analytics-client-lib 1.0.7 → 1.0.10
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 +19 -10
- package/dist/analytics.min.js +3 -3
- package/dist/analytics.min.js.map +1 -1
- package/package.json +1 -1
- package/src/analytics.js +102 -55
package/README.md
CHANGED
|
@@ -113,14 +113,13 @@ during the `initAnalyticsSession` call. `initAnalyticsSession()` takes the follo
|
|
|
113
113
|
|
|
114
114
|
* `accountID`: Your analytics account id as configured in the server or core.ai analytics
|
|
115
115
|
* `appName`: The app name to log the events against. Eg: "phoenixCode"
|
|
116
|
-
* `
|
|
116
|
+
* `analyticsURL` (_Optional_): Provide your own analytics server address if you self-hosted the server.
|
|
117
|
+
* `postIntervalSeconds` (_Optional_): This defines the interval between sending analytics events to the server. Default is 1 minutes or server controlled.
|
|
117
118
|
* `granularitySec` (_Optional_): The smallest time period under which the events can be distinguished. Multiple
|
|
118
|
-
events happening during this time period is aggregated to a count. The default granularity is 3 Seconds
|
|
119
|
-
that any events that happen within 3 seconds cannot be distinguished in ordering.
|
|
120
|
-
* `analyticsURL` (_Optional_): Provide your own analytics server address if you self-hosted the server
|
|
121
|
-
* `debug` (_Optional_): set to true if you want to see detailed debug logs.
|
|
119
|
+
events happening during this time period is aggregated to a count. The default granularity is 3 Seconds or server controlled,
|
|
120
|
+
which means that any events that happen within 3 seconds cannot be distinguished in ordering.
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
#### usageExample
|
|
124
123
|
```javascript
|
|
125
124
|
// Init with default values and server controlled config. use the following `analyticsLibLoaded` function
|
|
126
125
|
function analyticsLibLoaded() {
|
|
@@ -134,12 +133,22 @@ function analyticsLibLoaded() {
|
|
|
134
133
|
// is posted to custom server https://localhost:3000 every 600 secs
|
|
135
134
|
// with a granularity(resolution) of 5 seconds.
|
|
136
135
|
initAnalyticsSession("accountID", "appName", "https://localhost:3000", 600, 5);
|
|
136
|
+
```
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
### Debug logs
|
|
139
|
+
If you want to see detailed logs on what is happening inside analytics lib, use the below code:
|
|
140
|
+
```js
|
|
141
|
+
// Just before initAnalyticsSession call, set or unset window.analytics.debugMode
|
|
142
|
+
window.analytics.debugMode = true;
|
|
143
|
+
initAnalyticsSession("accountID", "appName");
|
|
141
144
|
```
|
|
142
145
|
|
|
146
|
+
To see info level logs that shows actual analytics data being sent to server, set or unset the below property:
|
|
147
|
+
```js
|
|
148
|
+
window.analytics.debugInfoLogsEnable = true;
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
|
|
143
152
|
# Contribute to core-analytics-client-lib
|
|
144
153
|
|
|
145
154
|
## Building
|
|
@@ -149,7 +158,7 @@ Since this is a pure JS template project, build command just runs test with cove
|
|
|
149
158
|
|
|
150
159
|
# Before raising a pull request, run release script and add the generated
|
|
151
160
|
# minified files in dist folder to commits .
|
|
152
|
-
# WARNING!!!: If the minified files are not
|
|
161
|
+
# WARNING!!!: If the minified files are not checked in git push will fail.
|
|
153
162
|
> npm run release
|
|
154
163
|
```
|
|
155
164
|
|
package/dist/analytics.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function initAnalyticsSession(e,t,n,
|
|
2
|
-
typically means that you may be sending too many value events? .`),
|
|
3
|
-
postIntervalSeconds:${
|
|
1
|
+
function initAnalyticsSession(e,t,n,o,a){let i,r,s,l,u,c,d,f,y={};const g="aicore.analytics.userID",v="aicore.analytics.sessionID",p=1e4;let m=null;var w,h,b,C="undefined"==typeof window;let I="https://analytics.core.ai",S,D,E=0,T=!1;function U(...e){window.analytics.debugMode&&console.log("analytics client: ",...e)}function A(...e){window.analytics.debugMode&&console.error("analytics client: ",...e)}if(C)throw new Error("Node environment is not currently supported");function N(){return{schemaVersion:1,accountID:i,appName:r,uuid:s,sessionID:l,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function $(){if(!m)throw new Error("Please call initSession before using any analytics event")}function k(e){e.backoffCount=(e.backoffCount||0)+1,U(`Failed to call core analytics server. Will retry in ${30*e.backoffCount}s: `),setTimeout(()=>{L(e)},3e4*e.backoffCount)}function B(t){var e,n=JSON.stringify(t);n.length>p&&console.warn(`Analytics event generated is very large at greater than ${n.length}B. This
|
|
2
|
+
typically means that you may be sending too many value events? .`),U("Sending Analytics data of length: ",n.length,"B"),e=["Sending data:",n],window.analytics.debugMode&&window.analytics.debugInfoLogsEnable&&console.info("analytics client: ",...e),window.navigator.onLine?window.fetch(f,{method:"POST",headers:{"Content-Type":"application/json"},body:n}).then(e=>{200!==e.status&&(400!==e.status?k(t):console.error("Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{A(e),k(t)}):k(t)}function L(e){T||(e||(e=m,E=0,R(),m=N()),0!==e.numEventsTotal&&B(e))}function R(e){S&&(clearInterval(S),S=null),e||(S=setInterval(()=>{E+=c},1e3*c))}function M(e){R(e),D&&(clearInterval(D),D=null),e||(D=setInterval(L,1e3*u))}function _(n,o,a,i=1,r=0){if(!T){var s=n,l=o,u=a,c=i,d=r;if($(),!s||!l||!u)throw new Error("missing eventType or category or subCategory");if("number"!=typeof c||c<0)throw new Error("invalid count, count should be a positive number");if("number"!=typeof d)throw new Error("invalid value, value should be a number");{s=n;l=o;u=a;let e=m.events;e[s]=e[s]||{},e[s][l]=e[s][l]||{},e[s][l][u]=e[s][l][u]||{time:[],valueCount:[]}}let t=m.events;c=t[n][o][a].time;if((0<c.length?c[c.length-1]:null)===E){d=t[n][o][a].valueCount.length-1;{var s=d,l=n,u=o,c=a,d=i,f=r;let t=m.events;var e="number"==typeof t[l][u][c].valueCount[s];if(e&&0===f)t[l][u][c].valueCount[s]+=d;else if(e&&0!==f){let e={};e[f]=d,e[0]=t[l][u][c].valueCount[s],t[l][u][c].valueCount[s]=e}else if(!e){let e=t[l][u][c].valueCount[s];e[f]=(e[f]||0)+d}m.numEventsTotal+=1}}else{if(t[n][o][a].time.push(E),0===r)t[n][o][a].valueCount.push(i);else{let e={};e[r]=i,t[n][o][a].valueCount.push(e)}m.numEventsTotal+=1}}}if(!e||!t)throw new Error("accountID and appName must exist for init");d=n?n.toString().replace(/\/$/,""):I,i=e,r=t,u=o||60,c=a||3,f=d+"/ingest",s=function(){let e=localStorage.getItem(g);return e||(e=crypto.randomUUID(),localStorage.setItem(g,e)),e}(),l=function(){let e=sessionStorage.getItem(v);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(v,e)),e}(),m=N(),M(),w=o,h=a,new Promise(t=>{var e;window.navigator.onLine?(e=d+(`/getAppConfig?accountID=${i}&appName=`+r),window.fetch(e).then(e=>{switch(e.status){case 200:return void e.json().then(e=>{t(e)}).catch(e=>{A("remote response invalid. Continuing with defaults.",e),t({})});case 400:A("Bad Request, check library version compatible?",e),t({});break;default:A("Could not update from remote config. Continuing with defaults.",e),t({})}}).catch(e=>{A("Could not update from remote config. Continuing with defaults.",e),t({})})):t({})}).then(e=>{y!=={}&&(y=e,u=w||y.postIntervalSecondsInit||60,c=h||y.granularitySecInit||3,d=y.analyticsURLInit||d||I,M(T=!0===y.disabled),U(`Init analytics Config from remote. disabled: ${T}
|
|
3
|
+
postIntervalSeconds:${u}, granularitySec: ${c} ,URL: `+d),T&&console.warn(`Core Analytics is disabled from the server for app: ${i}:`+r))});for(b of analytics._initData)_(...b);analytics._initData=[],analytics._getCurrentAnalyticsEvent=function(){return $(),JSON.parse(JSON.stringify(m))},analytics._getAppConfig=function(){return{accountID:i,appName:r,disabled:T,uuid:s,sessionID:l,postIntervalSeconds:u,granularitySec:c,analyticsURL:d,serverConfig:y}},analytics.event=_}window.analytics||(window.analytics={_initData:[],debugMode:!1}),void 0===window.crypto&&(window.crypto={}),"randomUUID"in crypto||(crypto.randomUUID=function(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))});
|
|
4
4
|
//# sourceMappingURL=analytics.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sourceRoot":"src/analytics.js","sources":["src/analytics.js"],"names":["initAnalyticsSession","accountIDInit","appNameInit","analyticsURLInit","postIntervalSecondsInit","granularitySecInit","
|
|
1
|
+
{"version":3,"sourceRoot":"src/analytics.js","sources":["src/analytics.js"],"names":["initAnalyticsSession","accountIDInit","appNameInit","analyticsURLInit","postIntervalSecondsInit","granularitySecInit","let","accountID","appName","userID","sessionID","postIntervalSeconds","granularitySec","analyticsURL","postURL","serverConfig","USERID_LOCAL_STORAGE_KEY","SESSION_ID_LOCAL_STORAGE_KEY","POST_LARGE_DATA_THRESHOLD_BYTES","currentAnalyticsEvent","postIntervalSecondsInitial","granularitySecInitial","eventData","IS_NODE_ENV","window","DEFAULT_BASE_URL","granularityTimer","postTimer","currentQuantisedTime","disabled","debugLog","args","analytics","debugMode","console","log","debugError","error","Error","_createAnalyticsEvent","schemaVersion","uuid","unixTimestampUTC","Date","numEventsTotal","events","_validateCurrentState","_retryPost","eventToSend","backoffCount","setTimeout","_postCurrentAnalyticsEvent","DEFAULT_RETRY_TIME_IN_SECONDS","_postEventWithRetry","textToSend","JSON","stringify","length","warn","debugInfo","debugInfoLogsEnable","info","navigator","onLine","fetch","method","headers","Content-Type","body","then","res","status","catch","_resetGranularityTimer","disable","clearInterval","setInterval","_setupTimers","event","eventType","eventCategory","subCategory","eventCount","eventValue","_validateEvent","category","count","value","_ensureAnalyticsEventExists","time","valueCount","timeArray","modificationIndex","_updateExistingAnalyticsEvent","index","newValue","storedValueIsCount","newValueCount","storedValueObject","push","toString","replace","localUserID","localStorage","getItem","crypto","randomUUID","setItem","_getOrCreateUserID","localSessionID","sessionStorage","Math","random","substr","_getOrCreateSessionID","Promise","configURL","json","serverResponse","resolve","err","updatedServerConfig","_initData","_getCurrentAnalyticsEvent","parse","_getAppConfig","c","getRandomValues","Uint8Array"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/analytics.js
CHANGED
|
@@ -6,7 +6,24 @@
|
|
|
6
6
|
|
|
7
7
|
if(!window.analytics){
|
|
8
8
|
window.analytics = {
|
|
9
|
-
_initData: []
|
|
9
|
+
_initData: [],
|
|
10
|
+
debugMode: false
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (typeof window.crypto === 'undefined'){
|
|
15
|
+
window.crypto = {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!('randomUUID' in crypto)){
|
|
19
|
+
// https://stackoverflow.com/a/2117523/2800218
|
|
20
|
+
// LICENSE: https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
21
|
+
crypto.randomUUID = function randomUUID() {
|
|
22
|
+
return (
|
|
23
|
+
[1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,
|
|
24
|
+
// eslint-disable-next-line no-bitwise
|
|
25
|
+
c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
26
|
+
);
|
|
10
27
|
};
|
|
11
28
|
}
|
|
12
29
|
|
|
@@ -14,21 +31,20 @@ if(!window.analytics){
|
|
|
14
31
|
* Initialize the analytics session
|
|
15
32
|
* @param accountIDInit Your analytics account id as configured in the server or core.ai analytics
|
|
16
33
|
* @param appNameInit The app name to log the events against.
|
|
17
|
-
* @param analyticsURLInit Optional: Provide your own analytics server address if you self-hosted the server
|
|
34
|
+
* @param analyticsURLInit Optional: Provide your own analytics server address if you self-hosted the server.
|
|
18
35
|
* @param postIntervalSecondsInit Optional: This defines the interval between sending analytics events to the server.
|
|
19
|
-
* Default is
|
|
36
|
+
* Default is 1 minutes or server controlled.
|
|
20
37
|
* @param granularitySecInit Optional: The smallest time period under which the events can be distinguished. Multiple
|
|
21
|
-
* events happening during this time period is aggregated to a count. The default granularity is 3 Seconds
|
|
22
|
-
* that any events that happen within 3 seconds cannot be distinguished in ordering.
|
|
23
|
-
* @param debug set to true if you want to see detailed debug logs.
|
|
38
|
+
* events happening during this time period is aggregated to a count. The default granularity is 3 Seconds or server
|
|
39
|
+
* controlled, which means that any events that happen within 3 seconds cannot be distinguished in ordering.
|
|
24
40
|
*/
|
|
25
41
|
function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
26
|
-
postIntervalSecondsInit, granularitySecInit
|
|
42
|
+
postIntervalSecondsInit, granularitySecInit) {
|
|
27
43
|
let accountID, appName, userID, sessionID, postIntervalSeconds,
|
|
28
44
|
granularitySec, analyticsURL, postURL, serverConfig={};
|
|
29
45
|
const DEFAULT_GRANULARITY_IN_SECONDS = 3;
|
|
30
46
|
const DEFAULT_RETRY_TIME_IN_SECONDS = 30;
|
|
31
|
-
const DEFAULT_POST_INTERVAL_SECONDS =
|
|
47
|
+
const DEFAULT_POST_INTERVAL_SECONDS = 60; // 1 minutes
|
|
32
48
|
const USERID_LOCAL_STORAGE_KEY = 'aicore.analytics.userID';
|
|
33
49
|
const SESSION_ID_LOCAL_STORAGE_KEY = 'aicore.analytics.sessionID';
|
|
34
50
|
const POST_LARGE_DATA_THRESHOLD_BYTES = 10000;
|
|
@@ -40,20 +56,25 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
40
56
|
let postTimer;
|
|
41
57
|
let currentQuantisedTime = 0;
|
|
42
58
|
let disabled = false;
|
|
43
|
-
let debugMode = false;
|
|
44
59
|
|
|
45
60
|
function debugLog(...args) {
|
|
46
|
-
if(!debugMode){
|
|
61
|
+
if(!window.analytics.debugMode){
|
|
47
62
|
return;
|
|
48
63
|
}
|
|
49
|
-
console.log(...args);
|
|
64
|
+
console.log("analytics client: ", ...args);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function debugInfo(...args) {
|
|
68
|
+
if(window.analytics.debugMode && window.analytics.debugInfoLogsEnable){
|
|
69
|
+
console.info("analytics client: ", ...args);
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
72
|
|
|
52
73
|
function debugError(...args) {
|
|
53
|
-
if(!debugMode){
|
|
74
|
+
if(!window.analytics.debugMode){
|
|
54
75
|
return;
|
|
55
76
|
}
|
|
56
|
-
console.error(...args);
|
|
77
|
+
console.error("analytics client: ", ...args);
|
|
57
78
|
}
|
|
58
79
|
|
|
59
80
|
|
|
@@ -118,25 +139,20 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
118
139
|
}, DEFAULT_RETRY_TIME_IN_SECONDS * 1000 * eventToSend.backoffCount);
|
|
119
140
|
}
|
|
120
141
|
|
|
121
|
-
function
|
|
122
|
-
if(disabled){
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if(!eventToSend){
|
|
126
|
-
eventToSend = currentAnalyticsEvent;
|
|
127
|
-
currentQuantisedTime = 0;
|
|
128
|
-
_resetGranularityTimer();
|
|
129
|
-
currentAnalyticsEvent = _createAnalyticsEvent();
|
|
130
|
-
}
|
|
131
|
-
if(eventToSend.numEventsTotal === 0 ){
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
142
|
+
function _postEventWithRetry(eventToSend) {
|
|
134
143
|
let textToSend = JSON.stringify(eventToSend);
|
|
135
144
|
if(textToSend.length > POST_LARGE_DATA_THRESHOLD_BYTES){
|
|
136
145
|
console.warn(`Analytics event generated is very large at greater than ${textToSend.length}B. This
|
|
137
146
|
typically means that you may be sending too many value events? .`);
|
|
138
147
|
}
|
|
139
148
|
debugLog("Sending Analytics data of length: ", textToSend.length, "B");
|
|
149
|
+
debugInfo("Sending data:", textToSend);
|
|
150
|
+
if(!window.navigator.onLine){
|
|
151
|
+
_retryPost(eventToSend);
|
|
152
|
+
// chrome shows all network failure requests in console. In offline mode, we don't want to bomb debug
|
|
153
|
+
// console with network failure messages for analytics. So we prevent network requests when offline.
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
140
156
|
window.fetch(postURL, {
|
|
141
157
|
method: "POST",
|
|
142
158
|
headers: {'Content-Type': 'application/json'},
|
|
@@ -148,8 +164,7 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
148
164
|
if(res.status !== 400){ // we don't retry bad requests
|
|
149
165
|
_retryPost(eventToSend);
|
|
150
166
|
} else {
|
|
151
|
-
console.error("
|
|
152
|
-
"Bad Request, this is most likely a problem with the library, update to latest version.");
|
|
167
|
+
console.error("Bad Request, this is most likely a problem with the library, update to latest version.");
|
|
153
168
|
}
|
|
154
169
|
}).catch(res => {
|
|
155
170
|
debugError(res);
|
|
@@ -157,6 +172,22 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
157
172
|
});
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
function _postCurrentAnalyticsEvent(eventToSend) {
|
|
176
|
+
if(disabled){
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if(!eventToSend){
|
|
180
|
+
eventToSend = currentAnalyticsEvent;
|
|
181
|
+
currentQuantisedTime = 0;
|
|
182
|
+
_resetGranularityTimer();
|
|
183
|
+
currentAnalyticsEvent = _createAnalyticsEvent();
|
|
184
|
+
}
|
|
185
|
+
if(eventToSend.numEventsTotal === 0 ){
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
_postEventWithRetry(eventToSend);
|
|
189
|
+
}
|
|
190
|
+
|
|
160
191
|
function _resetGranularityTimer(disable) {
|
|
161
192
|
if(granularityTimer){
|
|
162
193
|
clearInterval(granularityTimer);
|
|
@@ -182,23 +213,36 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
182
213
|
postTimer = setInterval(_postCurrentAnalyticsEvent, postIntervalSeconds*1000);
|
|
183
214
|
}
|
|
184
215
|
|
|
185
|
-
|
|
186
|
-
return new Promise((resolve
|
|
216
|
+
function _getServerConfig() {
|
|
217
|
+
return new Promise((resolve)=>{
|
|
218
|
+
if(!window.navigator.onLine){
|
|
219
|
+
resolve({});
|
|
220
|
+
// chrome shows all network failure requests in console. In offline mode, we don't want to bomb debug
|
|
221
|
+
// console with network failure messages for analytics. So we prevent network requests when offline.
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
187
224
|
let configURL = analyticsURL + `/getAppConfig?accountID=${accountID}&appName=${appName}`;
|
|
188
|
-
window.fetch(configURL).then(
|
|
225
|
+
window.fetch(configURL).then(res=>{
|
|
189
226
|
switch (res.status) {
|
|
190
227
|
case 200:
|
|
191
|
-
|
|
192
|
-
|
|
228
|
+
res.json().then(serverResponse =>{
|
|
229
|
+
resolve(serverResponse);
|
|
230
|
+
}).catch(err => {
|
|
231
|
+
debugError("remote response invalid. Continuing with defaults.", err);
|
|
232
|
+
resolve({});
|
|
233
|
+
});
|
|
193
234
|
return;
|
|
194
235
|
case 400:
|
|
195
|
-
|
|
236
|
+
debugError("Bad Request, check library version compatible?", res);
|
|
237
|
+
resolve({});
|
|
196
238
|
break;
|
|
197
239
|
default:
|
|
198
|
-
|
|
240
|
+
debugError("Could not update from remote config. Continuing with defaults.", res);
|
|
241
|
+
resolve({});
|
|
199
242
|
}
|
|
200
243
|
}).catch(err => {
|
|
201
|
-
|
|
244
|
+
debugError("Could not update from remote config. Continuing with defaults.", err);
|
|
245
|
+
resolve({});
|
|
202
246
|
});
|
|
203
247
|
});
|
|
204
248
|
}
|
|
@@ -215,27 +259,29 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
215
259
|
};
|
|
216
260
|
}
|
|
217
261
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
262
|
+
function _initFromRemoteConfig(postIntervalSecondsInitial, granularitySecInitial) {
|
|
263
|
+
_getServerConfig().then(updatedServerConfig =>{
|
|
264
|
+
if(serverConfig !== {}){
|
|
265
|
+
serverConfig = updatedServerConfig;
|
|
266
|
+
// User init overrides takes precedence over server overrides
|
|
267
|
+
postIntervalSeconds = postIntervalSecondsInitial ||
|
|
268
|
+
serverConfig["postIntervalSecondsInit"] || DEFAULT_POST_INTERVAL_SECONDS;
|
|
269
|
+
granularitySec = granularitySecInitial || serverConfig["granularitySecInit"] || DEFAULT_GRANULARITY_IN_SECONDS;
|
|
270
|
+
// For URLs, the server suggested URL takes precedence over user init values
|
|
271
|
+
analyticsURL = serverConfig["analyticsURLInit"] || analyticsURL || DEFAULT_BASE_URL;
|
|
272
|
+
disabled = serverConfig["disabled"] === true;
|
|
273
|
+
_setupTimers(disabled);
|
|
274
|
+
debugLog(`Init analytics Config from remote. disabled: ${disabled}
|
|
230
275
|
postIntervalSeconds:${postIntervalSeconds}, granularitySec: ${granularitySec} ,URL: ${analyticsURL}`);
|
|
231
|
-
|
|
232
|
-
|
|
276
|
+
if(disabled){
|
|
277
|
+
console.warn(`Core Analytics is disabled from the server for app: ${accountID}:${appName}`);
|
|
278
|
+
}
|
|
233
279
|
}
|
|
234
|
-
}
|
|
280
|
+
});
|
|
235
281
|
}
|
|
236
282
|
|
|
237
283
|
function _stripTrailingSlash(url) {
|
|
238
|
-
return url.replace(/\/$/, "");
|
|
284
|
+
return url.toString().replace(/\/$/, "");
|
|
239
285
|
}
|
|
240
286
|
|
|
241
287
|
function _ensureAnalyticsEventExists(eventType, category, subCategory) {
|
|
@@ -243,8 +289,10 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
243
289
|
events[eventType] = events[eventType] || {};
|
|
244
290
|
events[eventType][category] = events[eventType][category] || {};
|
|
245
291
|
events[eventType][category][subCategory] = events[eventType][category][subCategory] || {
|
|
246
|
-
|
|
247
|
-
|
|
292
|
+
// quantised time
|
|
293
|
+
time: [],
|
|
294
|
+
// value and count array, If a single value, then it is count, else object {"val1":count1, ...}
|
|
295
|
+
valueCount: []
|
|
248
296
|
};
|
|
249
297
|
}
|
|
250
298
|
|
|
@@ -319,7 +367,6 @@ function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit,
|
|
|
319
367
|
analyticsURL = analyticsURLInit? _stripTrailingSlash(analyticsURLInit) : DEFAULT_BASE_URL;
|
|
320
368
|
accountID = accountIDInit;
|
|
321
369
|
appName = appNameInit;
|
|
322
|
-
debugMode = debug || false;
|
|
323
370
|
postIntervalSeconds = postIntervalSecondsInit || DEFAULT_POST_INTERVAL_SECONDS;
|
|
324
371
|
granularitySec = granularitySecInit || DEFAULT_GRANULARITY_IN_SECONDS;
|
|
325
372
|
postURL = analyticsURL + "/ingest";
|