New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@aicore/core-analytics-client-lib

Package Overview
Dependencies
Maintainers
3
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aicore/core-analytics-client-lib - npm Package Compare versions

Comparing version 1.0.4 to 1.0.5

6

dist/analytics.min.js

@@ -1,4 +0,4 @@

let accountID,appName,userID,sessionID,postIntervalSeconds,granularitySec,analyticsURL,postURL,serverConfig;const DEFAULT_GRANULARITY_IN_SECONDS=3,DEFAULT_RETRY_TIME_IN_SECONDS=30,DEFAULT_POST_INTERVAL_SECONDS=600,USERID_LOCAL_STORAGE_KEY="aicore.analytics.userID",POST_LARGE_DATA_THRESHOLD_BYTES=1e4;let currentAnalyticsEvent=null;const IS_NODE_ENV="undefined"==typeof window;let DEFAULT_BASE_URL="https://analytics.core.ai",granularityTimer,postTimer,currentQuantisedTime=0,disabled=!1,debugMode=!1;function debugLog(...e){debugMode&&console.log(...e)}function debugError(...e){debugMode&&console.error(...e)}if(IS_NODE_ENV)throw new Error("Node environment is not currently supported");function _createAnalyticsEvent(){return{schemaVersion:1,accountID:accountID,appName:appName,uuid:userID,sessionID:sessionID,unixTimestampUTC:+new Date,numEventsTotal:0,events:{}}}function _validateCurrentState(){if(!currentAnalyticsEvent)throw new Error("Please call initSession before using any analytics event")}function getCurrentAnalyticsEvent(){return _validateCurrentState(),JSON.parse(JSON.stringify(currentAnalyticsEvent))}function _getOrCreateUserID(){let e=localStorage.getItem(USERID_LOCAL_STORAGE_KEY);return e||(e=crypto.randomUUID(),localStorage.setItem(USERID_LOCAL_STORAGE_KEY,e)),e}function _getOrCreateSessionID(){let e=sessionStorage.getItem(USERID_LOCAL_STORAGE_KEY);return e||(e=Math.random().toString(36).substr(2,10),sessionStorage.setItem(USERID_LOCAL_STORAGE_KEY,e)),e}function _setupIDs(){userID=_getOrCreateUserID(),sessionID=_getOrCreateSessionID()}function _retryPost(e){e.backoffCount=(e.backoffCount||0)+1,debugLog(`Failed to call core analytics server. Will retry in ${DEFAULT_RETRY_TIME_IN_SECONDS*e.backoffCount}s: `),setTimeout(()=>{_postCurrentAnalyticsEvent(e)},1e3*DEFAULT_RETRY_TIME_IN_SECONDS*e.backoffCount)}function _postCurrentAnalyticsEvent(t){var e;disabled||(t||(t=currentAnalyticsEvent,currentQuantisedTime=0,_resetGranularityTimer(),currentAnalyticsEvent=_createAnalyticsEvent()),0!==t.numEventsTotal&&((e=JSON.stringify(t)).length>POST_LARGE_DATA_THRESHOLD_BYTES&&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? .`),debugLog("Sending Analytics data of length: ",e.length,"B"),window.fetch(postURL,{method:"POST",headers:{"Content-Type":"application/json"},body:e}).then(e=>{200!==e.status&&(400!==e.status?_retryPost(t):console.error("Analytics client: Bad Request, this is most likely a problem with the library, update to latest version."))}).catch(e=>{debugError(e),_retryPost(t)})))}function _resetGranularityTimer(e){granularityTimer&&(clearInterval(granularityTimer),granularityTimer=null),e||(granularityTimer=setInterval(()=>{currentQuantisedTime+=granularitySec},1e3*granularitySec))}function _setupTimers(e){_resetGranularityTimer(e),postTimer&&(clearInterval(postTimer),postTimer=null),e||(postTimer=setInterval(_postCurrentAnalyticsEvent,1e3*postIntervalSeconds))}async function _getServerConfig(){return new Promise((n,r)=>{var e=analyticsURL+(`/getAppConfig?accountID=${accountID}&appName=`+appName);window.fetch(e).then(async e=>{switch(e.status){case 200:var t=await e.json();return void n(t);case 400:r("Bad Request, check library version compatible?",e);break;default:r("analytics client: Could not update from remote config. Continuing with defaults.",e)}}).catch(e=>{r("analytics client: Could not update from remote config. Continuing with defaults.",e)})})}function getAppConfig(){return{accountID:accountID,appName:appName,disabled:disabled,uuid:userID,sessionID:sessionID,postIntervalSeconds:postIntervalSeconds,granularitySec:granularitySec,analyticsURL:analyticsURL,serverConfig:serverConfig}}async function _initFromRemoteConfig(e,t){(serverConfig=await _getServerConfig())!=={}&&(postIntervalSeconds=e||serverConfig.postIntervalSecondsInit||DEFAULT_POST_INTERVAL_SECONDS,granularitySec=t||serverConfig.granularitySecInit||DEFAULT_GRANULARITY_IN_SECONDS,analyticsURL=serverConfig.analyticsURLInit||analyticsURL||DEFAULT_BASE_URL,_setupTimers(disabled=!0===serverConfig.disabled),debugLog(`Init analytics Config from remote. disabled: ${disabled}
postIntervalSeconds:${postIntervalSeconds}, granularitySec: ${granularitySec} ,URL: `+analyticsURL),disabled&&console.warn(`Core Analytics is disabled from the server for app: ${accountID}:`+appName))}function _stripTrailingSlash(e){return e.replace(/\/$/,"")}function initSession(e,t,n,r,a,i){if(!e||!t)throw new Error("accountID and appName must exist for init");analyticsURL=n?_stripTrailingSlash(n):DEFAULT_BASE_URL,accountID=e,appName=t,debugMode=i||!1,postIntervalSeconds=r||DEFAULT_POST_INTERVAL_SECONDS,granularitySec=a||DEFAULT_GRANULARITY_IN_SECONDS,postURL=analyticsURL+"/ingest",_setupIDs(),currentAnalyticsEvent=_createAnalyticsEvent(),_setupTimers(),_initFromRemoteConfig(r,a)}function _ensureAnalyticsEventExists(e,t,n){let r=currentAnalyticsEvent.events;r[e]=r[e]||{},r[e][t]=r[e][t]||{},r[e][t][n]=r[e][t][n]||{time:[],valueCount:[]}}function _validateEvent(e,t,n,r,a){if(_validateCurrentState(),!e||!t||!n)throw new Error("missing eventType or category or subCategory");if("number"!=typeof r||r<0)throw new Error("invalid count");if("number"!=typeof a)throw new Error("invalid value")}function _updateExistingAnalyticsEvent(t,n,r,a,i,s){let o=currentAnalyticsEvent.events;var e="number"==typeof o[n][r][a].valueCount[t];if(e&&0===s)o[n][r][a].valueCount[t]+=i;else if(e&&0!==s){let e={};e[s]=i,e[0]=o[n][r][a].valueCount[t],o[n][r][a].valueCount[t]=e}else if(!e){let e=o[n][r][a].valueCount[t];e[s]=(e[s]||0)+i}currentAnalyticsEvent.numEventsTotal+=1}function analyticsEvent(n,r,a,i=1,s=0){if(!disabled){_validateEvent(n,r,a,i,s),_ensureAnalyticsEventExists(n,r,a);let t=currentAnalyticsEvent.events;var e=t[n][r][a].time;if((0<e.length?e[e.length-1]:null)!==currentQuantisedTime){if(t[n][r][a].time.push(currentQuantisedTime),0===s)t[n][r][a].valueCount.push(i);else{let e={};e[s]=i,t[n][r][a].valueCount.push(e)}currentAnalyticsEvent.numEventsTotal+=1}else _updateExistingAnalyticsEvent(t[n][r][a].valueCount.length-1,n,r,a,i,s)}}export{initSession,getCurrentAnalyticsEvent,analyticsEvent,getAppConfig};
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();
//# sourceMappingURL=analytics.min.js.map
{
"name": "@aicore/core-analytics-client-lib",
"version": "1.0.4",
"version": "1.0.5",
"description": "Analytics client library for https://github.com/aicore/Core-Analytics-Server",

@@ -22,13 +22,14 @@ "main": "dist/analytics.min.js",

"prepare": "husky install",
"test": "echo please open test/index.html in browser to run tests",
"test:unit": "echo please open test/index.html in browser to run tests",
"test": "echo please run - npm run serve - and then open test/unit-test.html in browser to run tests",
"test:unit": "npm run test",
"test:integ": "echo integration tests are disabled in this repo",
"cover": "echo please open test/index.html in browser to run tests",
"cover:unit": "echo please open test/index.html in browser to run tests",
"cover:integ": "echo please open test/index.html in browser to run tests",
"build": "",
"cover": "echo no coverage for now",
"cover:unit": "echo no coverage for now",
"cover:integ": "echo no coverage for now",
"build": "npm run minify",
"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'\"",
"bumpPatchVersion": "npm --no-git-tag-version version patch",
"bumpPatchVersionWithGitTag": "npm version patch",
"release": "npm run minify && npm run bumpPatchVersionWithGitTag"
"release": "npm run minify && npm run bumpPatchVersionWithGitTag",
"serve": "http-server . -p 8000 -c-1"
},

@@ -57,4 +58,5 @@ "files": [

"mocha": "9.2.2",
"uglify-js": "3.15.5"
"uglify-js": "3.15.5",
"http-server": "14.1.0"
}
}

@@ -22,16 +22,11 @@ # Core Analytics Client Lib - JS

## Initialize the session
## Load the Library
Embed the script in your HTML file :
```html
<html lang="en">
<script type="module">
// For production use cases, use url: https://unpkg.com/@aicore/core-analytics-client-lib/dist/analytics.min.js
// The below url is for development purposes only.
import {initSession} from "https://unpkg.com/@aicore/core-analytics-client-lib/src/analytics.js";
initSession("accountID", "appName");
</script>
</html>
<script src="https://unpkg.com/@aicore/core-analytics-client-lib/src/analytics.js"></script>
```
This will create a global `analytics` variable which can be used to access the analytics APIs.
initSession(): Initialize the analytics session. It takes the following parameters:
## Initialize the analytics session.
Call `analytics.initSession()` after loading the library. It takes the following parameters:

@@ -47,15 +42,18 @@ * `accountID`: Your analytics account id as configured in the server or core.ai analytics

### 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);
initSession("accountID", "appName", "https://localhost:3000", 600, 5);
// To initSession in debug mode set debug arg in init to true:
initSession("accountID", "appName", "https://localhost:3000", 600, 5, 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 `analyticsEvent` API.
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.

@@ -67,15 +65,15 @@

// Eg: event without counts and values
analyticsEvent("platform", "os", "linux");
analytics.event("platform", "os", "linux");
// Eg: event with count, here it logs that html file is opened 100 times
analyticsEvent("file", "opened", "html", 100);
analytics.event("file", "opened", "html", 100);
// Eg: event with count and value, here it logs that the startup time is 250 milliseconds.
// Note that the value is unitless from analytics perspective. unit is deduced from subCategory name
analyticsEvent("platform", "performance", "startupTimeMs", 1, 250);
analytics.event("platform", "performance", "startupTimeMs", 1, 250);
// Eg: event with fractional value.
analyticsEvent("platform", "CPU", "utilization", 1, .45);
analytics.event("platform", "CPU", "utilization", 1, .45);
// Eg. Here we register that the system has 8 cores with each core having 2300MHz frequency.
analyticsEvent("platform", "CPU", "coreCountsAndFrequencyMhz", 8, 2300);
analytics.event("platform", "CPU", "coreCountsAndFrequencyMhz", 8, 2300);
```

@@ -82,0 +80,0 @@ ### API parameters

@@ -6,322 +6,326 @@ // GNU AGPL-3.0 License Copyright (c) 2021 - present core.ai . All rights reserved.

let accountID, appName, userID, sessionID, postIntervalSeconds, granularitySec, analyticsURL, postURL, serverConfig;
const DEFAULT_GRANULARITY_IN_SECONDS = 3;
const DEFAULT_RETRY_TIME_IN_SECONDS = 30;
const DEFAULT_POST_INTERVAL_SECONDS = 600; // 10 minutes
const USERID_LOCAL_STORAGE_KEY = 'aicore.analytics.userID';
const POST_LARGE_DATA_THRESHOLD_BYTES = 10000;
let currentAnalyticsEvent = null;
const IS_NODE_ENV = (typeof window === 'undefined');
let DEFAULT_BASE_URL = "https://analytics.core.ai";
var analytics = {};
let granularityTimer;
let postTimer;
let currentQuantisedTime = 0;
let disabled = false;
let debugMode = false;
function init() {
let accountID, appName, userID, sessionID, postIntervalSeconds, granularitySec, analyticsURL, postURL, serverConfig;
const DEFAULT_GRANULARITY_IN_SECONDS = 3;
const DEFAULT_RETRY_TIME_IN_SECONDS = 30;
const DEFAULT_POST_INTERVAL_SECONDS = 600; // 10 minutes
const USERID_LOCAL_STORAGE_KEY = 'aicore.analytics.userID';
const POST_LARGE_DATA_THRESHOLD_BYTES = 10000;
let currentAnalyticsEvent = null;
const IS_NODE_ENV = (typeof window === 'undefined');
let DEFAULT_BASE_URL = "https://analytics.core.ai";
function debugLog(...args) {
if(!debugMode){
return;
let granularityTimer;
let postTimer;
let currentQuantisedTime = 0;
let disabled = false;
let debugMode = false;
function debugLog(...args) {
if(!debugMode){
return;
}
console.log(...args);
}
console.log(...args);
}
function debugError(...args) {
if(!debugMode){
return;
function debugError(...args) {
if(!debugMode){
return;
}
console.error(...args);
}
console.error(...args);
}
if(IS_NODE_ENV){
throw new Error("Node environment is not currently supported");
}
if(IS_NODE_ENV){
throw new Error("Node environment is not currently supported");
}
function _createAnalyticsEvent() {
return {
schemaVersion: 1,
accountID: accountID,
appName: appName,
uuid: userID,
sessionID: sessionID,
unixTimestampUTC: +new Date(),
numEventsTotal: 0,
events: {}
};
}
function _createAnalyticsEvent() {
return {
schemaVersion: 1,
accountID: accountID,
appName: appName,
uuid: userID,
sessionID: sessionID,
unixTimestampUTC: +new Date(),
numEventsTotal: 0,
events: {}
};
}
function _validateCurrentState() {
if(!currentAnalyticsEvent){
throw new Error("Please call initSession before using any analytics event");
function _validateCurrentState() {
if(!currentAnalyticsEvent){
throw new Error("Please call initSession before using any analytics event");
}
}
}
function getCurrentAnalyticsEvent() {
_validateCurrentState();
// return a clone
return JSON.parse(JSON.stringify(currentAnalyticsEvent));
}
function getCurrentAnalyticsEvent() {
_validateCurrentState();
// return a clone
return JSON.parse(JSON.stringify(currentAnalyticsEvent));
}
function _getOrCreateUserID() {
let localUserID = localStorage.getItem(USERID_LOCAL_STORAGE_KEY);
if(!localUserID){
localUserID = crypto.randomUUID();
localStorage.setItem(USERID_LOCAL_STORAGE_KEY, localUserID);
function _getOrCreateUserID() {
let localUserID = localStorage.getItem(USERID_LOCAL_STORAGE_KEY);
if(!localUserID){
localUserID = crypto.randomUUID();
localStorage.setItem(USERID_LOCAL_STORAGE_KEY, localUserID);
}
return localUserID;
}
return localUserID;
}
function _getOrCreateSessionID() {
let localSessionID = sessionStorage.getItem(USERID_LOCAL_STORAGE_KEY);
if(!localSessionID){
localSessionID = Math.random().toString(36).substr(2, 10);
sessionStorage.setItem(USERID_LOCAL_STORAGE_KEY, localSessionID);
function _getOrCreateSessionID() {
let localSessionID = sessionStorage.getItem(USERID_LOCAL_STORAGE_KEY);
if(!localSessionID){
localSessionID = Math.random().toString(36).substr(2, 10);
sessionStorage.setItem(USERID_LOCAL_STORAGE_KEY, localSessionID);
}
return localSessionID;
}
return localSessionID;
}
function _setupIDs() {
userID = _getOrCreateUserID();
sessionID = _getOrCreateSessionID();
}
function _setupIDs() {
userID = _getOrCreateUserID();
sessionID = _getOrCreateSessionID();
}
function _retryPost(eventToSend) {
eventToSend.backoffCount = (eventToSend.backoffCount || 0) + 1;
debugLog(`Failed to call core analytics server. Will retry in ${
DEFAULT_RETRY_TIME_IN_SECONDS * eventToSend.backoffCount}s: `);
setTimeout(()=>{
_postCurrentAnalyticsEvent(eventToSend);
}, DEFAULT_RETRY_TIME_IN_SECONDS * 1000 * eventToSend.backoffCount);
}
function _retryPost(eventToSend) {
eventToSend.backoffCount = (eventToSend.backoffCount || 0) + 1;
debugLog(`Failed to call core analytics server. Will retry in ${
DEFAULT_RETRY_TIME_IN_SECONDS * eventToSend.backoffCount}s: `);
setTimeout(()=>{
_postCurrentAnalyticsEvent(eventToSend);
}, DEFAULT_RETRY_TIME_IN_SECONDS * 1000 * eventToSend.backoffCount);
}
function _postCurrentAnalyticsEvent(eventToSend) {
if(disabled){
return;
}
if(!eventToSend){
eventToSend = currentAnalyticsEvent;
currentQuantisedTime = 0;
_resetGranularityTimer();
currentAnalyticsEvent = _createAnalyticsEvent();
}
if(eventToSend.numEventsTotal === 0 ){
return;
}
let textToSend = JSON.stringify(eventToSend);
if(textToSend.length > POST_LARGE_DATA_THRESHOLD_BYTES){
console.warn(`Analytics event generated is very large at greater than ${textToSend.length}B. This
function _postCurrentAnalyticsEvent(eventToSend) {
if(disabled){
return;
}
if(!eventToSend){
eventToSend = currentAnalyticsEvent;
currentQuantisedTime = 0;
_resetGranularityTimer();
currentAnalyticsEvent = _createAnalyticsEvent();
}
if(eventToSend.numEventsTotal === 0 ){
return;
}
let textToSend = JSON.stringify(eventToSend);
if(textToSend.length > POST_LARGE_DATA_THRESHOLD_BYTES){
console.warn(`Analytics event generated is very large at greater than ${textToSend.length}B. This
typically means that you may be sending too many value events? .`);
}
debugLog("Sending Analytics data of length: ", textToSend.length, "B");
window.fetch(postURL, {
method: "POST",
headers: {'Content-Type': 'application/json'},
body: textToSend
}).then(res=>{
if(res.status === 200){
return;
}
if(res.status !== 400){ // we don't retry bad requests
_retryPost(eventToSend);
} else {
console.error("Analytics client: " +
"Bad Request, this is most likely a problem with the library, update to latest version.");
}
}).catch(res => {
debugError(res);
_retryPost(eventToSend);
});
}
debugLog("Sending Analytics data of length: ", textToSend.length, "B");
window.fetch(postURL, {
method: "POST",
headers: {'Content-Type': 'application/json'},
body: textToSend
}).then(res=>{
if(res.status === 200){
function _resetGranularityTimer(disable) {
if(granularityTimer){
clearInterval(granularityTimer);
granularityTimer = null;
}
if(disable){
return;
}
if(res.status !== 400){ // we don't retry bad requests
_retryPost(eventToSend);
} else {
console.error("Analytics client: " +
"Bad Request, this is most likely a problem with the library, update to latest version.");
}
}).catch(res => {
debugError(res);
_retryPost(eventToSend);
});
}
function _resetGranularityTimer(disable) {
if(granularityTimer){
clearInterval(granularityTimer);
granularityTimer = null;
granularityTimer = setInterval(()=>{
currentQuantisedTime = currentQuantisedTime + granularitySec;
}, granularitySec*1000);
}
if(disable){
return;
}
granularityTimer = setInterval(()=>{
currentQuantisedTime = currentQuantisedTime + granularitySec;
}, granularitySec*1000);
}
function _setupTimers(disable) {
_resetGranularityTimer(disable);
if(postTimer){
clearInterval(postTimer);
postTimer = null;
function _setupTimers(disable) {
_resetGranularityTimer(disable);
if(postTimer){
clearInterval(postTimer);
postTimer = null;
}
if(disable){
return;
}
postTimer = setInterval(_postCurrentAnalyticsEvent, postIntervalSeconds*1000);
}
if(disable){
return;
}
postTimer = setInterval(_postCurrentAnalyticsEvent, postIntervalSeconds*1000);
}
async function _getServerConfig() {
return new Promise((resolve, reject)=>{
let configURL = analyticsURL + `/getAppConfig?accountID=${accountID}&appName=${appName}`;
window.fetch(configURL).then(async res=>{
switch (res.status) {
case 200:
let serverResponse = await res.json();
resolve(serverResponse);
return;
case 400:
reject("Bad Request, check library version compatible?", res);
break;
default:
reject("analytics client: Could not update from remote config. Continuing with defaults.", res);
}
}).catch(err => {
reject("analytics client: Could not update from remote config. Continuing with defaults.", err);
async function _getServerConfig() {
return new Promise((resolve, reject)=>{
let configURL = analyticsURL + `/getAppConfig?accountID=${accountID}&appName=${appName}`;
window.fetch(configURL).then(async res=>{
switch (res.status) {
case 200:
let serverResponse = await res.json();
resolve(serverResponse);
return;
case 400:
reject("Bad Request, check library version compatible?", res);
break;
default:
reject("analytics client: Could not update from remote config. Continuing with defaults.", res);
}
}).catch(err => {
reject("analytics client: Could not update from remote config. Continuing with defaults.", err);
});
});
});
}
}
/**
* Returns the analytics config for the app
* @returns {Object}
*/
function getAppConfig() {
return {
accountID, appName, disabled,
uuid: userID, sessionID,
postIntervalSeconds, granularitySec, analyticsURL, serverConfig
};
}
/**
* Returns the analytics config for the app
* @returns {Object}
*/
function getAppConfig() {
return {
accountID, appName, disabled,
uuid: userID, sessionID,
postIntervalSeconds, granularitySec, analyticsURL, serverConfig
};
}
async function _initFromRemoteConfig(postIntervalSecondsInit, granularitySecInit) {
serverConfig = await _getServerConfig();
if(serverConfig !== {}){
// User init overrides takes precedence over server overrides
postIntervalSeconds = postIntervalSecondsInit ||
serverConfig["postIntervalSecondsInit"] || DEFAULT_POST_INTERVAL_SECONDS;
granularitySec = granularitySecInit || serverConfig["granularitySecInit"] || DEFAULT_GRANULARITY_IN_SECONDS;
// For URLs, the server suggested URL takes precedence over user init values
analyticsURL = serverConfig["analyticsURLInit"] || analyticsURL || DEFAULT_BASE_URL;
disabled = serverConfig["disabled"] === true;
_setupTimers(disabled);
debugLog(`Init analytics Config from remote. disabled: ${disabled}
async function _initFromRemoteConfig(postIntervalSecondsInit, granularitySecInit) {
serverConfig = await _getServerConfig();
if(serverConfig !== {}){
// User init overrides takes precedence over server overrides
postIntervalSeconds = postIntervalSecondsInit ||
serverConfig["postIntervalSecondsInit"] || DEFAULT_POST_INTERVAL_SECONDS;
granularitySec = granularitySecInit || serverConfig["granularitySecInit"] || DEFAULT_GRANULARITY_IN_SECONDS;
// For URLs, the server suggested URL takes precedence over user init values
analyticsURL = serverConfig["analyticsURLInit"] || analyticsURL || DEFAULT_BASE_URL;
disabled = serverConfig["disabled"] === true;
_setupTimers(disabled);
debugLog(`Init analytics Config from remote. disabled: ${disabled}
postIntervalSeconds:${postIntervalSeconds}, granularitySec: ${granularitySec} ,URL: ${analyticsURL}`);
if(disabled){
console.warn(`Core Analytics is disabled from the server for app: ${accountID}:${appName}`);
if(disabled){
console.warn(`Core Analytics is disabled from the server for app: ${accountID}:${appName}`);
}
}
}
}
function _stripTrailingSlash(url) {
return url.replace(/\/$/, "");
}
function _stripTrailingSlash(url) {
return url.replace(/\/$/, "");
}
/**
* 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");
/**
* 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);
}
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) {
let events = currentAnalyticsEvent.events;
events[eventType] = events[eventType] || {};
events[eventType][category] = events[eventType][category] || {};
events[eventType][category][subCategory] = events[eventType][category][subCategory] || {
time: [], // quantised time
valueCount: [] // value and count array, If a single value, then it is count, else object {"val1":count1, ...}
};
}
function _validateEvent(eventType, category, subCategory, count, value) {
_validateCurrentState();
if(!eventType || !category || !subCategory){
throw new Error("missing eventType or category or subCategory");
function _ensureAnalyticsEventExists(eventType, category, subCategory) {
let events = currentAnalyticsEvent.events;
events[eventType] = events[eventType] || {};
events[eventType][category] = events[eventType][category] || {};
events[eventType][category][subCategory] = events[eventType][category][subCategory] || {
time: [], // quantised time
valueCount: [] // value and count array, If a single value, then it is count, else object {"val1":count1, ...}
};
}
if(typeof(count)!== 'number' || count <0){
throw new Error("invalid count");
}
if(typeof(value)!== 'number'){
throw new Error("invalid value");
}
}
function _updateExistingAnalyticsEvent(index, eventType, category, subCategory, count, newValue) {
let events = currentAnalyticsEvent.events;
const storedValueIsCount = typeof(events[eventType][category][subCategory]["valueCount"][index]) === 'number';
if(storedValueIsCount && newValue === 0){
events[eventType][category][subCategory]["valueCount"][index] += count;
} else if(storedValueIsCount && newValue !== 0){
let newValueCount = {};
newValueCount[newValue] = count;
newValueCount[0] = events[eventType][category][subCategory]["valueCount"][index];
events[eventType][category][subCategory]["valueCount"][index] = newValueCount;
} else if(!storedValueIsCount){
let storedValueObject = events[eventType][category][subCategory]["valueCount"][index];
storedValueObject[newValue] = (storedValueObject[newValue] || 0) + count;
function _validateEvent(eventType, category, subCategory, count, value) {
_validateCurrentState();
if(!eventType || !category || !subCategory){
throw new Error("missing eventType or category or subCategory");
}
if(typeof(count)!== 'number' || count <0){
throw new Error("invalid count");
}
if(typeof(value)!== 'number'){
throw new Error("invalid value");
}
}
currentAnalyticsEvent.numEventsTotal += 1;
}
/**
* Register an analytics event. The events will be aggregated and send to the analytics server periodically.
* @param eventType - String, required
* @param eventCategory - String, required
* @param subCategory - String, required
* @param 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.
* @param eventValue (Optional) : A number value associated with the event. defaults to 0
*/
function analyticsEvent(eventType, eventCategory, subCategory, eventCount=1, eventValue=0) {
if(disabled){
return;
}
_validateEvent(eventType, eventCategory, subCategory, eventCount, eventValue);
_ensureAnalyticsEventExists(eventType, eventCategory, subCategory);
let events = currentAnalyticsEvent.events;
let timeArray = events[eventType][eventCategory][subCategory]["time"];
let lastTime = timeArray.length>0? timeArray[timeArray.length-1] : null;
if(lastTime !== currentQuantisedTime){
events[eventType][eventCategory][subCategory]["time"].push(currentQuantisedTime);
if(eventValue===0){
events[eventType][eventCategory][subCategory]["valueCount"].push(eventCount);
} else {
let valueCount = {};
valueCount[eventValue] = eventCount;
events[eventType][eventCategory][subCategory]["valueCount"].push(valueCount);
function _updateExistingAnalyticsEvent(index, eventType, category, subCategory, count, newValue) {
let events = currentAnalyticsEvent.events;
const storedValueIsCount = typeof(events[eventType][category][subCategory]["valueCount"][index]) === 'number';
if(storedValueIsCount && newValue === 0){
events[eventType][category][subCategory]["valueCount"][index] += count;
} else if(storedValueIsCount && newValue !== 0){
let newValueCount = {};
newValueCount[newValue] = count;
newValueCount[0] = events[eventType][category][subCategory]["valueCount"][index];
events[eventType][category][subCategory]["valueCount"][index] = newValueCount;
} else if(!storedValueIsCount){
let storedValueObject = events[eventType][category][subCategory]["valueCount"][index];
storedValueObject[newValue] = (storedValueObject[newValue] || 0) + count;
}
currentAnalyticsEvent.numEventsTotal += 1;
return;
}
let modificationIndex = events[eventType][eventCategory][subCategory]["valueCount"].length -1;
_updateExistingAnalyticsEvent(modificationIndex, eventType, eventCategory, subCategory, eventCount, eventValue);
/**
* Register an analytics event. The events will be aggregated and send to the analytics server periodically.
* @param eventType - String, required
* @param eventCategory - String, required
* @param subCategory - String, required
* @param 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.
* @param eventValue (Optional) : A number value associated with the event. defaults to 0
*/
function event(eventType, eventCategory, subCategory, eventCount=1, eventValue=0) {
if(disabled){
return;
}
_validateEvent(eventType, eventCategory, subCategory, eventCount, eventValue);
_ensureAnalyticsEventExists(eventType, eventCategory, subCategory);
let events = currentAnalyticsEvent.events;
let timeArray = events[eventType][eventCategory][subCategory]["time"];
let lastTime = timeArray.length>0? timeArray[timeArray.length-1] : null;
if(lastTime !== currentQuantisedTime){
events[eventType][eventCategory][subCategory]["time"].push(currentQuantisedTime);
if(eventValue===0){
events[eventType][eventCategory][subCategory]["valueCount"].push(eventCount);
} else {
let valueCount = {};
valueCount[eventValue] = eventCount;
events[eventType][eventCategory][subCategory]["valueCount"].push(valueCount);
}
currentAnalyticsEvent.numEventsTotal += 1;
return;
}
let modificationIndex = events[eventType][eventCategory][subCategory]["valueCount"].length -1;
_updateExistingAnalyticsEvent(modificationIndex, eventType, eventCategory, subCategory, eventCount, eventValue);
}
analytics.initSession = initSession;
analytics.getCurrentAnalyticsEvent = getCurrentAnalyticsEvent;
analytics.event = event;
analytics.getAppConfig = getAppConfig;
}
export {
initSession,
getCurrentAnalyticsEvent,
analyticsEvent,
getAppConfig
};
init();

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc