collectd-interface 0.3.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/collectd-interface-daemon +21 -361
- data/bin/collectd-interface-plugins +11 -11
- data/lib/collectd/interface/config.rb +117 -0
- data/lib/collectd/interface/options.rb +68 -0
- data/lib/collectd/interface/service/data.rb +110 -0
- data/lib/collectd/interface/service/graph.rb +106 -0
- data/lib/collectd/interface/service/report.rb +82 -0
- data/lib/collectd/interface/service.rb +44 -0
- data/public/images/cpus.png +0 -0
- data/public/images/device/ops/sda.png +0 -0
- data/public/images/device/ops/sda1.png +0 -0
- data/public/images/device/ops/sda2.png +0 -0
- data/public/images/device/ops/sda5.png +0 -0
- data/public/images/device/ops/sda6.png +0 -0
- data/public/images/device/ops/sda7.png +0 -0
- data/public/images/device/ops/sda8.png +0 -0
- data/public/images/device/ops/sda9.png +0 -0
- data/public/images/device/ops/sdb.png +0 -0
- data/public/images/device/ops/sdb1.png +0 -0
- data/public/images/device/ops/sdh.png +0 -0
- data/public/images/device/ops/sdh1.png +0 -0
- data/public/images/device/ops/sdh2.png +0 -0
- data/public/images/device/ops/sdh3.png +0 -0
- data/public/images/device/ops/sdh4.png +0 -0
- data/public/images/device/ops/sr0.png +0 -0
- data/public/images/device/time/sda.png +0 -0
- data/public/images/device/time/sda1.png +0 -0
- data/public/images/device/time/sda2.png +0 -0
- data/public/images/device/time/sda5.png +0 -0
- data/public/images/device/time/sda6.png +0 -0
- data/public/images/device/time/sda7.png +0 -0
- data/public/images/device/time/sda8.png +0 -0
- data/public/images/device/time/sda9.png +0 -0
- data/public/images/device/time/sdb.png +0 -0
- data/public/images/device/time/sdb1.png +0 -0
- data/public/images/device/time/sdh.png +0 -0
- data/public/images/device/time/sdh1.png +0 -0
- data/public/images/device/time/sdh2.png +0 -0
- data/public/images/device/time/sdh3.png +0 -0
- data/public/images/device/time/sdh4.png +0 -0
- data/public/images/device/time/sr0.png +0 -0
- data/public/images/device/traffic/sda.png +0 -0
- data/public/images/device/traffic/sda1.png +0 -0
- data/public/images/device/traffic/sda2.png +0 -0
- data/public/images/device/traffic/sda5.png +0 -0
- data/public/images/device/traffic/sda6.png +0 -0
- data/public/images/device/traffic/sda7.png +0 -0
- data/public/images/device/traffic/sda8.png +0 -0
- data/public/images/device/traffic/sda9.png +0 -0
- data/public/images/device/traffic/sdb.png +0 -0
- data/public/images/device/traffic/sdb1.png +0 -0
- data/public/images/device/traffic/sdh.png +0 -0
- data/public/images/device/traffic/sdh1.png +0 -0
- data/public/images/device/traffic/sdh2.png +0 -0
- data/public/images/device/traffic/sdh3.png +0 -0
- data/public/images/device/traffic/sdh4.png +0 -0
- data/public/images/device/traffic/sr0.png +0 -0
- data/public/images/irqs.png +0 -0
- data/public/images/load.png +0 -0
- data/public/images/memory.png +0 -0
- data/public/images/network/packets/eth0.png +0 -0
- data/public/images/network/packets/lo.png +0 -0
- data/public/images/network/packets/nbr0-nic.png +0 -0
- data/public/images/network/packets/nbr0.png +0 -0
- data/public/images/network/packets/virbr0.png +0 -0
- data/public/images/network/packets/vnet0.png +0 -0
- data/public/images/network/packets/vnet1.png +0 -0
- data/public/images/network/packets/vnet2.png +0 -0
- data/public/images/network/packets/vnet3.png +0 -0
- data/public/images/network/packets/vnet4.png +0 -0
- data/public/images/network/packets/vnet5.png +0 -0
- data/public/images/network/traffic/eth0.png +0 -0
- data/public/images/network/traffic/lo.png +0 -0
- data/public/images/network/traffic/nbr0-nic.png +0 -0
- data/public/images/network/traffic/nbr0.png +0 -0
- data/public/images/network/traffic/virbr0.png +0 -0
- data/public/images/network/traffic/vnet0.png +0 -0
- data/public/images/network/traffic/vnet1.png +0 -0
- data/public/images/network/traffic/vnet2.png +0 -0
- data/public/images/network/traffic/vnet3.png +0 -0
- data/public/images/network/traffic/vnet4.png +0 -0
- data/public/images/network/traffic/vnet5.png +0 -0
- data/public/images/processes.png +0 -0
- data/public/images/users.png +0 -0
- data/public/script/table_filter.js +1217 -0
- data/public/style/default.css +28 -0
- data/test/collectd/interface/config_test.rb +9 -0
- data/test/collectd/interface/service_config_test.rb +26 -0
- data/test/collectd/interface/service_data_test.rb +46 -0
- data/test/start.rb +3 -0
- data/views/graph_header.erb +13 -4
- data/views/graphs/device/ops.erb +37 -0
- data/views/graphs/device/time.erb +37 -0
- data/views/graphs/device/traffic.erb +38 -0
- data/views/graphs/{irq.erb.disabled → irqs.erb} +8 -8
- data/views/graphs/network/packets.erb +35 -0
- data/views/graphs/network/traffic.erb +35 -0
- data/views/graphs/{users.erb.disabled → users.erb} +0 -0
- data/views/report.erb +32 -14
- data/views/reports/open-files/local.erb +62 -0
- data/views/reports/{processes-cpu-usage.erb → processes.erb} +0 -0
- data/views/reports/{system-sockets.erb → sockets.erb} +0 -0
- data/views/reports/{disk-free.erb → storage.erb} +1 -1
- data/views/template/options/graph.erb +1 -1
- metadata +98 -30
- data/public/images/cpus.svg +0 -946
- data/public/images/disk-traffic-root.png +0 -0
- data/public/images/disk-traffic-srv.png +0 -0
- data/public/images/disk-traffic-tmp.png +0 -0
- data/public/images/disk-traffic-var.png +0 -0
- data/public/images/irq.png +0 -0
- data/public/images/load.svg +0 -638
- data/public/images/memory.svg +0 -741
- data/public/images/network-eth0.png +0 -0
- data/public/images/network-eth0.svg +0 -609
- data/public/images/network-lo.png +0 -0
- data/public/images/network-lo.svg +0 -644
- data/public/images/processes.svg +0 -832
- data/views/graphs/disk-traffic-root.erb +0 -24
- data/views/graphs/disk-traffic-srv.erb.disabled +0 -25
- data/views/graphs/disk-traffic-tmp.erb.disabled +0 -24
- data/views/graphs/disk-traffic-var.erb.disabled +0 -25
- data/views/graphs/network-eth0.erb +0 -23
- data/views/graphs/network-lo.erb +0 -23
- data/views/reports/list-open-files-lustre.erb.disabled +0 -44
- data/views/reports/list-open-files-tmp.erb +0 -44
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
module Collectd
|
3
|
+
module Interface
|
4
|
+
class Service < Sinatra::Base
|
5
|
+
# give the user an interface to select data from the Collectd
|
6
|
+
# RRD file stored on disk
|
7
|
+
get '/data' do
|
8
|
+
@data = settings.data
|
9
|
+
# client has selected a specific data source
|
10
|
+
if params.has_key?('display')
|
11
|
+
@target = params['display']
|
12
|
+
# this URI parameter needs to be removed for the redirect
|
13
|
+
params.delete('display')
|
14
|
+
# all other URI parameters will be passed on
|
15
|
+
p = Array.new; params.each_pair { |k,v| p << "#{k}=#{v}" }
|
16
|
+
@args = p.join('&')
|
17
|
+
# get the data
|
18
|
+
redirect "/data/#{@target}?#{@args}"
|
19
|
+
# REST style interface discovery to list all available data sources
|
20
|
+
elsif params.has_key?('format')
|
21
|
+
case params['format']
|
22
|
+
when 'json'
|
23
|
+
content_type :json
|
24
|
+
JSON.pretty_generate @data.map! { |d| "/data/#{d}" }
|
25
|
+
# present a clear text by default
|
26
|
+
else
|
27
|
+
content_type :plain
|
28
|
+
@data.join("\n")
|
29
|
+
end
|
30
|
+
# render the default view display the selection menu
|
31
|
+
else
|
32
|
+
@target = 'data'
|
33
|
+
erb :data, :layout => "template/default".to_sym
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# interface to the data source
|
37
|
+
get '/data/*' do |path|
|
38
|
+
redirect '/data' if path.empty?
|
39
|
+
# build the data sources file name
|
40
|
+
plugin,type,value = path.split("/")
|
41
|
+
file = "#{settings.rrd_path}/#{plugin}/#{type}.rrd"
|
42
|
+
unless File.exists? file
|
43
|
+
"Couldn't find source file #{file}"
|
44
|
+
else
|
45
|
+
data = Array.new
|
46
|
+
# construct the RRD query
|
47
|
+
# return average bu default
|
48
|
+
function = 'AVERAGE'
|
49
|
+
if params.has_key? 'function'
|
50
|
+
param = params['function'].upcase
|
51
|
+
if %w(AVERAGE MIN MAX).include? param
|
52
|
+
function = param
|
53
|
+
end
|
54
|
+
end
|
55
|
+
# build the command line to read the RRD file
|
56
|
+
command = "rrdtool fetch #{file} #{function}"
|
57
|
+
command << " --end Now --start Now-#{params['last']}" if params.has_key? 'last'
|
58
|
+
command << " --r #{params['resolution']}"if params.has_key? 'resolution'
|
59
|
+
# get the data
|
60
|
+
output = `#{command}`.split("\n")
|
61
|
+
# select the value of interest
|
62
|
+
headers = output.shift.split # remove header
|
63
|
+
key = headers.index(value)
|
64
|
+
output.delete_at 0 # remove empty line
|
65
|
+
# collect the data
|
66
|
+
output.each do |line|
|
67
|
+
line = line.delete(':').split
|
68
|
+
time = line[0].to_i
|
69
|
+
value = line[key+1].to_f # omit time stamp
|
70
|
+
lv = data[-1]
|
71
|
+
data << [time, value]
|
72
|
+
end
|
73
|
+
# remove most time wrong elements
|
74
|
+
data.slice!(0)
|
75
|
+
data.slice!(-1)
|
76
|
+
# filter values which are the same for multiple timestamps
|
77
|
+
final_data = []
|
78
|
+
data.each_index do |el|
|
79
|
+
cur_e = data[el][1]
|
80
|
+
if data[el-1] != nil and data[el+1] != nil and el != 0 and el != data.size-1
|
81
|
+
last_e = data[el-1][1]
|
82
|
+
next_e = data[el+1][1]
|
83
|
+
if cur_e != last_e or cur_e != next_e then
|
84
|
+
final_data.push(data[el])
|
85
|
+
end
|
86
|
+
else
|
87
|
+
final_data.push(data[el])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
data = final_data
|
91
|
+
if params.has_key? 'format'
|
92
|
+
if params['format'] == 'json'
|
93
|
+
content_type :json
|
94
|
+
json = {'name'=>"#{plugin} #{file}",'data'=>data}
|
95
|
+
JSON.pretty_generate json
|
96
|
+
else
|
97
|
+
content_type 'text/plain'
|
98
|
+
output = String.new
|
99
|
+
data.each { |line| output << "#{line[0]}: #{line[1..-1].join(' ')}\n" }
|
100
|
+
output
|
101
|
+
end
|
102
|
+
else
|
103
|
+
@data = data
|
104
|
+
erb :show_values
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Collectd
|
5
|
+
module Interface
|
6
|
+
class Service < Sinatra::Base
|
7
|
+
##
|
8
|
+
## Web-Interface to all graphs generated from the Collectd RRD files
|
9
|
+
##
|
10
|
+
get '/graph' do
|
11
|
+
# Clients can discover a list of available graphs using the
|
12
|
+
# format parameters
|
13
|
+
if params.has_key? 'format'
|
14
|
+
graph_list = settings.graphs.keys.sort.map! { |g| "/graph/#{g}" }
|
15
|
+
if params['format'] == 'json'
|
16
|
+
content_type :json
|
17
|
+
JSON.pretty_generate graph_list
|
18
|
+
else
|
19
|
+
content_type :text
|
20
|
+
graph_list.join("\n")
|
21
|
+
end
|
22
|
+
# By default the web-interface will be displayed
|
23
|
+
else
|
24
|
+
# by default each graph presents the last 12 hours
|
25
|
+
unless params.has_key? 'start' and params.has_key? 'end'
|
26
|
+
params['start'] = 'end-12h'
|
27
|
+
params['end'] = 'now'
|
28
|
+
end
|
29
|
+
params['image'] = 'png' unless params.has_key?('image')
|
30
|
+
# display only a subset of the graphs by default
|
31
|
+
unless params.has_key?('display')
|
32
|
+
params['display'] = [ 'cpus', 'memory', 'load', ]
|
33
|
+
end
|
34
|
+
# pass the list of graphs to display into the template
|
35
|
+
@display = params['display']
|
36
|
+
# remove it from the parameter list
|
37
|
+
params.delete('display') if params.has_key?('display')
|
38
|
+
# all other parameters will be appended for the graph
|
39
|
+
# generation.
|
40
|
+
p = Array.new; params.each_pair { |k,v| p << "#{k}=#{v}" }
|
41
|
+
@args = p.join('&')
|
42
|
+
# list of all available graphs for the drop down menu
|
43
|
+
@graphs = settings.graphs
|
44
|
+
# identifier for the template
|
45
|
+
@target = 'graph'
|
46
|
+
# render the templates
|
47
|
+
erb :graph, :layout => "template/default".to_sym
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
get '/graph/*' do |path|
|
52
|
+
unless settings.graphs.has_key? path
|
53
|
+
redirect '/'
|
54
|
+
else
|
55
|
+
# name of the template use to render the graph
|
56
|
+
_template = settings.graphs[path]
|
57
|
+
# path to the public directory to store the rendered image
|
58
|
+
_target_path = File.dirname(File.join(settings.public_folder,'images',path))
|
59
|
+
FileUtils.mkdir_p(_target_path) unless File.directory? _target_path
|
60
|
+
# variables available to the plug-in
|
61
|
+
@color = {
|
62
|
+
:red_light => '#FF000044', :red_dark => '#FF0000AA',
|
63
|
+
:green_light => '#00F00022', :green_dark => '#00F000AA',
|
64
|
+
:yellow_light => '#FFFF0022', :yellow_dark => '#FFFF00AA',
|
65
|
+
:blue_light => '#0000FF22', :blue_dark => '#0000FFAA',
|
66
|
+
:orange_light => '#FF450022', :orange_dark => '#FF4500AA',
|
67
|
+
:cyan_light => '#00FFFF22', :cyan_dark => '#00FFFFAA',
|
68
|
+
:purple_light => '#FF00FF22', :purple_dark => '#FF00FFAA'
|
69
|
+
}
|
70
|
+
@type = params.has_key?('image') ? params['image'] : 'png'
|
71
|
+
if params.has_key? 'start' and params.has_key? 'end'
|
72
|
+
@start = params['start']
|
73
|
+
@end = params['end']
|
74
|
+
else
|
75
|
+
@start = 'end-24h'
|
76
|
+
@end = 'now'
|
77
|
+
end
|
78
|
+
# clients can query custom sized graphs, without legend
|
79
|
+
@graph_only = false
|
80
|
+
if params.has_key?('width') and params.has_key?('height')
|
81
|
+
@width = params['width']
|
82
|
+
@height = params['height']
|
83
|
+
@graph_only = true
|
84
|
+
# default graph size
|
85
|
+
else
|
86
|
+
@width = 400
|
87
|
+
@height = 100
|
88
|
+
end
|
89
|
+
# name of the file to store the graph image into
|
90
|
+
@target = %Q[#{settings.public_folder}/images/#{path}.#{@type}]
|
91
|
+
# location of the Collectd RRD files
|
92
|
+
@rrd_path = settings.rrd_path + '/'
|
93
|
+
# last value of the URI path is parameter to the template
|
94
|
+
@param = path.split('/')[-1]
|
95
|
+
# run the plug-in the generate to image
|
96
|
+
command = erb :"graphs/#{_template}", :layout => :graph_header
|
97
|
+
puts command.chomp if $DEBUG
|
98
|
+
output = `#{command} > /dev/null 2>&1`
|
99
|
+
puts output.chomp if $DEBUG and not output.empty?
|
100
|
+
# redirect the client to the rendered image
|
101
|
+
redirect %Q[/images/#{path}.#{@type}]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'sinatra/base'
|
4
|
+
|
5
|
+
module Collectd
|
6
|
+
module Interface
|
7
|
+
class Service < Sinatra::Base
|
8
|
+
|
9
|
+
get '/report' do
|
10
|
+
@reports = settings.reports.keys.sort
|
11
|
+
# List all available path to reports
|
12
|
+
if params.has_key? 'format'
|
13
|
+
report_list = @reports.map! { |r| "/report/#{r}" }
|
14
|
+
if params['format'] == 'json'
|
15
|
+
content_type :json
|
16
|
+
JSON.pretty_generate report_list
|
17
|
+
else # default is plain text
|
18
|
+
content_type :text
|
19
|
+
report_list.join("\n")
|
20
|
+
end
|
21
|
+
# Render a HTML representation of all/one report(s)
|
22
|
+
else
|
23
|
+
# list of the URLs to requested all reports selected by the client query
|
24
|
+
_reports_selected = Array.new
|
25
|
+
# the default report to display
|
26
|
+
unless params.has_key? 'display'
|
27
|
+
_reports_selected << '/report/storage?format=html'
|
28
|
+
# when a selection is passed by URI parameter
|
29
|
+
else
|
30
|
+
_display = params['display']
|
31
|
+
# show all reports
|
32
|
+
if _display == 'all'
|
33
|
+
@reports.each do |path|
|
34
|
+
_reports_selected << "/report/#{path}?format=html"
|
35
|
+
end
|
36
|
+
# a report select by the client
|
37
|
+
else
|
38
|
+
not_fount unless settings.reports.has_key?(_display)
|
39
|
+
# query URL for this request
|
40
|
+
_reports_selected << "/report/#{_display}?format=html"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@target = 'report'
|
44
|
+
# actual reports requested by the client query
|
45
|
+
@reports_selected = Hash.new
|
46
|
+
_reports_selected.each do |path|
|
47
|
+
__uri = URI.parse("http://localhost:#{settings.port}#{path}")
|
48
|
+
@reports_selected[path] = Net::HTTP.get_response(__uri).body
|
49
|
+
end
|
50
|
+
erb :report, :layout => :'template/default'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
get '/report/*' do |path|
|
55
|
+
redirect '/report' if path.empty?
|
56
|
+
unless settings.reports.has_key?(path)
|
57
|
+
redirect '/report'
|
58
|
+
end
|
59
|
+
_template = settings.reports[path]
|
60
|
+
# user asks for a specific output format
|
61
|
+
if params.has_key?('format')
|
62
|
+
case params['format']
|
63
|
+
when 'json'
|
64
|
+
content_type :json
|
65
|
+
@type = 'json'
|
66
|
+
when 'html'
|
67
|
+
@type = 'html'
|
68
|
+
else
|
69
|
+
content_type :plain
|
70
|
+
@type = 'text'
|
71
|
+
end
|
72
|
+
else
|
73
|
+
content_type :plain
|
74
|
+
@type = 'text'
|
75
|
+
end
|
76
|
+
@param = path.split('/')[-1]
|
77
|
+
erb :"reports/#{_template}"
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'collectd/interface/config'
|
4
|
+
require 'collectd/interface/service/data'
|
5
|
+
require 'collectd/interface/service/graph'
|
6
|
+
require 'collectd/interface/service/report'
|
7
|
+
|
8
|
+
module Collectd
|
9
|
+
module Interface
|
10
|
+
class Service < Sinatra::Base
|
11
|
+
configure do
|
12
|
+
mime_type :json, 'application/json'
|
13
|
+
mime_type :plain, 'text/plain'
|
14
|
+
# read the configuration object and set the Sinatra defaults
|
15
|
+
set :root, Config.root
|
16
|
+
set :port, Config['service']['port']
|
17
|
+
set :rrd_path, Config['rrd_path']
|
18
|
+
set :public_folder, File.join(Config.root,'public')
|
19
|
+
set :static, true
|
20
|
+
set :environment, :production
|
21
|
+
set :graphs, Config['graphs']
|
22
|
+
set :data, Config['data']
|
23
|
+
set :reports, Config['reports']
|
24
|
+
end
|
25
|
+
get '/' do
|
26
|
+
redirect '/graph'
|
27
|
+
end
|
28
|
+
get '/config/:name' do
|
29
|
+
if settings.respond_to?(params[:name])
|
30
|
+
_data = settings.send(params[:name])
|
31
|
+
if %w(graphs reports data).include? params[:name]
|
32
|
+
content_type :json
|
33
|
+
JSON.pretty_generate(_data)
|
34
|
+
else
|
35
|
+
content_type :text
|
36
|
+
_data
|
37
|
+
end
|
38
|
+
else
|
39
|
+
not_found
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/public/images/cpus.png
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/public/images/load.png
CHANGED
Binary file
|
data/public/images/memory.png
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/public/images/processes.png
CHANGED
Binary file
|
data/public/images/users.png
CHANGED
Binary file
|