Skip to content

Commit

Permalink
Merge pull request #172 from telefonicaid/task/addMongoDbPersistanceF…
Browse files Browse the repository at this point in the history
…orStats

Task/add mongo db persistance for stats
  • Loading branch information
XavierVal committed Oct 22, 2015
2 parents 2c9b3ad + 062e59e commit 4be3d1d
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 23 deletions.
3 changes: 2 additions & 1 deletion CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
- FIX Change Device Not Found to 404 instead of 500 (#161).
- ADD First version of the stats registry (#160).
- FIX Reestructure files and folders (#164).
- FIX Use Express Methods to check content type (#170).
- ADD Mongodb action to persist stats.
- FIX Use Express Methods to check content type (#170).
10 changes: 8 additions & 2 deletions lib/model/dbConn.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
*/

var mongoose = require('mongoose'),
defaultDb;
defaultDb,
DEFAULT_DB_NAME = 'iotagent';

function loadModels() {
require('./Device').load(defaultDb);
Expand All @@ -38,19 +39,24 @@ function loadModels() {
/**
* Creates a new connection to the Mongo DB.
*
* @this Reference to the dbConn module itself.
*/
function init(host, db, port, options, callback) {
/*jshint camelcase:false */
/*jshint camelcase:false, validthis:true */

defaultDb = mongoose.createConnection(host, db, port, options);

defaultDb.on('error', function mongodbErrorHandler(error) {
throw new Error(error);
});

this.db = defaultDb;

loadModels();

callback(null);
}

exports.init = init;
exports.db = defaultDb;
exports.DEFAULT_DB_NAME = DEFAULT_DB_NAME;
3 changes: 1 addition & 2 deletions lib/services/devices/deviceRegistryMongoDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ var logger = require('logops'),
dbService = require('../../model/dbConn'),
errors = require('../../errors'),
Device = require('../../model/Device'),
DEFAULT_DB_NAME = 'iotagent',
context = {
op: 'IoTAgentNGSI.MongoDBDeviceRegister'
};
Expand Down Expand Up @@ -223,7 +222,7 @@ function init(newConfig, callback) {
port = newConfig.deviceRegistry.port || 27017;

if (!newConfig.deviceRegistry.db) {
dbName = DEFAULT_DB_NAME;
dbName = dbService.DEFAULT_DB_NAME;
}

dbService.init(newConfig.deviceRegistry.host, dbName, port, {}, callback);
Expand Down
66 changes: 52 additions & 14 deletions lib/services/stats/statsRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
'use strict';

var async = require('async'),
_ = require('underscore'),
apply = async.apply,
logger = require('logops'),
errors = require('../../errors'),
dbService = require('../../model/dbConn'),
config,
globalStats = {},
currentStats = {},
Expand Down Expand Up @@ -107,19 +110,6 @@ function globalLoad(values, callback) {
callback(null);
}

/**
* Changes the configuration of the Stats Registry service.
*
* @param {Object} newConfig New configuration of the registry.
*/
function init(newConfig, callback) {
config = newConfig;

if (callback) {
callback();
}
}

/**
* Reset each of the current stats to value zero.
*/
Expand Down Expand Up @@ -160,6 +150,7 @@ function addTimerAction(handler, callback) {
function clearTimers(callback) {
if (timerHandler) {
clearInterval(timerHandler);
timerHandler = undefined;
}

timerActions = [];
Expand All @@ -179,6 +170,52 @@ function logStats(currentValues, globalValues, callback) {
resetCurrent(callback);
}

/**
* Predefined action that persists the current value of the stats in the MongoDb instance.
*
* @param {Object} currentValues Current stat values.
* @param {Object} globalValues Global stat values.
*/
function mongodbPersistence(currentValues, globalValues, callback) {
var statStamp = _.clone(globalValues);

statStamp.timestamp = new Date().toISOString();
dbService.db.collection('kpis').insert(statStamp);

callback();
}

function configureDb(newConfig, callback) {
if (!newConfig.mongodb || !newConfig.mongodb.host) {
logger.fatal('No host found for MongoDB driver.');
callback(new errors.BadConfiguration('No host found for MongoDB driver'));
} else {
var dbName = newConfig.mongodb.db,
port = newConfig.mongodb.port || 27017;

if (!newConfig.mongodb.db) {
dbName = dbService.DEFAULT_DB_NAME;
}

dbService.init(newConfig.mongodb.host, dbName, port, {}, callback);
}
}

/**
* Changes the configuration of the Stats Registry service.
*
* @param {Object} newConfig New configuration of the registry.
*/
function init(newConfig, callback) {
config = newConfig;

if (config.stats && config.stats.persistence) {
configureDb(newConfig, callback);
} else {
callback();
}
}

exports.init = init;
exports.add = add;
exports.getCurrent = getCurrent;
Expand All @@ -187,6 +224,7 @@ exports.getAllGlobal = getAllGlobal;
exports.getAllCurrent = getAllCurrent;
exports.globalLoad = globalLoad;
exports.resetCurrent = resetCurrent;
exports.addTimerAction = addTimerAction;
exports.clearTimers = clearTimers;
exports.addTimerAction = addTimerAction;
exports.logStats = logStats;
exports.mongodbPersistence = mongodbPersistence;
101 changes: 101 additions & 0 deletions test/unit/statistics-persistence_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
*
* This file is part of fiware-iotagent-lib
*
* fiware-iotagent-lib is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* fiware-iotagent-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with fiware-iotagent-lib.
* If not, seehttp://www.gnu.org/licenses/.
*
* For those usages not covered by the GNU Affero General Public License
* please contact with::[[email protected]]
*/
'use strict';

var statsService = require('../../lib/services/stats/statsRegistry'),
should = require('should'),
mongo = require('mongodb').MongoClient,
mongoUtils = require('./mongoDBUtils'),
iotAgentConfig = {
logLevel: 'FATAL',
contextBroker: {
host: '10.11.128.16',
port: '1026'
},
server: {
port: 4041,
baseRoot: '/'
},
stats: {
interval: 100,
persistence: true
},
mongodb: {
host: 'localhost',
port: '27017',
db: 'iotagent'
},
types: {},
service: 'smartGondor',
subservice: 'gardens',
providerUrl: 'http://smartGondor.com',
deviceRegistrationDuration: 'P1M',
throttling: 'PT5S'
},
iotAgentDb;

describe('Statistics persistence service', function() {
beforeEach(function(done) {
statsService.init(iotAgentConfig, function() {
statsService.globalLoad({}, function() {
mongo.connect('mongodb://localhost:27017/iotagent', function(err, db) {
iotAgentDb = db;
done();
});
});
});
});

afterEach(function(done) {
statsService.globalLoad({}, function() {
iotAgentDb.close(function(error) {
mongoUtils.cleanDbs(done);
});
});
});

describe('When a periodic persitence action is set', function() {
beforeEach(function(done) {
statsService.globalLoad({
stat1: 10
}, function() {
statsService.add('stat1', 5, done);
});
});

it('should store all the records in the database', function(done) {
statsService.addTimerAction(statsService.mongodbPersistence, function() {
setTimeout(function() {
statsService.clearTimers(function() {
iotAgentDb.collection('kpis').find({}).toArray(function(err, docs) {
should.not.exist(err);
should.exist(docs);
docs.length.should.be.above(2);
done();
});
});
}, 480);
});
});
});
});
10 changes: 6 additions & 4 deletions test/unit/statistics-service_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ var statsService = require('../../lib/services/stats/statsRegistry'),

describe('Statistics service', function() {
beforeEach(function(done) {
statsService.init(iotAgentConfig);

statsService.globalLoad({}, done);
statsService.init(iotAgentConfig, function() {
statsService.globalLoad({}, function() {
statsService.clearTimers(done);
});
});
});

afterEach(function(done) {
Expand Down Expand Up @@ -152,7 +154,7 @@ describe('Statistics service', function() {

it('should be triggered with the periodicity stated in the config.stats.interval parameter', function(done) {
statsService.addTimerAction(mockedAction, function() {
setInterval(function() {
setTimeout(function() {
statsService.clearTimers(function() {
valueCurrent.should.equal(5);
valueGlobal.should.equal(15);
Expand Down

0 comments on commit 4be3d1d

Please sign in to comment.