collectd-interface 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/README.md +134 -0
  2. data/bin/collectd-interface-daemon +401 -0
  3. data/bin/collectd-interface-plugins +95 -0
  4. data/graphs/cpus.erb +76 -0
  5. data/graphs/disk-traffic-root.erb +30 -0
  6. data/graphs/disk-traffic-srv.erb.disabled +30 -0
  7. data/graphs/disk-traffic-tmp.erb.disabled +30 -0
  8. data/graphs/disk-traffic-var.erb.disabled +30 -0
  9. data/graphs/gridengine-jobs.erb.disabled +32 -0
  10. data/graphs/load.erb +36 -0
  11. data/graphs/memory.erb +47 -0
  12. data/graphs/network-eth0.erb +26 -0
  13. data/graphs/network-lo.erb +26 -0
  14. data/graphs/processes.erb +66 -0
  15. data/public/images/cpus.png +0 -0
  16. data/public/images/cpus.svg +946 -0
  17. data/public/images/disk-traffic-root.png +0 -0
  18. data/public/images/disk-traffic-srv.png +0 -0
  19. data/public/images/disk-traffic-var.png +0 -0
  20. data/public/images/load.png +0 -0
  21. data/public/images/load.svg +638 -0
  22. data/public/images/memory.png +0 -0
  23. data/public/images/memory.svg +741 -0
  24. data/public/images/network-eth0.png +0 -0
  25. data/public/images/network-eth0.svg +609 -0
  26. data/public/images/network-lo.png +0 -0
  27. data/public/images/network-lo.svg +644 -0
  28. data/public/images/processes.png +0 -0
  29. data/public/images/processes.svg +832 -0
  30. data/public/readme/user-interface.png +0 -0
  31. data/public/script/toggle.js +9 -0
  32. data/public/style/default.css +275 -0
  33. data/public/style/nav.css +265 -0
  34. data/views/README.md +134 -0
  35. data/views/data.erb +3 -0
  36. data/views/graph.erb +19 -0
  37. data/views/readme.erb +3 -0
  38. data/views/report.erb +17 -0
  39. data/views/reports/disk-free.erb +20 -0
  40. data/views/reports/list-open-files-lustre.erb.disabled +44 -0
  41. data/views/reports/list-open-files-tmp.erb +44 -0
  42. data/views/reports/processes-cpu-usage.erb +39 -0
  43. data/views/reports/system-sockets.erb +32 -0
  44. data/views/show_values.erb +11 -0
  45. data/views/template/default.erb +21 -0
  46. data/views/template/header.erb +3 -0
  47. data/views/template/navigation.erb +9 -0
  48. data/views/template/options/data.erb +31 -0
  49. data/views/template/options/graph.erb +23 -0
  50. data/views/template/options/readme.erb +0 -0
  51. data/views/template/options/report.erb +11 -0
  52. metadata +128 -0
