@aicore/core-analytics-client-lib
Advanced tools
Comparing version 1.0.7 to 1.0.8
@@ -1,4 +0,4 @@ | ||
function initAnalyticsSession(e,t,n,a,o,i){let s,r,l,u,c,f,y,v,d={};const m=30,p="aicore.analytics.userID",g="aicore.analytics.sessionID",h=1e4;let w=null;var C,b="undefined"==typeof window;let I="https://analytics.core.ai",S,D,E=0,T=!1,A=!1;function N(...e){A&&console.log(...e)}if(b)throw new Error("Node environment is not currently supported");function $(){return{schemaVersion:1,accountID:s,appName:r,uuid:l,sessionID:u,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function k(){if(!w)throw new Error("Please call initSession before using any analytics event")}function U(e){e.backoffCount=(e.backoffCount||0)+1,N(`Failed to call core analytics server. Will retry in ${m*e.backoffCount}s: `),setTimeout(()=>{R(e)},1e3*m*e.backoffCount)}function R(t){var e;T||(t||(t=w,E=0,_(),w=$()),0!==t.numEventsTotal&&((e=JSON.stringify(t)).length>h&&console.warn(`Analytics event generated is very large at greater than ${e.length}B. This | ||
typically means that you may be sending too many value events? .`),N("Sending Analytics data of length: ",e.length,"B"),window.fetch(v,{method:"POST",headers:{"Content-Type":"application/json"},body:e}).then(e=>{200!==e.status&&(400!==e.status?U(t):console.error("Analytics client: Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{e=[e],A&&console.error(...e),U(t)})))}function _(e){S&&(clearInterval(S),S=null),e||(S=setInterval(()=>{E+=f},1e3*f))}function B(e){_(e),D&&(clearInterval(D),D=null),e||(D=setInterval(R,1e3*c))}function O(n,a,o,i=1,s=0){if(!T){var r=n,l=a,u=o,c=i,f=s;if(k(),!r||!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 f)throw new Error("invalid value, value should be a number");{r=n;l=a;u=o;let e=w.events;e[r]=e[r]||{},e[r][l]=e[r][l]||{},e[r][l][u]=e[r][l][u]||{time:[],valueCount:[]}}let t=w.events;c=t[n][a][o].time;if((0<c.length?c[c.length-1]:null)===E){f=t[n][a][o].valueCount.length-1;{var r=f,l=n,u=a,c=o,f=i,y=s;let t=w.events;var e="number"==typeof t[l][u][c].valueCount[r];if(e&&0===y)t[l][u][c].valueCount[r]+=f;else if(e&&0!==y){let e={};e[y]=f,e[0]=t[l][u][c].valueCount[r],t[l][u][c].valueCount[r]=e}else if(!e){let e=t[l][u][c].valueCount[r];e[y]=(e[y]||0)+f}w.numEventsTotal+=1}}else{if(t[n][a][o].time.push(E),0===s)t[n][a][o].valueCount.push(i);else{let e={};e[s]=i,t[n][a][o].valueCount.push(e)}w.numEventsTotal+=1}}}if(!e||!t)throw new Error("accountID and appName must exist for init");y=n?n.replace(/\/$/,""):I,s=e,r=t,A=i||!1,c=a||600,f=o||3,v=y+"/ingest",l=function(){let e=localStorage.getItem(p);return e||(e=crypto.randomUUID(),localStorage.setItem(p,e)),e}(),u=function(){let e=sessionStorage.getItem(g);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(g,e)),e}(),w=$(),B(),async function(e,t){(d=await new Promise((n,a)=>{var e=y+(`/getAppConfig?accountID=${s}&appName=`+r);window.fetch(e).then(async e=>{switch(e.status){case 200:var t=await e.json();return void n(t);case 400:a("Bad Request, check library version compatible?",e);break;default:a("analytics client: Could not update from remote config. Continuing with defaults.",e)}}).catch(e=>{a("analytics client: Could not update from remote config. Continuing with defaults.",e)})}))!=={}&&(c=e||d.postIntervalSecondsInit||600,f=t||d.granularitySecInit||3,y=d.analyticsURLInit||y||I,B(T=!0===d.disabled),N(`Init analytics Config from remote. disabled: ${T} | ||
postIntervalSeconds:${c}, granularitySec: ${f} ,URL: `+y),T&&console.warn(`Core Analytics is disabled from the server for app: ${s}:`+r))}(a,o);for(C of analytics._initData)O(...C);analytics._initData=[],analytics._getCurrentAnalyticsEvent=function(){return k(),JSON.parse(JSON.stringify(w))},analytics._getAppConfig=function(){return{accountID:s,appName:r,disabled:T,uuid:l,sessionID:u,postIntervalSeconds:c,granularitySec:f,analyticsURL:y,serverConfig:d}},analytics.event=O}window.analytics||(window.analytics={_initData:[]}); | ||
function initAnalyticsSession(e,t,n,a,o,i){let s,r,l,u,c,f,d,v,y={};const g="aicore.analytics.userID",m="aicore.analytics.sessionID",p=1e4;let h=null;var w,b="undefined"==typeof window;let C="https://analytics.core.ai",I,S,D=0,E=!1,T=!1;function N(...e){T&&console.log("analytics client: ",...e)}function $(...e){T&&console.error("analytics client: ",...e)}if(b)throw new Error("Node environment is not currently supported");function k(){return{schemaVersion:1,accountID:s,appName:r,uuid:l,sessionID:u,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function A(){if(!h)throw new Error("Please call initSession before using any analytics event")}function L(e){e.backoffCount=(e.backoffCount||0)+1,N(`Failed to call core analytics server. Will retry in ${30*e.backoffCount}s: `),setTimeout(()=>{U(e)},3e4*e.backoffCount)}function O(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 | ||
typically means that you may be sending too many value events? .`),N("Sending Analytics data of length: ",n.length,"B"),e=["Sending data:",n],T&&window.analytics.debugInfoLogsEnable&&console.info("analytics client: ",...e),window.navigator.onLine?window.fetch(v,{method:"POST",headers:{"Content-Type":"application/json"},body:n}).then(e=>{200!==e.status&&(400!==e.status?L(t):console.error("Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{$(e),L(t)}):L(t)}function U(e){E||(e||(e=h,D=0,R(),h=k()),0!==e.numEventsTotal&&O(e))}function R(e){I&&(clearInterval(I),I=null),e||(I=setInterval(()=>{D+=f},1e3*f))}function _(e){R(e),S&&(clearInterval(S),S=null),e||(S=setInterval(U,1e3*c))}function B(n,a,o,i=1,s=0){if(!E){var r=n,l=a,u=o,c=i,f=s;if(A(),!r||!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 f)throw new Error("invalid value, value should be a number");{r=n;l=a;u=o;let e=h.events;e[r]=e[r]||{},e[r][l]=e[r][l]||{},e[r][l][u]=e[r][l][u]||{time:[],valueCount:[]}}let t=h.events;c=t[n][a][o].time;if((0<c.length?c[c.length-1]:null)===D){f=t[n][a][o].valueCount.length-1;{var r=f,l=n,u=a,c=o,f=i,d=s;let t=h.events;var e="number"==typeof t[l][u][c].valueCount[r];if(e&&0===d)t[l][u][c].valueCount[r]+=f;else if(e&&0!==d){let e={};e[d]=f,e[0]=t[l][u][c].valueCount[r],t[l][u][c].valueCount[r]=e}else if(!e){let e=t[l][u][c].valueCount[r];e[d]=(e[d]||0)+f}h.numEventsTotal+=1}}else{if(t[n][a][o].time.push(D),0===s)t[n][a][o].valueCount.push(i);else{let e={};e[s]=i,t[n][a][o].valueCount.push(e)}h.numEventsTotal+=1}}}if(!e||!t)throw new Error("accountID and appName must exist for init");d=n?n.replace(/\/$/,""):C,s=e,r=t,T=i||!1,c=a||60,f=o||3,v=d+"/ingest",l=function(){let e=localStorage.getItem(g);return e||(e=crypto.randomUUID(),localStorage.setItem(g,e)),e}(),u=function(){let e=sessionStorage.getItem(m);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(m,e)),e}(),h=k(),_(),async function(e,t){(y=await new Promise(n=>{var e;window.navigator.onLine?(e=d+(`/getAppConfig?accountID=${s}&appName=`+r),window.fetch(e).then(async e=>{switch(e.status){case 200:var t=await e.json();return void n(t);case 400:$("Bad Request, check library version compatible?",e),n({});break;default:$("Could not update from remote config. Continuing with defaults.",e),n({})}}).catch(e=>{$("Could not update from remote config. Continuing with defaults.",e),n({})})):n({})}))!=={}&&(c=e||y.postIntervalSecondsInit||60,f=t||y.granularitySecInit||3,d=y.analyticsURLInit||d||C,_(E=!0===y.disabled),N(`Init analytics Config from remote. disabled: ${E} | ||
postIntervalSeconds:${c}, granularitySec: ${f} ,URL: `+d),E&&console.warn(`Core Analytics is disabled from the server for app: ${s}:`+r))}(a,o);for(w of analytics._initData)B(...w);analytics._initData=[],analytics._getCurrentAnalyticsEvent=function(){return A(),JSON.parse(JSON.stringify(h))},analytics._getAppConfig=function(){return{accountID:s,appName:r,disabled:E,uuid:l,sessionID:u,postIntervalSeconds:c,granularitySec:f,analyticsURL:d,serverConfig:y}},analytics.event=B}window.analytics||(window.analytics={_initData:[]}); | ||
//# sourceMappingURL=analytics.min.js.map |
{ | ||
"name": "@aicore/core-analytics-client-lib", | ||
"version": "1.0.7", | ||
"version": "1.0.8", | ||
"description": "Analytics client library for https://github.com/aicore/Core-Analytics-Server", | ||
@@ -5,0 +5,0 @@ "main": "dist/analytics.min.js", |
@@ -116,10 +116,10 @@ # Core Analytics Client Lib - JS | ||
* `appName`: The app name to log the events against. Eg: "phoenixCode" | ||
* `postIntervalSeconds` (_Optional_): This defines the interval between sending analytics events to the server. Default is 10 minutes | ||
* `analyticsURL` (_Optional_): Provide your own analytics server address if you self-hosted the server. | ||
* `postIntervalSeconds` (_Optional_): This defines the interval between sending analytics events to the server. Default is 1 minutes or server controlled. | ||
* `granularitySec` (_Optional_): The smallest time period under which the events can be distinguished. Multiple | ||
events happening during this time period is aggregated to a count. The default granularity is 3 Seconds, which means | ||
that any events that happen within 3 seconds cannot be distinguished in ordering. | ||
* `analyticsURL` (_Optional_): Provide your own analytics server address if you self-hosted the server | ||
events happening during this time period is aggregated to a count. The default granularity is 3 Seconds or server controlled, | ||
which means that any events that happen within 3 seconds cannot be distinguished in ordering. | ||
* `debug` (_Optional_): set to true if you want to see detailed debug logs. | ||
### usageExample | ||
#### usageExample | ||
```javascript | ||
@@ -138,3 +138,7 @@ // Init with default values and server controlled config. use the following `analyticsLibLoaded` function | ||
initAnalyticsSession("accountID", "appName", "https://localhost:3000", 600, 5); | ||
``` | ||
### Debug logs | ||
If you want to see detailed logs on what is happening inside analytics lib, use the below code: | ||
```js | ||
// To initSession in debug mode set debug arg in init to true. In debug mode, details logs | ||
@@ -145,2 +149,8 @@ // about analytics library events will be emitted. | ||
To see info level logs that shows actual analytics data being sent to server, set the below property: | ||
```js | ||
window.analytics.debugInfoLogsEnable = true; | ||
``` | ||
# Contribute to core-analytics-client-lib | ||
@@ -147,0 +157,0 @@ |
@@ -17,8 +17,8 @@ // GNU AGPL-3.0 License Copyright (c) 2021 - present core.ai . All rights reserved. | ||
* @param appNameInit The app name to log the events against. | ||
* @param analyticsURLInit Optional: Provide your own analytics server address if you self-hosted the server | ||
* @param analyticsURLInit Optional: Provide your own analytics server address if you self-hosted the server. | ||
* @param postIntervalSecondsInit Optional: This defines the interval between sending analytics events to the server. | ||
* Default is 10 minutes | ||
* Default is 1 minutes or server controlled. | ||
* @param granularitySecInit Optional: The smallest time period under which the events can be distinguished. Multiple | ||
* events happening during this time period is aggregated to a count. The default granularity is 3 Seconds, which means | ||
* that any events that happen within 3 seconds cannot be distinguished in ordering. | ||
* events happening during this time period is aggregated to a count. The default granularity is 3 Seconds or server | ||
* controlled, which means that any events that happen within 3 seconds cannot be distinguished in ordering. | ||
* @param debug set to true if you want to see detailed debug logs. | ||
@@ -32,3 +32,3 @@ */ | ||
const DEFAULT_RETRY_TIME_IN_SECONDS = 30; | ||
const DEFAULT_POST_INTERVAL_SECONDS = 600; // 10 minutes | ||
const DEFAULT_POST_INTERVAL_SECONDS = 60; // 1 minutes | ||
const USERID_LOCAL_STORAGE_KEY = 'aicore.analytics.userID'; | ||
@@ -51,5 +51,11 @@ const SESSION_ID_LOCAL_STORAGE_KEY = 'aicore.analytics.sessionID'; | ||
} | ||
console.log(...args); | ||
console.log("analytics client: ", ...args); | ||
} | ||
function debugInfo(...args) { | ||
if(debugMode && window.analytics.debugInfoLogsEnable){ | ||
console.info("analytics client: ", ...args); | ||
} | ||
} | ||
function debugError(...args) { | ||
@@ -59,3 +65,3 @@ if(!debugMode){ | ||
} | ||
console.error(...args); | ||
console.error("analytics client: ", ...args); | ||
} | ||
@@ -125,15 +131,3 @@ | ||
function _postCurrentAnalyticsEvent(eventToSend) { | ||
if(disabled){ | ||
return; | ||
} | ||
if(!eventToSend){ | ||
eventToSend = currentAnalyticsEvent; | ||
currentQuantisedTime = 0; | ||
_resetGranularityTimer(); | ||
currentAnalyticsEvent = _createAnalyticsEvent(); | ||
} | ||
if(eventToSend.numEventsTotal === 0 ){ | ||
return; | ||
} | ||
function _postEventWithRetry(eventToSend) { | ||
let textToSend = JSON.stringify(eventToSend); | ||
@@ -145,2 +139,9 @@ if(textToSend.length > POST_LARGE_DATA_THRESHOLD_BYTES){ | ||
debugLog("Sending Analytics data of length: ", textToSend.length, "B"); | ||
debugInfo("Sending data:", textToSend); | ||
if(!window.navigator.onLine){ | ||
_retryPost(eventToSend); | ||
// chrome shows all network failure requests in console. In offline mode, we don't want to bomb debug | ||
// console with network failure messages for analytics. So we prevent network requests when offline. | ||
return; | ||
} | ||
window.fetch(postURL, { | ||
@@ -157,4 +158,3 @@ method: "POST", | ||
} else { | ||
console.error("Analytics client: " + | ||
"Bad Request, this is most likely a problem with the library, update to latest version."); | ||
console.error("Bad Request, this is most likely a problem with the library, update to latest version."); | ||
} | ||
@@ -167,2 +167,18 @@ }).catch(res => { | ||
function _postCurrentAnalyticsEvent(eventToSend) { | ||
if(disabled){ | ||
return; | ||
} | ||
if(!eventToSend){ | ||
eventToSend = currentAnalyticsEvent; | ||
currentQuantisedTime = 0; | ||
_resetGranularityTimer(); | ||
currentAnalyticsEvent = _createAnalyticsEvent(); | ||
} | ||
if(eventToSend.numEventsTotal === 0 ){ | ||
return; | ||
} | ||
_postEventWithRetry(eventToSend); | ||
} | ||
function _resetGranularityTimer(disable) { | ||
@@ -194,3 +210,9 @@ if(granularityTimer){ | ||
async function _getServerConfig() { | ||
return new Promise((resolve, reject)=>{ | ||
return new Promise((resolve)=>{ | ||
if(!window.navigator.onLine){ | ||
resolve({}); | ||
// chrome shows all network failure requests in console. In offline mode, we don't want to bomb debug | ||
// console with network failure messages for analytics. So we prevent network requests when offline. | ||
return; | ||
} | ||
let configURL = analyticsURL + `/getAppConfig?accountID=${accountID}&appName=${appName}`; | ||
@@ -204,9 +226,12 @@ window.fetch(configURL).then(async res=>{ | ||
case 400: | ||
reject("Bad Request, check library version compatible?", res); | ||
debugError("Bad Request, check library version compatible?", res); | ||
resolve({}); | ||
break; | ||
default: | ||
reject("analytics client: Could not update from remote config. Continuing with defaults.", res); | ||
debugError("Could not update from remote config. Continuing with defaults.", res); | ||
resolve({}); | ||
} | ||
}).catch(err => { | ||
reject("analytics client: Could not update from remote config. Continuing with defaults.", err); | ||
debugError("Could not update from remote config. Continuing with defaults.", err); | ||
resolve({}); | ||
}); | ||
@@ -213,0 +238,0 @@ }); |
Sorry, the diff of this file is not supported yet
76170
355
209