Skip to content

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.

Copy link
Owner Author

commented Dec 15, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.