Health check endpoint

This commit is contained in:
Raul Ochoa
2014-11-05 15:06:01 +01:00
parent 1c638aa661
commit 7c389a8010
7 changed files with 210 additions and 5 deletions
+4 -1
View File
@@ -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
--------------------
+26
View File
@@ -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;
};
+130
View File
@@ -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);
}
);
};
+45
View File
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map[]>
<Map srs="+init=epsg:3857" buffer-size="128" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
<Parameters>
<Parameter name="format">png8:m=h</Parameter>
<Parameter name="interactivity_layer">layer0</Parameter>
<Parameter name="interactivity_fields">interactivity_id</Parameter>
</Parameters>
<Style name="layer0-labels" filter-mode="first">
<Rule>
<TextSymbolizer face-name="DejaVu Sans Book" size="18" label-position-tolerance="10" fill="#000000" halo-fill="#ffffff" halo-radius="1" dy="-10" allow-overlap="true" placement="point" placement-type="simple" ><![CDATA[[label]]]></TextSymbolizer>
</Rule>
</Style>
<Style name="layer0" filter-mode="first">
<Rule>
<MarkersSymbolizer fill-opacity="0.9" stroke="#ffffff" stroke-width="2" stroke-opacity="1" placement="point" marker-type="ellipse" width="16" fill="#cc3333" allow-overlap="true" />
</Rule>
</Style>
<Layer name="layer0"
srs="+init=epsg:{{=it.srid}}">
<StyleName>layer0</StyleName>
<StyleName>layer0-labels</StyleName>
<Datasource>
<Parameter name="type"><![CDATA[postgis]]></Parameter>
<Parameter name="user"><![CDATA[{{=it.dbuser}}]]></Parameter>
<Parameter name="password"><![CDATA[]]></Parameter>
<Parameter name="host"><![CDATA[{{=it.dbhost}}]]></Parameter>
<Parameter name="port"><![CDATA[{{=it.dbport}}]]></Parameter>
<Parameter name="dbname"><![CDATA[{{=it.dbname}}]]></Parameter>
<Parameter name="extent"><![CDATA[-20037508.3,-20037508.3,20037508.3,20037508.3]]></Parameter>
<Parameter name="row_limit"><![CDATA[0]]></Parameter>
<Parameter name="simplify_geometries"><![CDATA[true]]></Parameter>
<Parameter name="persist_connection"><![CDATA[false]]></Parameter>
<Parameter name="asynchronous_request"><![CDATA[false]]></Parameter>
<Parameter name="max_size"><![CDATA[500]]></Parameter>
<Parameter name="geometry_field"><![CDATA[{{=it.geometry_field}}]]></Parameter>
<Parameter name="srid"><![CDATA[{{=it.srid}}]]></Parameter>
<Parameter name="table"><![CDATA[({{=it.query}}) as cdbq]]></Parameter>
</Datasource>
</Layer>
</Map>
+2 -1
View File
@@ -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
+2 -2
View File
@@ -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"
}
}
},
+1 -1
View File
@@ -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"