collectd-interface 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>