elasticsearch-watchdog
Version:
A watchdog of elasticsearch - cluster nodes' statuses monitor, auto restart, keep PRIMARY node unique.
127 lines (110 loc) • 3.47 kB
JavaScript
window.addEventListener('load', function () {
d3.json('/json', function (err, data) {
if (err) {
return error(err);
}
if (!data || data.length == 0 || Object.keys(data).length == 0) {
return error('No data was found.');
}
var root = {name:'Watchdog', status:'green', children:[]};
data.forEach(function (d) {
var children = [];
if (d.data.timestamp) {
children.push({name:fromNow(d.data.timestamp) + ' ago', status:'grey'});
}
var health = d.data.health, state = d.data.state;
if ((!health || Object.keys(health) == 0) && (!state || Object.keys(state) == 0)) {
return children.push({name:'no data', status:'red'});
}
if (!state && health) {
for (var k in health) {
children.push({name:k, status:health[k]});
}
} else if (state) {
health = health || {};
for (var k in state) {
var _children = [];
state[k].forEach(function (s) {
_children.push({name:s, status:health[s] || 'unknown'})
});
children.push({name:k, status:health[k] || 'unknown', children:_children});
}
}
root.children.push({name:d.name, status:'green', children:children});
});
renderCluster(root);
});
});
function renderCluster(root) {
var body = d3.select('body'),
width = parseInt(body.style('width')) * 0.5,
height = parseInt(body.style('height')) * 0.5;
width = Math.max(960, width);
height = Math.max(640, height);
body.html('');
var cluster = d3.layout.cluster()
.size([height, width - (root.name.length + 18) * 6 - 100]);
var diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.y, d.x];
});
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(100,0)');
var nodes = cluster.nodes(root),
links = cluster.links(nodes);
var link = svg.selectAll('.link')
.data(links)
.enter().append('path')
.attr('class', 'link')
.attr('d', diagonal);
var node = svg.selectAll('.node')
.data(nodes)
.enter().append('g')
.attr('class', 'node')
.attr('transform', function (d) {
return 'translate(' + d.y + ',' + d.x + ')';
})
node.append('circle')
.style('stroke', fillColor)
.attr('r', 5);
node.append('text')
.attr('dx', function (d) {
return d.children ? -10 : 10;
})
.attr('dy', 4)
.style('text-anchor', function (d) {
return d.children ? 'end' : 'start';
})
.style('fill', fillColor)
.attr()
.text(function (d) {
return d.name + (!!~['red', 'yellow', 'grey', 'green'].indexOf(d.status) ? '' : '[' + d.status + ']')
});
}
function fillColor(d){
var color = (!!~['red', 'yellow', 'grey', 'green'].indexOf(d.status) ? d.status : 'red');
color == 'yellow' && (color = '#a0a000');
return color;
}
function fromNow(tick) {
tick = Date.now() - tick;
if (tick < 1e3) {
return tick + 'ms';
}
tick = parseInt(tick / 1e3);
if (tick < 60) {
return tick + 's';
}
var s = tick % 60 + 's';
if (tick < 3600) {
return parseInt(tick / 60) + 'm' + s
}
var m = parseInt((tick % 3600) / 60) + 'm'
return parseInt(tick / 3600) + 'h' + m + s;
}
function error(msg) {
d3.select('body').html('<label class="text-danger">' + (msg || 'Can not load data from server.') + '</label>');
}