From 7c389a8010da23ff9064e0bfb7b0e226a83c5d78 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Nov 2014 15:06:01 +0100 Subject: [PATCH] Health check endpoint --- NEWS.md | 5 +- lib/cartodb/cartodb_windshaft.js | 26 +++++ lib/cartodb/monitoring/health_check.js | 130 +++++++++++++++++++++++++ lib/cartodb/monitoring/map-config.xml | 45 +++++++++ lib/cartodb/server_options.js | 3 +- npm-shrinkwrap.json | 4 +- package.json | 2 +- 7 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 lib/cartodb/monitoring/health_check.js create mode 100644 lib/cartodb/monitoring/map-config.xml diff --git a/NEWS.md b/NEWS.md index 69257515..e49eab41 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,12 @@ -1.21.1 -- 2014-mm-dd +1.22.0 -- 2014-mm-dd -------------------- Announcements: - Upgrades windshaft to 0.32.0 +New features: + - Health check endpoint + 1.21.0 -- 2014-10-24 -------------------- diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index 216d8682..c5934428 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -5,6 +5,7 @@ var _ = require('underscore') , TemplateMaps = require('./template_maps.js') , Cache = require('./cache_validator') , os = require('os') + , HealthCheck = require('./monitoring/health_check') ; if ( ! process.env['PGAPPNAME'] ) @@ -665,6 +666,31 @@ var CartodbWindshaft = function(serverOptions) { // ---- Template maps interface ends @} + var healthCheck = new HealthCheck(cartoData, serverOptions.queryTablesApi, Windshaft.tilelive); + ws.get('/health', function(req, res) { + var healthConfig = global.environment.health || {}; + + if (!!healthConfig.enabled) { + var startTime = Date.now(); + healthCheck.check(healthConfig, function(err, result) { + var ok = !err; + var response = { + enabled: true, + ok: ok, + elapsed: Date.now() - startTime, + result: result + }; + if (err) { + response.err = err.message; + } + res.send(response, ok ? 200 : 503); + + }); + } else { + res.send({enabled: false, ok: true}, 200); + } + }); + return ws; }; diff --git a/lib/cartodb/monitoring/health_check.js b/lib/cartodb/monitoring/health_check.js new file mode 100644 index 00000000..2facc846 --- /dev/null +++ b/lib/cartodb/monitoring/health_check.js @@ -0,0 +1,130 @@ +var _ = require('underscore'), + dot = require('dot'), + fs = require('fs'), + path = require('path'), + Step = require('step'); + +function HealthCheck(metadataBackend, queryTablesApi, tilelive) { + this.metadataBackend = metadataBackend; + this.queryTablesApi = queryTablesApi; + this.tilelive = tilelive; +} + +module.exports = HealthCheck; + + +var mapnikOptions = { + query: { + metatile: 1, + poolSize: 4, + bufferSize: 64 + }, + protocol: 'mapnik:', + slashes: true, + xml: null +}; + +var xmlTemplate = dot.template(fs.readFileSync(path.resolve(__dirname, 'map-config.xml'), 'utf-8')); + +HealthCheck.prototype.check = function(config, callback) { + + var self = this, + startTime, + result = { + redis: { + ok: false + }, + postgresql: { + ok: false + }, + mapnik: { + ok: false + }, + tile: { + ok: false + } + }, + mapnikXmlParams = _.extend({ + dbport: global.environment.postgres.port + }, config); + + Step( + function getDBParams() { + startTime = Date.now(); + self.metadataBackend.getAllUserDBParams(config.username, this); + }, + function runQuery(err, dbParams) { + if (err) { + throw err; + } + + result.redis = { + ok: !err, + elapsed: Date.now() - startTime, + size: Object.keys(dbParams).length + }; + + dbParams.dbuser = _.template(global.environment.postgres_auth_user, {user_id: dbParams.dbuser}); + + mapnikXmlParams = _.extend(mapnikXmlParams, dbParams); + + startTime = Date.now(); + self.queryTablesApi.getAffectedTablesInQuery(config.username, { + user: dbParams.dbuser, + pass: dbParams.dbpass, + host: dbParams.dbhost, + port: global.environment.postgres.port, + dbname: dbParams.dbname, + api_key: dbParams.apikey + }, config.query, this); + }, + function handleAffectedTablesQuery(err, affectedTables) { + if (err) { + throw err; + } + + result.postgresql = { + ok: !err, + elapsed: Date.now() - startTime, + size: affectedTables.length + }; + + this(); + }, + function loadMapnik(err) { + if (err) { + throw err; + } + mapnikOptions.xml = xmlTemplate(mapnikXmlParams); + + console.log(mapnikOptions.xml); + startTime = Date.now(); + self.tilelive.load(mapnikOptions, this); + }, + function getTile(err, source) { + if (err) { + throw err; + } + + result.mapnik = { + ok: !err, + elapsed: Date.now() - startTime + }; + + startTime = Date.now(); + source.getTile(config.z, config.x, config.y, this); + }, + function handleTile(err, tile) { + result.tile = { + ok: !err + }; + + if (tile) { + result.tile.elapsed = Date.now() - startTime; + result.tile.size = tile.length; + } + + callback(err, result); + } + ); +}; \ No newline at end of file diff --git a/lib/cartodb/monitoring/map-config.xml b/lib/cartodb/monitoring/map-config.xml new file mode 100644 index 00000000..e81cb17a --- /dev/null +++ b/lib/cartodb/monitoring/map-config.xml @@ -0,0 +1,45 @@ + + + + + + png8:m=h + layer0 + interactivity_id + + + + + + + layer0 + layer0-labels + + + + + + + + + + + + + + + + + + + + diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index adea9a3c..d67ccd0e 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -71,7 +71,8 @@ module.exports = function(redisPool) { varnish_secret: global.environment.varnish.secret, cache_enabled: global.environment.cache_enabled, log_format: global.environment.log_format, - useProfiler: global.environment.useProfiler + useProfiler: global.environment.useProfiler, + queryTablesApi: queryTablesApi }; // Do not send unwatch on release diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index f3656c7b..453036e4 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "windshaft-cartodb", - "version": "1.21.1", + "version": "1.22.0", "dependencies": { "cartodb-psql": { "version": "0.4.0", @@ -1528,7 +1528,7 @@ }, "sphericalmercator": { "version": "1.0.2", - "from": "sphericalmercator@~1.0.2" + "from": "sphericalmercator@~1.0.1" } } }, diff --git a/package.json b/package.json index ecd7190f..d9a30a19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "1.21.1", + "version": "1.22.0", "description": "A map tile server for CartoDB", "keywords": [ "cartodb"