@aicore/core-analytics-client-lib
Advanced tools
Comparing version 1.0.5 to 1.0.6
@@ -1,4 +0,4 @@ | ||
var analytics={};function init(){let r,s,e,t,l,u,c,f,n;const v=3,a=30,y=600,o="aicore.analytics.userID",i=1e4;let d=null;var m="undefined"==typeof window;let g="https://analytics.core.ai",p,h,w=0,C=!1,I=!1;function b(...e){I&&console.log(...e)}if(m)throw new Error("Node environment is not currently supported");function S(){return{schemaVersion:1,accountID:r,appName:s,uuid:e,sessionID:t,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function E(){if(!d)throw new Error("Please call initSession before using any analytics event")}function T(){e=function(){let e=localStorage.getItem(o);return e||(e=crypto.randomUUID(),localStorage.setItem(o,e)),e}(),t=function(){let e=sessionStorage.getItem(o);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(o,e)),e}()}function D(e){e.backoffCount=(e.backoffCount||0)+1,b(`Failed to call core analytics server. Will retry in ${a*e.backoffCount}s: `),setTimeout(()=>{N(e)},1e3*a*e.backoffCount)}function N(t){var e;C||(t||(t=d,w=0,$(),d=S()),0!==t.numEventsTotal&&((e=JSON.stringify(t)).length>i&&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? .`),b("Sending Analytics data of length: ",e.length,"B"),window.fetch(f,{method:"POST",headers:{"Content-Type":"application/json"},body:e}).then(e=>{200!==e.status&&(400!==e.status?D(t):console.error("Analytics client: Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{e=[e],I&&console.error(...e),D(t)})))}function $(e){p&&(clearInterval(p),p=null),e||(p=setInterval(()=>{w+=u},1e3*u))}function k(e){$(e),h&&(clearInterval(h),h=null),e||(h=setInterval(N,1e3*l))}async function A(e,t){(n=await new Promise((n,a)=>{var e=c+(`/getAppConfig?accountID=${r}&appName=`+s);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)})}))!=={}&&(l=e||n.postIntervalSecondsInit||y,u=t||n.granularitySecInit||v,c=n.analyticsURLInit||c||g,k(C=!0===n.disabled),b(`Init analytics Config from remote. disabled: ${C} | ||
postIntervalSeconds:${l}, granularitySec: ${u} ,URL: `+c),C&&console.warn(`Core Analytics is disabled from the server for app: ${r}:`+s))}analytics.initSession=function(e,t,n,a,o,i){if(!e||!t)throw new Error("accountID and appName must exist for init");c=n?n.replace(/\/$/,""):g,r=e,s=t,I=i||!1,l=a||y,u=o||v,f=c+"/ingest",T(),d=S(),k(),A(a,o)},analytics.getCurrentAnalyticsEvent=function(){return E(),JSON.parse(JSON.stringify(d))},analytics.event=function(n,a,o,i=1,r=0){if(!C){var s=n,l=a,u=o,c=i,f=r;if(E(),!s||!l||!u)throw new Error("missing eventType or category or subCategory");if("number"!=typeof c||c<0)throw new Error("invalid count");if("number"!=typeof f)throw new Error("invalid value");{s=n;l=a;u=o;let e=d.events;e[s]=e[s]||{},e[s][l]=e[s][l]||{},e[s][l][u]=e[s][l][u]||{time:[],valueCount:[]}}let t=d.events;c=t[n][a][o].time;if((0<c.length?c[c.length-1]:null)===w){f=t[n][a][o].valueCount.length-1;{var s=f,l=n,u=a,c=o,f=i,v=r;let t=d.events;var e="number"==typeof t[l][u][c].valueCount[s];if(e&&0===v)t[l][u][c].valueCount[s]+=f;else if(e&&0!==v){let e={};e[v]=f,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[v]=(e[v]||0)+f}d.numEventsTotal+=1}}else{if(t[n][a][o].time.push(w),0===r)t[n][a][o].valueCount.push(i);else{let e={};e[r]=i,t[n][a][o].valueCount.push(e)}d.numEventsTotal+=1}}},analytics.getAppConfig=function(){return{accountID:r,appName:s,disabled:C,uuid:e,sessionID:t,postIntervalSeconds:l,granularitySec:u,analyticsURL:c,serverConfig:n}}}init(); | ||
function initAnalyticsSession(e,t,n,a,o,i){let r,s,l,u,c,f,v,y,d={};const m=30,p="aicore.analytics.userID",g=1e4;let h=null;var w,C="undefined"==typeof window;let b="https://analytics.core.ai",I,S,D=0,E=!1,T=!1;function A(...e){T&&console.log(...e)}if(C)throw new Error("Node environment is not currently supported");function N(){return{schemaVersion:1,accountID:r,appName:s,uuid:l,sessionID:u,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function $(){if(!h)throw new Error("Please call initSession before using any analytics event")}function k(e){e.backoffCount=(e.backoffCount||0)+1,A(`Failed to call core analytics server. Will retry in ${m*e.backoffCount}s: `),setTimeout(()=>{U(e)},1e3*m*e.backoffCount)}function U(t){var e;E||(t||(t=h,D=0,R(),h=N()),0!==t.numEventsTotal&&((e=JSON.stringify(t)).length>g&&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? .`),A("Sending Analytics data of length: ",e.length,"B"),window.fetch(y,{method:"POST",headers:{"Content-Type":"application/json"},body:e}).then(e=>{200!==e.status&&(400!==e.status?k(t):console.error("Analytics client: Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{e=[e],T&&console.error(...e),k(t)})))}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,r=0){if(!E){var s=n,l=a,u=o,c=i,f=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 f)throw new Error("invalid value, value should be a number");{s=n;l=a;u=o;let e=h.events;e[s]=e[s]||{},e[s][l]=e[s][l]||{},e[s][l][u]=e[s][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 s=f,l=n,u=a,c=o,f=i,v=r;let t=h.events;var e="number"==typeof t[l][u][c].valueCount[s];if(e&&0===v)t[l][u][c].valueCount[s]+=f;else if(e&&0!==v){let e={};e[v]=f,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[v]=(e[v]||0)+f}h.numEventsTotal+=1}}else{if(t[n][a][o].time.push(D),0===r)t[n][a][o].valueCount.push(i);else{let e={};e[r]=i,t[n][a][o].valueCount.push(e)}h.numEventsTotal+=1}}}if(!e||!t)throw new Error("accountID and appName must exist for init");v=n?n.replace(/\/$/,""):b,r=e,s=t,T=i||!1,c=a||600,f=o||3,y=v+"/ingest",l=function(){let e=localStorage.getItem(p);return e||(e=crypto.randomUUID(),localStorage.setItem(p,e)),e}(),u=function(){let e=sessionStorage.getItem(p);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(p,e)),e}(),h=N(),_(),async function(e,t){(d=await new Promise((n,a)=>{var e=v+(`/getAppConfig?accountID=${r}&appName=`+s);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,v=d.analyticsURLInit||v||b,_(E=!0===d.disabled),A(`Init analytics Config from remote. disabled: ${E} | ||
postIntervalSeconds:${c}, granularitySec: ${f} ,URL: `+v),E&&console.warn(`Core Analytics is disabled from the server for app: ${r}:`+s))}(a,o);for(w of analytics._initData)B(...w);analytics._initData=[],analytics._getCurrentAnalyticsEvent=function(){return $(),JSON.parse(JSON.stringify(h))},analytics._getAppConfig=function(){return{accountID:r,appName:s,disabled:E,uuid:l,sessionID:u,postIntervalSeconds:c,granularitySec:f,analyticsURL:v,serverConfig:d}},analytics.event=B}window.analytics||(window.analytics={_initData:[]}); | ||
//# sourceMappingURL=analytics.min.js.map |
{ | ||
"name": "@aicore/core-analytics-client-lib", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "Analytics client library for https://github.com/aicore/Core-Analytics-Server", | ||
@@ -5,0 +5,0 @@ "main": "dist/analytics.min.js", |
@@ -23,37 +23,25 @@ # Core Analytics Client Lib - JS | ||
## Load the Library | ||
Embed the script in your HTML file : | ||
Embed the script in your HTML file and replace `your_analytics_account_ID` and `appName` | ||
in the `initAnalyticsSession` call below: | ||
```html | ||
<script src="https://unpkg.com/@aicore/core-analytics-client-lib/src/analytics.js"></script> | ||
<!-- Global window.analytics object - core.ai analytics services --> | ||
<script async src="https://unpkg.com/@aicore/core-analytics-client-lib/src/analytics.js" | ||
onload="analyticsLibLoaded()"></script> | ||
<script> | ||
if(!window.analytics){ window.analytics = { | ||
_initData : [], loadStartTime: new Date().getTime(), | ||
event: function (){window.analytics._initData.push(arguments);} | ||
};} | ||
function analyticsLibLoaded() { | ||
initAnalyticsSession('your_analytics_account_ID', 'appName'); | ||
analytics.event("core-analytics", "client-lib", "loadTime", 1, (new Date().getTime())-analytics.loadStartTime); | ||
} | ||
</script> | ||
``` | ||
This will create a global `analytics` variable which can be used to access the analytics APIs. | ||
## Initialize the analytics session. | ||
Call `analytics.initSession()` after loading the library. It takes the following parameters: | ||
* `accountID`: Your analytics account id as configured in the server or core.ai analytics | ||
* `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 | ||
* `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 | ||
* `debug` (_Optional_): set to true if you want to see detailed debug logs. | ||
### usageExample | ||
```javascript | ||
// Init with default values. | ||
analytics.initSession("accountID", "appName"); | ||
// Example for custom initSession where the analytics aggregated data | ||
// is posted to custom server https://localhost:3000 every 600 secs | ||
// with a granularity(resolution) of 5 seconds. | ||
analytics.initSession("accountID", "appName", "https://localhost:3000", 600, 5); | ||
// To initSession in debug mode set debug arg in init to true: | ||
analytics.initSession("accountID", "appName", "https://localhost:3000", 600, 5, true); | ||
``` | ||
## Raising analytics events | ||
Once `initSession` is called, we can now start logging analytics events by calling `analytics.event` API. | ||
The API registers an analytics event. The events will be aggregated and send to the analytics server periodically. | ||
We can now start logging analytics events by calling `analytics.event` API. | ||
The events will be aggregated and send to the analytics server periodically. | ||
@@ -83,5 +71,42 @@ ```javascript | ||
* `eventCount` (_Optional_) : A non-negative number indicating the number of times the event (or an event with a | ||
particular value if a value is specified) happened. defaults to 1. | ||
particular value if a value is specified) happened. defaults to 1. | ||
* `eventValue` (_Optional_) : A number value associated with the event. defaults to 0 | ||
## Advanced Usages | ||
If you want to modify how analytics library collects and sends information, it is recommended to do so | ||
with analytics server [accountConfig](https://github.com/aicore/Core-Analytics-Server#accountconfig-configuration). | ||
Alternatively for one off development time uses, the behavior of the library can be configured | ||
during the `initAnalyticsSession` call. `initAnalyticsSession()` takes the following parameters: | ||
* `accountID`: Your analytics account id as configured in the server or core.ai analytics | ||
* `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 | ||
* `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 | ||
* `debug` (_Optional_): set to true if you want to see detailed debug logs. | ||
### usageExample | ||
```javascript | ||
// Init with default values and server controlled config. use the following `analyticsLibLoaded` function | ||
function analyticsLibLoaded() { | ||
initAnalyticsSession('your_analytics_account_ID', 'appName'); | ||
analytics.event("core-analytics", "client-lib", "loadTime", 1, (new Date().getTime())-analytics.loadStartTime); | ||
} | ||
//Replace initAnalyticsSession in analyticsLibLoaded function for the below use cases. | ||
// Example for custom initSession where the analytics aggregated data | ||
// is posted to custom server https://localhost:3000 every 600 secs | ||
// with a granularity(resolution) of 5 seconds. | ||
initAnalyticsSession("accountID", "appName", "https://localhost:3000", 600, 5); | ||
// To initSession in debug mode set debug arg in init to true. In debug mode, details logs | ||
// about analytics library events will be emitted. | ||
initAnalyticsSession("accountID", "appName", "https://localhost:3000", 600, 5, true); | ||
``` | ||
# Contribute to core-analytics-client-lib | ||
@@ -88,0 +113,0 @@ |
// GNU AGPL-3.0 License Copyright (c) 2021 - present core.ai . All rights reserved. | ||
// jshint ignore: start | ||
/*global localStorage, sessionStorage, crypto*/ | ||
/*global localStorage, sessionStorage, crypto, analytics*/ | ||
var analytics = {}; | ||
function init() { | ||
let accountID, appName, userID, sessionID, postIntervalSeconds, granularitySec, analyticsURL, postURL, serverConfig; | ||
if(!window.analytics){ | ||
window.analytics = { | ||
_initData: [] | ||
}; | ||
} | ||
/** | ||
* Initialize the analytics session | ||
* @param accountIDInit Your analytics account id as configured in the server or core.ai analytics | ||
* @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 postIntervalSecondsInit Optional: This defines the interval between sending analytics events to the server. | ||
* Default is 10 minutes | ||
* @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. | ||
* @param debug set to true if you want to see detailed debug logs. | ||
*/ | ||
function initAnalyticsSession(accountIDInit, appNameInit, analyticsURLInit, | ||
postIntervalSecondsInit, granularitySecInit, debug) { | ||
let accountID, appName, userID, sessionID, postIntervalSeconds, | ||
granularitySec, analyticsURL, postURL, serverConfig={}; | ||
const DEFAULT_GRANULARITY_IN_SECONDS = 3; | ||
@@ -63,3 +82,3 @@ const DEFAULT_RETRY_TIME_IN_SECONDS = 30; | ||
function getCurrentAnalyticsEvent() { | ||
function _getCurrentAnalyticsEvent() { | ||
_validateCurrentState(); | ||
@@ -191,3 +210,3 @@ // return a clone | ||
*/ | ||
function getAppConfig() { | ||
function _getAppConfig() { | ||
return { | ||
@@ -200,9 +219,9 @@ accountID, appName, disabled, | ||
async function _initFromRemoteConfig(postIntervalSecondsInit, granularitySecInit) { | ||
async function _initFromRemoteConfig(postIntervalSecondsInitial, granularitySecInitial) { | ||
serverConfig = await _getServerConfig(); | ||
if(serverConfig !== {}){ | ||
// User init overrides takes precedence over server overrides | ||
postIntervalSeconds = postIntervalSecondsInit || | ||
postIntervalSeconds = postIntervalSecondsInitial || | ||
serverConfig["postIntervalSecondsInit"] || DEFAULT_POST_INTERVAL_SECONDS; | ||
granularitySec = granularitySecInit || serverConfig["granularitySecInit"] || DEFAULT_GRANULARITY_IN_SECONDS; | ||
granularitySec = granularitySecInitial || serverConfig["granularitySecInit"] || DEFAULT_GRANULARITY_IN_SECONDS; | ||
// For URLs, the server suggested URL takes precedence over user init values | ||
@@ -224,31 +243,2 @@ analyticsURL = serverConfig["analyticsURLInit"] || analyticsURL || DEFAULT_BASE_URL; | ||
/** | ||
* Initialize the analytics session | ||
* @param accountIDInit Your analytics account id as configured in the server or core.ai analytics | ||
* @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 postIntervalSecondsInit Optional: This defines the interval between sending analytics events to the server. | ||
* Default is 10 minutes | ||
* @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. | ||
* @param debug set to true if you want to see detailed debug logs. | ||
*/ | ||
function initSession(accountIDInit, appNameInit, analyticsURLInit, postIntervalSecondsInit, granularitySecInit, debug) { | ||
if(!accountIDInit || !appNameInit){ | ||
throw new Error("accountID and appName must exist for init"); | ||
} | ||
analyticsURL = analyticsURLInit? _stripTrailingSlash(analyticsURLInit) : DEFAULT_BASE_URL; | ||
accountID = accountIDInit; | ||
appName = appNameInit; | ||
debugMode = debug || false; | ||
postIntervalSeconds = postIntervalSecondsInit || DEFAULT_POST_INTERVAL_SECONDS; | ||
granularitySec = granularitySecInit || DEFAULT_GRANULARITY_IN_SECONDS; | ||
postURL = analyticsURL + "/ingest"; | ||
_setupIDs(); | ||
currentAnalyticsEvent = _createAnalyticsEvent(); | ||
_setupTimers(); | ||
_initFromRemoteConfig(postIntervalSecondsInit, granularitySecInit); | ||
} | ||
function _ensureAnalyticsEventExists(eventType, category, subCategory) { | ||
@@ -270,6 +260,6 @@ let events = currentAnalyticsEvent.events; | ||
if(typeof(count)!== 'number' || count <0){ | ||
throw new Error("invalid count"); | ||
throw new Error("invalid count, count should be a positive number"); | ||
} | ||
if(typeof(value)!== 'number'){ | ||
throw new Error("invalid value"); | ||
throw new Error("invalid value, value should be a number"); | ||
} | ||
@@ -329,8 +319,33 @@ } | ||
analytics.initSession = initSession; | ||
analytics.getCurrentAnalyticsEvent = getCurrentAnalyticsEvent; | ||
// Init Analytics | ||
if(!accountIDInit || !appNameInit){ | ||
throw new Error("accountID and appName must exist for init"); | ||
} | ||
analyticsURL = analyticsURLInit? _stripTrailingSlash(analyticsURLInit) : DEFAULT_BASE_URL; | ||
accountID = accountIDInit; | ||
appName = appNameInit; | ||
debugMode = debug || false; | ||
postIntervalSeconds = postIntervalSecondsInit || DEFAULT_POST_INTERVAL_SECONDS; | ||
granularitySec = granularitySecInit || DEFAULT_GRANULARITY_IN_SECONDS; | ||
postURL = analyticsURL + "/ingest"; | ||
_setupIDs(); | ||
currentAnalyticsEvent = _createAnalyticsEvent(); | ||
_setupTimers(); | ||
_initFromRemoteConfig(postIntervalSecondsInit, granularitySecInit); | ||
// As analytics lib load is async, our loading scripts will push event data into initData array till the lib load | ||
// is complete. Now as load is done, we need to push these pending analytics events. Assuming that the async load of | ||
// the lib should mostly happen under a second, we should not lose any accuracy of event times within the initial | ||
// 3-second granularity. For more precision use cases, load the lib sync. | ||
for(let eventData of analytics._initData){ | ||
event(...eventData); | ||
} | ||
analytics._initData = []; | ||
// Private API for tests | ||
analytics._getCurrentAnalyticsEvent = _getCurrentAnalyticsEvent; | ||
analytics._getAppConfig = _getAppConfig; | ||
// Public API | ||
analytics.event = event; | ||
analytics.getAppConfig = getAppConfig; | ||
} | ||
init(); |
Sorry, the diff of this file is not supported yet
72461
330
166