data/views/README.md ADDED
@@ -0,0 +1,134 @@
1
+ Created 10 Feb 2012 -- Last change 14 Feb 2012
2
+ By Victor Penso
3
+
4
+ Description
5
+ ===========
6
+
7
+ _Collectd-Interface_ serves a web user-interface to data stored
8
+ by [Collectd](http://collectd.org/). Furthermore it provides REST
9
+ access to all data.
10
+
11
+ Installation
12
+ ============
13
+
14
+ Download and install Collectd following the instructions
15
+ from the developers.
16
+
17
+ On Debian flavored Linux use:
18
+
19
+ apt-get install collectd rrdtool
20
+
21
+ You will need the [RRDtool](http://oss.oetiker.ch/rrdtool/) too.
22
+
23
+ Usage
24
+ =====
25
+
26
+ Get help:
27
+
28
+ collectd-interface-daemon --help
29
+
30
+ Start the Collectd Interface in fore-ground:
31
+
32
+ collectd-interface-daemon
33
+
34
+ Open the web-interface <a href='localhost:4567'>localhost:4567</a>.
35
+
36
+ Start the Collectd Interface as daemon:
37
+
38
+ collectd-interface-daemon -p 5000 -l /var/log/ -P /var/run/ &
39
+
40
+
41
+ Interfaces
42
+ ==========
43
+
44
+ Collectd-Interface servers three different kinds of output:
45
+
46
+ 1. `/graph` is the user-interface showing line charts of many
47
+ of the data accumulated by Collectd.
48
+ 2. `/report` presents tables of system specific information
49
+ like disk capacity of a list of network sockets.
50
+ 3. `/data` servers an REST API to all data available from
51
+ Collectd.
52
+
53
+ All content from `/graph`, `/report` and `/data` is accessible
54
+ by a REST interface, to allow embedding this content into other
55
+ applications.
56
+
57
+ Graph
58
+ -----
59
+
60
+ ![Screenshot of User-Interface](https://github.com/vpenso/collectd-interface/raw/master/public/readme/user-interface.png "Screenshot of the User-Interface")
61
+
62
+ You can select individual graphs using the drop-down menu followed by
63
+ clicking the "Show" button. In case you just want to have the image, to
64
+ embed it into another web-page, use the links beneath the graph.
65
+
66
+ Once the graph is generated the caller will be redirected to `/image/`.
67
+
68
+ **Parameters**
69
+
70
+ It is possible to limit the time-frame of the graph using the option
71
+ `last=10h`(us (m)inutes,(d)ays or (w)eeks).
72
+
73
+ This simple example:
74
+
75
+ http://.../memory?last=1w&image=svg
76
+
77
+ Requests an SVG image with the memory graph for the last week.
78
+
79
+ **Plugin**
80
+
81
+ You can create add a custom graph rendering data from Collectd
82
+ by creating a template which is used to generate the <tt>rrdtool graph</tt>.
83
+ Take a look to the <tt>graphs/</tt> and <tt>disabled/graphs/</tt> directories
84
+ for examples. I recommend you the start the Collectd-Interface in
85
+ debug mode (option <tt>-d</tt>) while you develop new graph templates.
86
+
87
+ In case you want to enable graphs from <tt>disabled/graphs/</tt> create
88
+ a soft link from <tt>graphs/</tt>. The <tt>collectd-interface</tt> daemon will
89
+ automatically recognize new templates within <tt>graphs</tt> on start.
90
+
91
+ Report
92
+ ------
93
+
94
+ Reports a basically wrappers around commands like <tt>df -l</tt> or
95
+ <tt>ss -ar</tt>. The output is available as HTML in the "Report" section
96
+ of the user-interface.
97
+
98
+ TODO
99
+
100
+ Data
101
+ ----
102
+
103
+ List all available values <a href="/data/">/data/</a> from
104
+ Collectd. Get the time-series of a specific value.
105
+
106
+ http://.../data/interface/if_packets-eth0/rx
107
+
108
+ By default the severs will answer with averages
109
+ of all data-points and an HTML document.
110
+
111
+ **Parameters**
112
+
113
+ http://.../value?last=36h&resolution=3600
114
+
115
+ Request only values from the last 36 hours, with a
116
+ data point resolution of 1 hour (3600 seconds).
117
+ Default resolution is the highest possible and you
118
+ will get by default values of the last 24 hours.
119
+ In the time specification you can also use (w)eeks,
120
+ (d)ays and (m)inutes.
121
+
122
+ http://.../rx?function=max&format=json
123
+
124
+ Request the maximum of all data points for the past
125
+ in the JSON format. Other consolidation functions
126
+ are average (default) and min, for the smallest value
127
+ in a time-frame.
128
+
129
+
130
+ Copying
131
+ =======
132
+
133
+ Copyright 2011 Victor Penso
134
+ License [GPLv3](http://www.gnu.org/licenses/gpl-3.0.html) (see LICENSE file)
data/views/data.erb ADDED
@@ -0,0 +1,3 @@
1
+ <script>
2
+ window.onload=toggle();
3
+ </script>
data/views/graph.erb ADDED
@@ -0,0 +1,19 @@
1
+ <ul>
2
+ <% if @display.first == 'all' then %>
3
+ <% @graphs.keys.sort.each do |name| %>
4
+ <% url = "/graph/#{name}?#{@args}" %>
5
+ <li>
6
+ <img src="<%= url %>"/><br/>
7
+ <a href="<%= url %>"><%= url %></a>
8
+ </li>
9
+ <% end %>
10
+ <% else %>
11
+ <% @display.each do |graph| %>
12
+ <% url = "/graph/#{graph}?#{@args}"%>
13
+ <li>
14
+ <img src="<%= url %>"/><br/>
15
+ <a href="<%= url %>"><%= url %></a>
16
+ </li>
17
+ <% end%>
18
+ <% end %>
19
+ </ul>
data/views/readme.erb ADDED
@@ -0,0 +1,3 @@
1
+ <div class="docs">
2
+ <%= markdown(:README) %>
3
+ </div>
data/views/report.erb ADDED
@@ -0,0 +1,17 @@
1
+ <ul style='list-style-type:none; padding-left:0'>
2
+ <% if @display == 'all' %>
3
+ <% for val in @reports %>
4
+ <li>
5
+ <%= erb("/reports/#{val}".to_sym) %>
6
+ <% url = "/report/#{val}?format=json" %>
7
+ <a href="<%= url %>"><%= url %></a>
8
+ </li>
9
+ <% end %>
10
+ <% else %>
11
+ <li>
12
+ <%= erb("/reports/#{@display}".to_sym)%>
13
+ <% url = "/report/#{@display}?format=json" %>
14
+ <a href="<%= url%>"><%= url %></a>
15
+ </li>
16
+ <% end %>
17
+ </ul>
@@ -0,0 +1,20 @@
1
+ <% require 'json'
2
+ content = `df -lh`.split("\n")
3
+ if @type == 'text' then %><%= content.join("\n") %>
4
+ <% elsif @type == 'json'
5
+ keys = content[0].chop.chop.split.map! { |v| v.downcase }
6
+ json = Array.new
7
+ content[1..-1].each { |values| json << Hash[*keys.zip(values.split).flatten] } %><%= JSON.pretty_generate json %>
8
+ <% else %>
9
+ <div style="font-size:160%"><strong>Local Storage</strong></div>
10
+ <table>
11
+ <thead>
12
+ <tr><th><%= content[0].chop.chop.split.join('</th><th>') %></th></tr>
13
+ </thead>
14
+ <tbody>
15
+ <% content[1..-1].each do |line| %>
16
+ <tr><td><%= line.split.join('</td><td>') %></td></tr>
17
+ <% end %>
18
+ </tbody>
19
+ </table>
20
+ <% end %>
@@ -0,0 +1,44 @@
1
+ <% path = '/lustre' %>
2
+ <% content = `lsof -u ^root -S2 #{path} | tr -s ' ' | cut -d' ' -f2-4,9-` %>
3
+ <% if @type == 'text' then %>
4
+ <%= content %>
5
+ <% elsif @type == 'json' %>
6
+ <% require 'json' %>
7
+ <% struct = Array.new %>
8
+ <% content = content.split("\n")[1..-1] %>
9
+ <% keys = ['pid','user','state','file'] %>
10
+ <% unless content.empty? %>
11
+ <% content.each do |file| %>
12
+ <% file = file.split %>
13
+ <% values = file[0..2] %>
14
+ <% values << file[3..-1].join(' ') %>
15
+ <% struct << Hash[*keys.zip(values).flatten] %>
16
+ <% end %>
17
+ <% end %>
18
+ <%= JSON.pretty_generate struct %>
19
+ <% else %>
20
+ <div style="font-size:160%"><strong>Open Files in Lustre</strong></div>
21
+ <table>
22
+ <thead>
23
+ <tr>
24
+ <td>Process&nbsp;ID</td>
25
+ <td>User</td>
26
+ <td>State</td>
27
+ <td>File</td>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <% if content.empty? %>
32
+ <tr><td>none</td><td>none</td><td>none</td><td>none</td></tr>
33
+ <% else %>
34
+ <% content.split("\n")[1..-1].each do |file| %>
35
+ <% file = file.split%>
36
+ <tr>
37
+ <td><%= file[0..2].join('</td><td>') %></td>
38
+ <td><span style="font-size:80%"><%= file[3..-1].join(' ')%></span></td>
39
+ </tr>
40
+ <% end %>
41
+ <% end %>
42
+ </tbody>
43
+ </table>
44
+ <% end %>
@@ -0,0 +1,44 @@
1
+ <% path = '/tmp' %>
2
+ <% content = `lsof -u ^root -S2 #{path} | tr -s ' ' | cut -d' ' -f2-4,9-` %>
3
+ <% if @type == 'text' then %>
4
+ <%= content %>
5
+ <% elsif @type == 'json' %>
6
+ <% require 'json' %>
7
+ <% struct = Array.new %>
8
+ <% content = content.split("\n")[1..-1] %>
9
+ <% keys = ['pid','user','state','file'] %>
10
+ <% unless content.empty? %>
11
+ <% content.each do |file| %>
12
+ <% file = file.split %>
13
+ <% values = file[0..2] %>
14
+ <% values << file[3..-1].join(' ') %>
15
+ <% struct << Hash[*keys.zip(values).flatten] %>
16
+ <% end %>
17
+ <% end %>
18
+ <%= JSON.pretty_generate struct %>
19
+ <% else %>
20
+ <div style="font-size:160%"><strong>Open Files in Temp</strong></div>
21
+ <table>
22
+ <thead>
23
+ <tr>
24
+ <td>Process&nbsp;ID</td>
25
+ <td>User</td>
26
+ <td>State</td>
27
+ <td>File</td>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <% if content.empty? %>
32
+ <tr><td>none</td><td>none</td><td>none</td><td>none</td></tr>
33
+ <% else %>
34
+ <% content.split("\n")[1..-1].each do |file| %>
35
+ <% file = file.split%>
36
+ <tr>
37
+ <td><%= file[0..2].join('</td><td>') %></td>
38
+ <td><span style="font-size:80%"><%= file[3..-1].join(' ')%></span></td>
39
+ </tr>
40
+ <% end %>
41
+ <% end %>
42
+ </tbody>
43
+ </table>
44
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <% content = `ps -d -o pid,user,pcpu,pmem,state,time,args --sort pcpu | sed '/^ 0.0 /d' | tail -n 30` %>
2
+ <% if @type == 'text' then %>
3
+ <%= content.split("\n").reverse.join("\n") %>
4
+ <% elsif @type == 'json' %>
5
+ <% content = content.split("\n")[1..-1].reverse %>
6
+ <% keys = ['pid','user','cpu_percent','mem_percent','state','cpu_time','command'] %>
7
+ <% require 'json'; struct = Array.new %>
8
+ <% content.each do |process| %>
9
+ <% process = process.split %>
10
+ <% values = process[0..5] %>
11
+ <% values << process[6..-1].join(' ') %>
12
+ <% struct << Hash[*keys.zip(values).flatten] %>
13
+ <% end%>
14
+ <%= JSON.pretty_generate struct %>
15
+ <% else %>
16
+ <div style="font-size:160%"><strong>Process CPU Usage</strong></div>
17
+ <table>
18
+ <thead>
19
+ <tr>
20
+ <th>Process&nbsp;ID</th>
21
+ <th>User</th>
22
+ <th>CPU&nbsp;%</th>
23
+ <th>Memory&nbsp;%</th>
24
+ <th>State</th>
25
+ <th>CPU&nbsp;Time</th>
26
+ <th>Command</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <% content.split("\n")[1..-1].reverse.each do |process| %>
31
+ <% process = process.split %>
32
+ <tr>
33
+ <td><%= process[0..5].join('</td><td>') %></td>
34
+ <td><span style="font-size:80%"><%= process[6..-1].join(' ')%></span></td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ </table>
39
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <% content = `ss -ar` %>
2
+ <% if @type == 'text' then %>
3
+ <%= content %>
4
+ <% elsif @type == 'json' %>
5
+ <% content = content.split("\n")[1..-1] %>
6
+ <% keys = ['state','recive_queue','send_queue','local_address','peer_address'] %>
7
+ <% require 'json'; struct = Array.new %>
8
+ <% content.each do |values| %>
9
+ <% struct << Hash[*keys.zip(values.split).flatten] %>
10
+ <% end %>
11
+ <%= JSON.pretty_generate struct %>
12
+ <% else %>
13
+ <div style="font-size:160%"><strong>System Sockets</strong></div>
14
+ <table>
15
+ <thead>
16
+ <tr>
17
+ <th>State</td>
18
+ <th>Recv-Q</th>
19
+ <th>Send-Q</th>
20
+ <th>Local Address:Port</th>
21
+ <th>Peer Address:Port</th>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ <% content.split("\n")[1..-1].each do |line| %>
26
+ <tr>
27
+ <td><%= line.split.join("</td>\n<td>") %></td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+ </table>
32
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <table>
6
+ <% for entry in @data %>
7
+ <tr><td><b><%= entry[0] %></b></td><td><%= entry[1..-1].join(' ')%></td></tr>
8
+ <% end %>
9
+ </table>
10
+ </body>
11
+ </html>
@@ -0,0 +1,21 @@
1
+ <html>
2
+ <head>
3
+ <%= erb "template/header".to_sym %>
4
+ <title><%= @target.capitalize %></title>
5
+ </head>
6
+ <body>
7
+ <form action="/<%= @target %>" method='get' style="top">
8
+ <%= erb "template/navigation".to_sym %>
9
+ <div id="toggle" class="options">
10
+ <%= erb "template/options/#{@target}".to_sym %>
11
+ <div class="submitter">
12
+ <button class="primary" type="submit"/>Show</button>
13
+ <button type="button" onClick="toggleCancel()">Cancel</button>
14
+ </div>
15
+ </div>
16
+ </form>
17
+ <div class='content'>
18
+ <%= yield %>
19
+ </div>
20
+ </body>
21
+ </html>
@@ -0,0 +1,3 @@
1
+ <link href='style/default.css' rel='stylesheet' type='text/css'>
2
+ <link href='style/nav.css' rel='stylesheet' type='text/css'>
3
+ <script src="script/toggle.js" type="text/javascript"></script>
@@ -0,0 +1,9 @@
1
+ <div class="navigation">
2
+ <ul>
3
+ <li><a href="/graph">Graph</a></li>
4
+ <li><a href='/data'>Data</a></li>
5
+ <li><a href='/report'>Report</a></li>
6
+ <li><a href='/help'>Help</a></li>
7
+ </ul>
8
+ <button type="button" onClick="toggle()">&#8595;</button>
9
+ </div>
@@ -0,0 +1,31 @@
1
+ <ul>
2
+ <li>
3
+ <div class="label">Select data source:</div>
4
+ <select name="display">
5
+ <% for source in @data %>
6
+ <option><%= source %></option>
7
+ <% end %>
8
+ </select>
9
+ </li>
10
+ <li>
11
+ <div class="label">Select output format:</div>
12
+ <select name="format">
13
+ <option>text</option>
14
+ <option>json</option>
15
+ </select>
16
+ </li>
17
+ <li>
18
+ <div class="label">Values of the last:</div>
19
+ <input type="text" name="last" value="12h"/>
20
+ <div class="explain">(s)econds (h)ours (d)ays (w)eeks</div>
21
+ </li>
22
+ <li>
23
+ <div class="label">Data accumulation function:</div>
24
+ <select name="function">
25
+ <option>max</option>
26
+ <option>min</option>
27
+ <option>average</option>
28
+ <option>last</option>
29
+ </select>
30
+ </li>
31
+ </ul>