Files
shields/lib/analytics.js
Paul Melnikow f47aa968cd Prepare to modify / refactor analytics (#970)
- Move analytics into their own file
- Add test of analytics endpoint
2017-04-28 01:06:06 -04:00

116 lines
3.6 KiB
JavaScript

const fs = require('fs');
// We can either use a process-wide object regularly saved to a JSON file,
// or a Redis equivalent (for multi-process / when the filesystem is unreliable.
var redis;
var useRedis = false;
if (process.env.REDISTOGO_URL) {
var redisToGo = require('url').parse(process.env.REDISTOGO_URL);
redis = require('redis').createClient(redisToGo.port, redisToGo.hostname);
redis.auth(redisToGo.auth.split(':')[1]);
useRedis = true;
}
var analytics = {};
var analyticsAutoSaveFileName = process.env.SHIELDS_ANALYTICS_FILE || './analytics.json';
var analyticsAutoSavePeriod = 10000;
setInterval(function analyticsAutoSave() {
if (useRedis) {
redis.set(analyticsAutoSaveFileName, JSON.stringify(analytics));
} else {
fs.writeFileSync(analyticsAutoSaveFileName, JSON.stringify(analytics));
}
}, analyticsAutoSavePeriod);
function defaultAnalytics() {
var analytics = Object.create(null);
// In case something happens on the 36th.
analytics.vendorMonthly = new Array(36);
resetMonthlyAnalytics(analytics.vendorMonthly);
analytics.rawMonthly = new Array(36);
resetMonthlyAnalytics(analytics.rawMonthly);
analytics.vendorFlatMonthly = new Array(36);
resetMonthlyAnalytics(analytics.vendorFlatMonthly);
analytics.rawFlatMonthly = new Array(36);
resetMonthlyAnalytics(analytics.rawFlatMonthly);
analytics.vendorFlatSquareMonthly = new Array(36);
resetMonthlyAnalytics(analytics.vendorFlatSquareMonthly);
analytics.rawFlatSquareMonthly = new Array(36);
resetMonthlyAnalytics(analytics.rawFlatSquareMonthly);
return analytics;
}
// Auto-load analytics.
function analyticsAutoLoad() {
var defaultAnalyticsObject = defaultAnalytics();
if (useRedis) {
redis.get(analyticsAutoSaveFileName, function(err, value) {
if (err == null && value != null) {
// if/try/return trick:
// if error, then the rest of the function is run.
try {
analytics = JSON.parse(value);
// Extend analytics with a new value.
for (var key in defaultAnalyticsObject) {
if (!(key in analytics)) {
analytics[key] = defaultAnalyticsObject[key];
}
}
return;
} catch(e) {
console.error('Invalid Redis analytics, resetting.');
console.error(e);
}
}
analytics = defaultAnalyticsObject;
});
} else {
// Not using Redis.
try {
analytics = JSON.parse(fs.readFileSync(analyticsAutoSaveFileName));
// Extend analytics with a new value.
for (var key in defaultAnalyticsObject) {
if (!(key in analytics)) {
analytics[key] = defaultAnalyticsObject[key];
}
}
} catch(e) {
if (e.code !== 'ENOENT') {
console.error('Invalid JSON file for analytics, resetting.');
console.error(e);
}
analytics = defaultAnalyticsObject;
}
}
}
var lastDay = (new Date()).getDate();
function resetMonthlyAnalytics(monthlyAnalytics) {
for (var i = 0; i < monthlyAnalytics.length; i++) {
monthlyAnalytics[i] = 0;
}
}
function incrMonthlyAnalytics(monthlyAnalytics) {
try {
var currentDay = (new Date()).getDate();
// If we changed month, reset empty days.
while (lastDay !== currentDay) {
// Assumption: at least a hit a month.
lastDay = (lastDay + 1) % monthlyAnalytics.length;
monthlyAnalytics[lastDay] = 0;
}
monthlyAnalytics[currentDay]++;
} catch(e) { console.error(e.stack); }
}
function getAnalytics() {
return analytics;
}
module.exports = {
analyticsAutoLoad,
incrMonthlyAnalytics,
getAnalytics
};