blob: a07a39bc30ffa8abd10c5b89ab387747f6ffb115 [file] [log] [blame]
/*
* Copyright (c) 2013 DataTorrent, Inc. ALL Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var redis = require('redis');
var dateFormat = require('dateformat');
var async = require('async');
var config = require('../config');
var _ = require('underscore');
var client;
var demoEnabled = (config.machine.redis.port && config.machine.redis.host);
if (demoEnabled) {
client = redis.createClient(config.machine.redis.port, config.machine.redis.host);
if (config.machine.redis.dbIndex) {
client.select(config.machine.redis.dbIndex);
}
}
exports.index = function (req, res) {
if (demoEnabled) {
res.render('machine');
} else {
res.render('error', {
message: 'Machine Generated Data Demo is not enabled. Please configure Redis.'
});
}
};
exports.data = function (req, res) {
getMinutes(req.query, function (err, result) {
var forcedDelay = config.machine.forcedDelay;
if (!forcedDelay) {
res.json(result);
} else {
setTimeout(function () { // for testing purpose only
res.json(result);
}, forcedDelay);
}
});
};
function extractMinutes(minuteKeys, replies) {
var minutes = [];
var latestKeyWithData = null;
for (var i = 0; i < replies.length; i++) {
var reply = replies[i];
var minuteKey = minuteKeys[i];
if (reply) {
if (parseInt(reply.day, 10) === parseInt(minuteKey.day, 10)) {
var minute = {
timestamp: minuteKeys[i].timestamp,
cpu: reply.cpu,
ram: reply.ram,
hdd: reply.hdd
};
minutes.push(minute);
if (!latestKeyWithData) {
latestKeyWithData = minuteKey.key;
}
} else if (!_.isEmpty(minutes)) {
break;
}
} else if (!_.isEmpty(minutes)) {
break;
}
}
var data = {
minutes: minutes,
latestKeyWithData: latestKeyWithData
};
return data;
}
exports.extractMinutes = extractMinutes;
function getMinutes(query, resCallback) {
var lookback = query.lookback;
var lastTimestamp = query.lastTimestamp;
var keyParams = [query.customer, query.product, query.os, query.software1, query.software2, query.software3, query.deviceId];
var paramKeyTemplate = '|$index:$param';
var minuteKeyTemplate = '$date';
keyParams.forEach(function (param, index) {
if (param) {
var paramKey = paramKeyTemplate
.replace('$index', index)
.replace('$param', param);
minuteKeyTemplate += paramKey;
}
});
var minute = (60 * 1000);
var endTime = Date.now();
endTime -= (endTime % minute); // round to minute
if (lastTimestamp) {
var startTime = lastTimestamp - (lastTimestamp % minute); // round to minute
var optimizedLookback = Math.floor((endTime - startTime)/minute) + 1;
if (optimizedLookback < lookback) {
lookback = optimizedLookback;
}
}
var minuteKeys = [];
for (var i = 0; i < lookback; i++) {
var time = endTime - (i * minute);
var date = dateFormat(time, 'UTC:HHMM');
var day = dateFormat(time, 'UTC:d');
var key = minuteKeyTemplate.replace('$date', date);
minuteKeys.push({
timestamp: time,
day: day,
key: key
});
}
var multi = client.multi();
minuteKeys.forEach(function(key) {
multi.hgetall(key.key);
});
var execStartTime = Date.now();
multi.exec(function (err, replies) {
var execTime = (Date.now() - execStartTime);
var minuteData = extractMinutes(minuteKeys, replies);
var minutes = minuteData.minutes;
minutes.reverse();
var lastKey = minuteData.latestKeyWithData;
var lastKeyQueried = _.first(minuteKeys).key;
var result = {
minutes: minutes,
keysQueried: minuteKeys.length,
lastKeyQueried: lastKeyQueried,
lastKey: lastKey,
queryTime: execTime
};
console.log('Redis exec time ' + execTime +
'ms. Replies: ' + replies.length +
'. Last key with data: ' + lastKey);
resCallback(err, result);
});
}