Skip to content

Commit

Permalink
[SDK-686] idtype and request t (#39)
Browse files Browse the repository at this point in the history
* tests, id type and request t added

* changelog entry

* linting

* more linting

* some timing issue fix

* update

* wording changes

* changelog and split up the init id assign functions

* some comments

* ID type ifs

* tests, comments and linting

* timing for tests
  • Loading branch information
turtledreams authored May 13, 2022
1 parent ae24421 commit 5236fe8
Show file tree
Hide file tree
Showing 6 changed files with 445 additions and 44 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 22.02.0
- !! Major breaking change !! Device ID provided during the init will be ignored if a device ID was provided previously
- Added a new init time flag which erases the previously stored device ID. This allows to set new device ID during init
- Added a call to get the device ID type of the user
- Added a call to get the device ID of the user
- Now it appends the device ID type with each request

## 21.11.0
- !! Major breaking change !! Changing device ID without merging will now clear the current consent. Consent has to be given again after performing this action.
- ! Minor breaking change ! Multiple values now have a default limit adjustable at initialization:
Expand Down
74 changes: 45 additions & 29 deletions lib/countly-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,38 @@ var cc = {
debugBulk: false,
debugBulkUser: false,
/**
*
*log level Enums:
*Error - this is a issues that needs attention right now.
*Warning - this is something that is potentially a issue. Maybe a deprecated usage of something, maybe consent is enabled but consent is not given.
*Info - All publicly exposed functions should log a call at this level to indicate that they were called. These calls should include the function name.
*Debug - this should contain logs from the internal workings of the SDK and it's important calls. This should include things like the SDK configuration options, success or fail of the current network request, "request queue is full" and the oldest request get's dropped, etc.
*Verbose - this should give a even deeper look into the SDK's inner working and should contain things that are more noisy and happen often.
*/
* log level Enums:
* Error - this is a issues that needs attention right now.
* Warning - this is something that is potentially a issue. Maybe a deprecated usage of something, maybe consent is enabled but consent is not given.
* Info - All publicly exposed functions should log a call at this level to indicate that they were called. These calls should include the function name.
* Debug - this should contain logs from the internal workings of the SDK and it's important calls. This should include things like the SDK configuration options, success or fail of the current network request, "request queue is full" and the oldest request get's dropped, etc.
* Verbose - this should give a even deeper look into the SDK's inner working and should contain things that are more noisy and happen often.
*/
logLevelEnums: {
ERROR: '[ERROR] ',
WARNING: '[WARNING] ',
INFO: '[INFO] ',
DEBUG: '[DEBUG] ',
VERBOSE: '[VERBOSE] ',
},
/**
* device ID type:
* 0 - device ID was set by the developer during init
* 1 - device ID was auto generated by Countly
*/
deviceIdTypeEnums: {
DEVELOPER_SUPPLIED: 0,
SDK_GENERATED: 1,
},
/**
* At the current moment there are following internal events and their respective required consent:
[CLY]_nps - "feedback" consent
[CLY]_survey - "feedback" consent
[CLY]_star_rating - "star_rating" consent
[CLY]_view - "view" consent
[CLY]_orientation - "users" consent
[CLY]_push_action - "push" consent
[CLY]_action - "clicks" or "scroll" consent
* [CLY]_nps - "feedback" consent
* [CLY]_survey - "feedback" consent
* [CLY]_star_rating - "star_rating" consent
* [CLY]_view - "view" consent
* [CLY]_orientation - "users" consent
* [CLY]_push_action - "push" consent
* [CLY]_action - "clicks" or "scroll" consent
*/
internalEventKeyEnums: {
NPS: '[CLY]_nps',
Expand Down Expand Up @@ -106,11 +114,11 @@ var cc = {
return newStr;
},
/**
* Retrieve only specific properties from object
* @param {Object} orig - object from which to get properties
* @param {Array} props - list of properties to get
* @returns {Object} Object with requested properties
*/
* Retrieve only specific properties from object
* @param {Object} orig - object from which to get properties
* @param {Array} props - list of properties to get
* @returns {Object} Object with requested properties
*/
getProperties: function getProperties(orig, props) {
var ob = {};
var prop;
Expand All @@ -123,21 +131,21 @@ var cc = {
return ob;
},
/**
* Removing trailing slashes
* @memberof Countly._internals
* @param {String} str - string from which to remove traling slash
* @returns {String} modified string
*/
* Removing trailing slashes
* @memberof Countly._internals
* @param {String} str - string from which to remove traling slash
* @returns {String} modified string
*/
stripTrailingSlash: function stripTrailingSlash(str) {
if (str.substring(str.length - 1) === "/") {
return str.substring(0, str.length - 1);
}
return str;
},
/**
* Generate random UUID value
* @returns {String} random UUID value
*/
* Generate random UUID value
* @returns {String} random UUID value
*/
generateUUID: function generateUUID() {
var d = new Date().getTime();
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
Expand All @@ -148,7 +156,15 @@ var cc = {
return uuid;
},
/**
* Log data if debug mode is enabled
* Check if value is in UUID format
* @param {string} providedId - Id to check
* @returns {Boolean} true if it is in UUID format
*/
isUUID: function isUUID(providedId) {
return /[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-4[0-9a-fA-F]{3}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/.test(providedId);
},
/**
* Log data if debug mode is enabled
* @param {string} level - log level (error, warning, info, debug, verbose)
* @param {string} message - any string message
*/
Expand Down
77 changes: 67 additions & 10 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Countly.Bulk = Bulk;
var maxStackTraceLinesPerThread = 30;
var maxStackTraceLineLength = 200;
var __data = {};
var deviceIdType = null;

/**
* Array with list of available features that you can require consent for
Expand Down Expand Up @@ -101,6 +102,8 @@ Countly.Bulk = Bulk;
* @param {number} [conf.session_update=60] - how often in seconds should session be extended
* @param {number} [conf.max_events=100] - maximum amount of events to send in one batch
* @param {boolean} [conf.force_post=false] - force using post method for all requests
* @param {boolean} [conf.clear_stored_device_id=false] - set it to true if you want to erase the stored device ID
* @param {boolean} [conf.test_mode=false] - set it to true if you want to initiate test_mode
* @param {string} [conf.storage_path="../data/"] - where SDK would store data, including id, queues, etc
* @param {boolean} [conf.require_consent=false] - pass true if you are implementing GDPR compatible consent management. It would prevent running any functionality without proper consent
* @param {boolean|function} [conf.remote_config=false] - Enable automatic remote config fetching, provide callback function to be notified when fetching done
Expand Down Expand Up @@ -147,6 +150,8 @@ Countly.Bulk = Bulk;
maxEventBatch = conf.max_events || Countly.max_events || maxEventBatch;
metrics = conf.metrics || Countly.metrics || {};
conf.debug = conf.debug || Countly.debug || false;
conf.clear_stored_device_id = conf.clear_stored_device_id || false;
Countly.test_mode = conf.test_mode || false;
Countly.app_key = conf.app_key || Countly.app_key || null;
Countly.url = cc.stripTrailingSlash(conf.url || Countly.url || "");
Countly.app_version = conf.app_version || Countly.app_version || "0.0";
Expand Down Expand Up @@ -179,15 +184,53 @@ Countly.Bulk = Bulk;
// eslint-disable-next-line no-console
console.log(ex.stack);
}
// clear stored device ID if flag is set
if (conf.clear_stored_device_id) {
cc.log(cc.logLevelEnums.WARNING, "Erasing stored ID");
storeSet("cly_id", null);
storeSet("cly_id_type", null);
}

if (Countly.url === "") {
cc.log(cc.logLevelEnums.ERROR, "Please provide server URL");
}
else {
cc.log(cc.logLevelEnums.INFO, "Countly initialized");
if (cluster.isMaster) {
Countly.device_id = conf.device_id || Countly.device_id || getId();
// fetch stored ID and ID type
var storedId = storeGet("cly_id", null);
var storedIdType = storeGet("cly_id_type", null);
// if there was a stored ID
if (storedId !== null) {
Countly.device_id = storedId;
// deviceIdType = storedIdType || cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED;
if (storedIdType === null) {
// even though the device ID set, not type was set, setting it here
if (cc.isUUID(storedId)) {
// assuming it is a UUID so also assuming it is SDK generated
storedIdType = cc.deviceIdTypeEnums.SDK_GENERATED;
}
else {
// assuming it was set by the developer
storedIdType = cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED;
}
}
deviceIdType = storedIdType;
}
// if the user provided device ID during the init and no ID was stored
else if (conf.device_id || Countly.device_id) {
Countly.device_id = conf.device_id || Countly.device_id;
deviceIdType = cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED;
}
// if no device ID provided during init nor it was stored previously
else {
Countly.device_id = cc.generateUUID();
deviceIdType = cc.deviceIdTypeEnums.SDK_GENERATED;
}
// save the ID and ID type
storeSet("cly_id", Countly.device_id);
storeSet("cly_id_type", deviceIdType);
// create queues
requestQueue = storeGet("cly_queue", []);
eventQueue = storeGet("cly_event", []);
remoteConfigs = storeGet("cly_remote_configs", {});
Expand Down Expand Up @@ -251,6 +294,7 @@ Countly.Bulk = Bulk;
maxStackTraceLinesPerThread = 30;
maxStackTraceLineLength = 200;
__data = {};
deviceIdType = null;

// cc DEBUG
cc.debug = false;
Expand Down Expand Up @@ -539,6 +583,24 @@ Countly.Bulk = Bulk;
}
};

/**
* Check and return the current device id type
* @returns {number} a number that indicates the device id type
*/
Countly.get_device_id_type = function() {
cc.log(cc.logLevelEnums.INFO, `check_device_id_type, Retrieving the current device id type.[${deviceIdType}]`);
return deviceIdType;
};

/**
* Gets the current device id
* @returns {string} device id
*/
Countly.get_device_id = function() {
cc.log(cc.logLevelEnums.INFO, `get_device_id, Retrieving the device id: [${Countly.device_id}]`);
return Countly.device_id;
};

/**
* Change current user/device id
* @param {string} newId - new user/device ID to use
Expand All @@ -564,7 +626,9 @@ Countly.Bulk = Bulk;
}
var oldId = Countly.device_id;
Countly.device_id = newId;
deviceIdType = cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED;
storeSet("cly_id", Countly.device_id);
storeSet("cly_id_type", deviceIdType);
cc.log(cc.logLevelEnums.INFO, "change_id, Changing ID");
if (merge) {
if (Countly.check_any_consent()) {
Expand Down Expand Up @@ -1297,6 +1361,7 @@ Countly.Bulk = Bulk;
request.device_id = Countly.device_id;
request.sdk_name = SDK_NAME;
request.sdk_version = SDK_VERSION;
request.t = deviceIdType;
if (Countly.check_consent("location")) {
if (Countly.country_code) {
request.country_code = Countly.country_code;
Expand Down Expand Up @@ -1369,7 +1434,7 @@ Countly.Bulk = Bulk;
}

// process request queue with event queue
if (requestQueue.length > 0 && readyToProcess && cc.getTimestamp() > failTimeout) {
if (requestQueue.length > 0 && readyToProcess && cc.getTimestamp() > failTimeout && !Countly.test_mode) {
readyToProcess = false;
var params = requestQueue.shift();
cc.log(cc.logLevelEnums.DEBUG, "Processing request", params);
Expand All @@ -1388,14 +1453,6 @@ Countly.Bulk = Bulk;
setTimeout(heartBeat, beatInterval);
}

/**
* Get device ID, stored one, or generate new one
* @returns {String} device id
*/
function getId() {
return storeGet("cly_id", null) || cc.generateUUID();
}

/**
* Get metrics of the browser or config object
* @returns {Object} Metrics object
Expand Down
11 changes: 7 additions & 4 deletions test/helpers/helper_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,22 @@ function readRequestQueue() {
}

// queue files clearing logic
function clearStorage() {
function clearStorage(keepID) {
keepID = keepID || false;
// Resets Countly
Countly.halt(true);
// clean storages
if (fs.existsSync(idDir)) {
fs.unlinkSync(idDir);
}
if (fs.existsSync(eventDir)) {
fs.unlinkSync(eventDir);
}
if (fs.existsSync(reqDir)) {
fs.unlinkSync(reqDir);
}
if (!keepID) {
if (fs.existsSync(idDir)) {
fs.unlinkSync(idDir);
}
}
}
/**
* bunch of tests specifically gathered for testing events
Expand Down
Loading

0 comments on commit 5236fe8

Please sign in to comment.