Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add timestamp to session generations in o-tracking #1856

Merged
merged 4 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libraries/o-tracking/src/javascript/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function track(config, callback = function(){ /* empty */}) {
device: {
spoor_session: currentSession.id,
spoor_session_is_new: currentSession.isNew,
spoor_session_timestamp: currentSession.timestamp,
spoor_id: userID(),
},
};
Expand Down
40 changes: 32 additions & 8 deletions libraries/o-tracking/src/javascript/core/session.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {is, merge, isUndefined, guid} from '../utils.js';
import {is, merge, isUndefined, guid, namedLog} from '../utils.js';
import {Store} from './store.js';

/**
* @typedef {object} Session
* @property {string} id - The id of the session
* @property {boolean} isNew - Whether it is a brand new session
* @property {number} timestamp - The timestamp of the session generation
*/

let store;
const logger = namedLog('Core.Session')
const defaultSessionConfig = {
storage: 'best',
name: 'session',
Expand All @@ -20,14 +22,20 @@ const defaultSessionConfig = {
* @param {string} session - The session to be stored.
* @returns {void}
*/
function setSession(session) {
function setSession(session, timestamp) {
const d = new Date();
d.setTime(d.getTime() + store.config.expires);

store.write({
const sessionData = {
value: session,
expiry: d.valueOf()
});
expiry: d.valueOf(),
}
if(timestamp) {
sessionData.timestamp = timestamp;
}
logger('Setting session', sessionData)

store.write(sessionData);
}

/**
Expand All @@ -39,32 +47,48 @@ function getSession() {
const s = store.read();
let session;
let isNew = false;
let sessionTimestamp;

if (s) {
const d = new Date().valueOf();
logger("Found session", s)
const currentDate = new Date();
const d = currentDate.valueOf();
const timestamp = currentDate.getTime();
const exp = parseInt(s.expiry, 10);

// If current session is active.
if (exp >= d) {
session = s.value;
sessionTimestamp = s.timestamp;

// session is active but no generated timestamp
if(!sessionTimestamp) {
logger("Session is valid but no timestamp, generating timestamp.")
sessionTimestamp = timestamp;
}
} else {
// session has expired, generate a new one
// session has expired, generate a new one along with a new timestamp
logger("Session has expired, generating new one")
sessionTimestamp = timestamp;
session = guid();
isNew = true;
}
}

// No active session, gen a new one.
if (!session) {
logger("No session found, generating new one")
session = guid();
sessionTimestamp = new Date().getTime();
isNew = true;
}

// Refreshes the cookie...
setSession(session);
setSession(session, sessionTimestamp);

return {
id: session,
timestamp: sessionTimestamp,
isNew: isNew
};
}
Expand Down
2 changes: 1 addition & 1 deletion libraries/o-tracking/src/javascript/tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const initPage = page.init;
*
* @type {string}
*/
const version = '4.5.4';
const version = '4.5.5';

/**
* The source of this event.
Expand Down
21 changes: 21 additions & 0 deletions libraries/o-tracking/src/javascript/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ function log(...args) {
}
}

/**
* Creates a logging function that logs messages to the console with a specified namespace.
*
* @function namedLog
* @param {string} namespace - The namespace to be prefixed to each log message.
* @returns {function} A function that logs messages to the console with the given namespace if the configuration allows.
*
* @example
* const log = namedLog('MyNamespace');
* log('This is a message');
* // Output: [MyNamespace]: This is a message
*/
function namedLog(namespace) {
return function(...args) {
if(get('config').test && window.console) {
window.console.log(`%c[${namespace}]:`, 'color: teal', ...args)
}
}
}

/**
* Tests if variable is a certain type. Defaults to check for undefined if no type specified.
*
Expand Down Expand Up @@ -389,6 +409,7 @@ function isDeepEqual(a, b) {

export {
log,
namedLog,
is,
is as isUndefined,
merge,
Expand Down
3 changes: 2 additions & 1 deletion libraries/o-tracking/test/core.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ describe('Core', function () {
proclaim.equal(sent_data.user.user_id, "userID");

// Device
proclaim.deepEqual(Object.keys(sent_data.device), ["spoor_session","spoor_session_is_new","spoor_id"]);
proclaim.deepEqual(Object.keys(sent_data.device), ["spoor_session","spoor_session_is_new","spoor_session_timestamp", "spoor_id"]);
proclaim.equal(sent_data.device.spoor_session, session().id);
proclaim.equal(sent_data.device.spoor_session_is_new, session().isNew);
proclaim.equal(sent_data.device.spoor_session_timestamp, session().timestamp);

});

Expand Down
15 changes: 15 additions & 0 deletions libraries/o-tracking/test/core/session.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('Core.Session', function () {
const newSession = getSession();
proclaim.equal(newSession.id, session.id);
proclaim.equal(newSession.isNew, false);
proclaim.equal(newSession.timestamp, session.timestamp)
});
});

Expand All @@ -59,6 +60,20 @@ describe('Core.Session', function () {
proclaim.isTrue(newSession.isNew);
done();
}, 2)
});

it('should generate timestamp for session', () => {
const currentTimestamp = new Date().getTime();
proclaim.equal(currentTimestamp, getSession().timestamp)
})

it('should generate a new timestamp if session has expired', (done) => {
const prevSession = initSession({expires: 1});
setTimeout(function() {
const newSession = getSession();
proclaim.notEqual(prevSession.timestamp, newSession.timestamp);
done()
}, 2)
})
})
});
Loading