Instantly share code, notes, and snippets.

Embed
What would you like to do?
Real-time monitor (Server-Sent Events)
#!/usr/bin/env ruby
require 'sinatra/base'
SECONDS_INTERVAL = 1.0
URL_STREAM = '/stream'
NAME_EVENT = 'ldavg'
NUMBER_MAX_PLOT = 180
SEPARATOR_OF_DATA = ' '
app = Sinatra.new do
# server has to support streaming
set :server, :thin
# exchange data with each requests via this buffer
set :my_data, ''
# client of EventSource requests here
get URL_STREAM do
content_type 'text/event-stream'
stream(:keep_open) do |out|
loop {
break if out.closed?
out << "event: #{NAME_EVENT}\n"
out << "data: #{settings.my_data}\n"
out << "\n"
sleep SECONDS_INTERVAL
}
end
end
# show HTML
get '/' do
erb <<-'HTML'
<h1>Live</h1>
<div id="chart" style="height: 280px; padding: 2em;"></div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
$(function (){
$(document).ready(function (){
Highcharts.setOptions({
global: { useUTC: false }
});
$('#chart').highcharts({
chart: { type: 'spline' },
title: { text: 'Load Averages' },
xAxis: { type: 'datetime' },
yAxis: { title: null },
series: [
{ name: '1 min', data: [] },
{ name: '5 min', data: [] },
{ name: '15 min', data: [] }
]
});
var es = new EventSource('<%= URL_STREAM %>');
es.addEventListener('<%= NAME_EVENT %>', function (ev){
var values = ev.data.split('<%= SEPARATOR_OF_DATA %>');
var epoch = values.shift();
console.log(values);
var chart = $('#chart').highcharts();
var x = new Date(parseInt(epoch) * 1000);
for(var i=0,l=chart.series.length; i<l; ++i){
var series = chart.series[i];
var y = parseFloat(values[i]);
var to_shift = <%= NUMBER_MAX_PLOT %> < series.data.length ? true : false;
console.log('x=['+ x +'] y=['+ y +'] shift=['+ to_shift +']');
series.addPoint({x: x, y: y}, true, to_shift);
}
});
});
});
</script>
HTML
end
# start background service
service = Thread.new {
command = 'uptime'
loop {
epoch = `date +%s`.chomp;
line = `#{command}` #.split("\n").first
data = [epoch, '-', '-', '-']
if line =~ /.*: ([.\d]+)\D+([.\d]+)\D+([.\d]+)\D*$/
data = [epoch, $1, $2, $3]
end
# update buffer
self.my_data = data.join(SEPARATOR_OF_DATA)
# interval
sleep SECONDS_INTERVAL
}
}
end
app.set :port, ARGV[0] || 9000
app.set :bind, ARGV[1] || '0.0.0.0'
app.run!
@hiroaki

This comment has been minimized.

Owner

hiroaki commented Dec 15, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment