collectd-plot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ collectd-plot (0.0.1)
5
+ errand (= 0.7.3)
6
+ gnuplot (= 2.4.1)
7
+ haml (= 3.1.4)
8
+ librrd (= 1.0.2)
9
+ sinatra (= 1.3.2)
10
+ tilt (= 1.3.3)
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ builder (3.0.0)
16
+ colorize (0.5.8)
17
+ cucumber (1.1.9)
18
+ builder (>= 2.1.2)
19
+ diff-lcs (>= 1.1.2)
20
+ gherkin (~> 2.9.0)
21
+ json (>= 1.4.6)
22
+ term-ansicolor (>= 1.0.6)
23
+ diff-lcs (1.1.3)
24
+ errand (0.7.3)
25
+ gherkin (2.9.1)
26
+ json (>= 1.4.6)
27
+ gnuplot (2.4.1)
28
+ haml (3.1.4)
29
+ json (1.6.5)
30
+ librrd (1.0.2)
31
+ nokogiri (1.5.2)
32
+ rack (1.4.1)
33
+ rack-protection (1.2.0)
34
+ rack
35
+ rack-test (0.6.1)
36
+ rack (>= 1.0)
37
+ rspec (2.9.0)
38
+ rspec-core (~> 2.9.0)
39
+ rspec-expectations (~> 2.9.0)
40
+ rspec-mocks (~> 2.9.0)
41
+ rspec-core (2.9.0)
42
+ rspec-expectations (2.9.0)
43
+ diff-lcs (~> 1.1.3)
44
+ rspec-mocks (2.9.0)
45
+ shotgun (0.9)
46
+ rack (>= 1.0)
47
+ sinatra (1.3.2)
48
+ rack (~> 1.3, >= 1.3.6)
49
+ rack-protection (~> 1.2)
50
+ tilt (~> 1.3, >= 1.3.3)
51
+ term-ansicolor (1.0.7)
52
+ tilt (1.3.3)
53
+ webrat (0.7.3)
54
+ nokogiri (>= 1.2.0)
55
+ rack (>= 1.0)
56
+ rack-test (>= 0.5.3)
57
+
58
+ PLATFORMS
59
+ ruby
60
+
61
+ DEPENDENCIES
62
+ collectd-plot!
63
+ colorize
64
+ cucumber
65
+ rack-test
66
+ rspec
67
+ shotgun
68
+ webrat
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+
2
+ # Overview
3
+
4
+ Collectd-Plot is a web interface for Collectd,
5
+ which plots data from RRD files using Gnuplot.
6
+
7
+ # Installation
8
+
9
+ TODO
10
+
11
+ # Development
12
+
13
+ TODO
@@ -0,0 +1,34 @@
1
+ #
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "collectd-plot"
6
+ s.version = "0.0.1"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = [ "Tim Miller" ]
9
+ s.email = [ "" ]
10
+ s.homepage = "https://github.com/echohead/collectd-plot"
11
+ s.summary = %q{A web interface for Collectd}
12
+ s.description = %q{Plot collectd data using gnuplot, with useful features such as host globbing.}
13
+
14
+ s.required_ruby_version = ">= 1.9.1"
15
+ s.required_rubygems_version = ">= 1.3.7"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_runtime_dependency "haml", "= 3.1.4"
23
+ s.add_runtime_dependency "tilt", "= 1.3.3"
24
+ s.add_runtime_dependency "sinatra", "= 1.3.2"
25
+ s.add_runtime_dependency "errand", "= 0.7.3"
26
+ s.add_runtime_dependency "librrd", "= 1.0.2"
27
+ s.add_runtime_dependency "gnuplot", "= 2.4.1"
28
+ s.add_development_dependency "shotgun", ">= 0"
29
+ s.add_development_dependency "rack-test", ">= 0"
30
+ s.add_development_dependency "rspec", ">= 0"
31
+ s.add_development_dependency "cucumber", ">= 0"
32
+ s.add_development_dependency "webrat", ">= 0"
33
+ s.add_development_dependency "colorize", ">= 0"
34
+ end
@@ -0,0 +1,60 @@
1
+ $: << File.dirname(__FILE__)
2
+ require 'sinatra'
3
+ require 'haml'
4
+ require 'collectd-plot/rrd_read'
5
+ require 'collectd-plot/plot'
6
+ require 'collectd-plot/plot_properties'
7
+
8
+ module CollectdPlot
9
+
10
+ helpers do
11
+ def link_to url_fragment, mode=:path_only
12
+ case mode
13
+ when :path_only
14
+ base = request.script_name
15
+ when :full_url
16
+ if (request.scheme == 'http' && request.port == 80 ||
17
+ request.scheme == 'https' && request.port == 443)
18
+ port = ""
19
+ else
20
+ port = ":#{request.port}"
21
+ end
22
+ base = "#{request.scheme}://#{request.host}#{port}#{request.script_name}"
23
+ else
24
+ raise "Unknown script_url mode #{mode}"
25
+ end
26
+ "#{base}#{url_fragment}"
27
+ end
28
+ end
29
+
30
+ get '/' do
31
+ @hosts = RRDRead.list_hosts
32
+ haml :index
33
+ end
34
+
35
+ get '/hosts/:h' do |h|
36
+ @host = h
37
+ @metrics = RRDRead.list_metrics_for(@host)
38
+ haml :host
39
+ end
40
+
41
+ get '/hosts/:h/metric/:m' do |h, m|
42
+ content_type 'image/png'
43
+ props = PlotProperties.new(:host => h, :metric => m)
44
+ data = RRDRead.get_data(props)
45
+ Plot.render(data, props)
46
+ end
47
+
48
+ get '/plot' do
49
+ content_type 'image/png'
50
+ props = PlotProperties.new(params)
51
+ data = RRDRead.get_data(props)
52
+ Plot.render(data, props)
53
+ end
54
+
55
+ get '/sandbox' do
56
+ content_type 'image/png'
57
+ CollectdPlot::Plot.example
58
+ end
59
+
60
+ end
@@ -0,0 +1,91 @@
1
+ require 'gnuplot'
2
+
3
+ module CollectdPlot
4
+ module Plot
5
+
6
+ def self.rand_filename()
7
+ "/tmp/#{(0...10).map{65.+(rand(25)).chr}.join}.png"
8
+ end
9
+
10
+
11
+ def self.render(data, props)
12
+ cmd = ''
13
+ png_file = rand_filename
14
+ Gnuplot::Plot.new(cmd) do |plot|
15
+ plot.terminal 'png'
16
+ plot.output png_file
17
+
18
+ #plot.xrange '[0:10]'
19
+ plot.title "#{props.metric} for #{props.host}"
20
+ plot.grid
21
+ plot.xrange "[#{props.start}:#{props.finish}]"
22
+ x = (props.start.to_i..props.finish.to_i).to_a
23
+
24
+ data.each_pair do |h, d|
25
+ plot.data << Gnuplot::DataSet.new( [x, d] ) do |ds|
26
+ ds.linewidth = 4
27
+ ds.title = props.host
28
+ end
29
+ end
30
+ end
31
+ cmd << "\n\n\n"
32
+
33
+ script = rand_filename
34
+ File.open(script, 'w') { |f| f.write cmd }
35
+ puts `gnuplot #{script}`
36
+ puts `cat #{script} > gnuplot`
37
+ f = File.open(png_file, "rb")
38
+ png = f.read
39
+ f.close
40
+ File.delete png_file
41
+ File.delete script
42
+ png
43
+ end
44
+
45
+
46
+ def self.example
47
+ cmd = ''
48
+ png_file = rand_filename
49
+ Gnuplot::Plot.new(cmd) do |plot|
50
+ plot.terminal "png"
51
+ plot.output png_file
52
+
53
+ plot.xrange "[0:10]"
54
+ plot.title "Sin Wave Example"
55
+ plot.xlabel "x"
56
+ plot.ylabel "y"
57
+ plot.grid
58
+
59
+ x = (0..50).collect { |v| v.to_f }
60
+ y = x.collect { |v| v ** 2 }
61
+ z = x.collect { |v| v * Math.sin(v) }
62
+
63
+ plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
64
+ ds.with = "linespoints"
65
+ ds.title = "quadratic"
66
+ ds.linewidth = 4
67
+ end
68
+ plot.data << Gnuplot::DataSet.new( [x, z] ) do |ds|
69
+ ds.with = "linespoints"
70
+ ds.title = "linear"
71
+ ds.linewidth = 4
72
+ end
73
+ # plot.data << Gnuplot::DataSet.new( "sin(x)" ) do |ds|
74
+ # ds.with = "lines"
75
+ # end
76
+ end
77
+ cmd << "\n\n\n"
78
+
79
+ script = rand_filename
80
+ File.open(script, 'w') { |f| f.write cmd }
81
+ puts `gnuplot #{script}`
82
+ puts `cat #{script} > gnuplot`
83
+ f = File.open(png_file, "rb")
84
+ png = f.read
85
+ f.close
86
+ File.delete png_file
87
+ File.delete script
88
+ png
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,20 @@
1
+
2
+
3
+ module CollectdPlot
4
+ class PlotProperties
5
+ attr_accessor :host # may be a glob
6
+ attr_accessor :metric
7
+ attr_accessor :start
8
+ attr_accessor :finish
9
+ attr_accessor :instance
10
+
11
+ def initialize(params = {})
12
+ self.host = params[:host] or raise ("no host")
13
+ self.metric = params[:metric] or raise ("no metric")
14
+ self.instance = params[:instance]
15
+ self.start = params[:start] || (Time.now.to_i - 86400)
16
+ self.finish = params[:finish] || Time.now.to_i
17
+ self.instance = params[:instance] || "TODO"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,60 @@
1
+ require 'errand'
2
+
3
+ module CollectdPlot
4
+ module RRDRead
5
+ RRDDIR = '/var/lib/collectd/rrd/'
6
+
7
+ def self.list_hosts
8
+ Dir.glob("#{RRDDIR}/*").map { |p| File.basename p }
9
+ end
10
+
11
+ def self.regexp_hosts(glob)
12
+ Dir.glob("#{RRDDIR}/*").each { |d| puts d }
13
+ end
14
+
15
+ def self.list_metrics_for(h)
16
+ Dir.glob("#{RRDDIR}/#{h}/*").map { |m| File.basename m }
17
+ end
18
+
19
+ def self.get_data(props)
20
+ data = {}
21
+ rrd_name = "#{RRDDIR}#{props.host}/load/load.rrd"
22
+ rrd = Errand.new(:filename => rrd_name)
23
+
24
+ puts rrd.fetch(:function => 'AVERAGE', :start => props.start, :finish => props.finish).inspect
25
+ rrd_data = rrd.fetch(:function => 'AVERAGE', :start => props.start, :finish => props.finish)[:data]
26
+ res = {}
27
+ rrd_data.each_pair do |source, metric|
28
+ metric.map! do |datapoint|
29
+ case
30
+ when datapoint && datapoint.nan?
31
+ @tripped = true
32
+ @last_valid
33
+ when @tripped
34
+ @last_valid
35
+ else
36
+ @last_valid = datapoint
37
+ end
38
+ end
39
+ data[props.host] = metric
40
+ end
41
+ data
42
+ end
43
+ =begin
44
+ props.host_a
45
+ props[
46
+ # Last value is always wack. Set to 0, so the timescale isn't off by 1.
47
+ metric[-1] = 0.0
48
+
49
+ res[d[:host]] ||= {}
50
+ res[d[:host]][d[:plugin]] ||= {}
51
+ res[d[:host]][d[:plugin]][d[:instance]] ||= {}
52
+ res[d[:host]][d[:plugin]][d[:instance]][source] ||= {}
53
+ res[d[:host]][d[:plugin]][d[:instance]][source][:start] ||= d[:start].to_i
54
+ res[d[:host]][d[:plugin]][d[:instance]][source][:finish] ||= d[:finish].to_i
55
+ res[d[:host]][d[:plugin]][d[:instance]][source][:data] ||= metric
56
+ end
57
+ res
58
+ =end
59
+ end
60
+ end
@@ -0,0 +1,444 @@
1
+ /* resets */
2
+ body {
3
+ font-size: 62.5%;
4
+ }
5
+
6
+ * {
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ a {
12
+ text-decoration: none;
13
+ }
14
+
15
+ input:focus {
16
+ outline: none;
17
+ }
18
+
19
+ /* styles */
20
+
21
+ a { color: #3465a4; padding: 2px 0px; }
22
+ a:hover { text-decoration: underline; }
23
+ a:visited { color: #75507b; }
24
+ a:hover:visited { text-decoration: underline; }
25
+
26
+ p {
27
+ margin: 0 0 1em;
28
+ }
29
+
30
+ body {
31
+ font-family: Bitstream Vera Serif, Baskerville, Garamond, serif;
32
+ font-size: 1.2em;
33
+ }
34
+
35
+ div#header {
36
+ margin-bottom: 16px;
37
+ border-bottom: 2px solid #C5D6ED;
38
+ background-color: #3465a4;
39
+ background: -moz-linear-gradient(100% 100% 90deg, #244671, #4C94F0);
40
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4C94F0), to(#244671));
41
+ -moz-box-shadow: -7px 0 7px rgba(0,0,0,0.4);
42
+ -webkit-box-shadow: -7px 0 7px rgba(0,0,0,0.4);
43
+ }
44
+
45
+ div#nav {
46
+ color: white;
47
+ font-family: Bitstream Vera Sans, Helvetica Neue, sans-serif;
48
+ text-align: right;
49
+ font-size: 16px;
50
+ }
51
+
52
+ div#nav ul {
53
+ padding: 8px 0px;
54
+ }
55
+
56
+ div#nav ul li {
57
+ display: inline;
58
+ padding: 8px 0px;
59
+ }
60
+
61
+ div#nav ul li a {
62
+ padding: 8px 16px;
63
+ color: white;
64
+ text-shadow: 0 2px 1px rgba(0,0,0,0.5);
65
+ font-weight: bold;
66
+ }
67
+
68
+ div#nav ul li a:hover {
69
+ text-shadow: 0 2px 1px rgba(255,255,255,0.1);
70
+ background: -webkit-gradient(linear, left top, left bottom, from(#529EFF), to(#274C7A));
71
+ background: -moz-linear-gradient(top, #529EFF, #274C7A);
72
+ text-decoration: none;
73
+ }
74
+
75
+ div#nav span.title {
76
+ font-weight: bold;
77
+ }
78
+
79
+
80
+ div#content, div#nav {
81
+ width: 950px;
82
+ margin: auto;
83
+ }
84
+
85
+ div#hosts {
86
+ clear: left;
87
+ }
88
+
89
+ div#profile-meta, div#profile-preview {
90
+ float: left;
91
+ margin-left: 25px;
92
+ width: 450px;
93
+ }
94
+
95
+ div#profile-meta input.text {
96
+ border: 1px solid #bbb;
97
+ font-size: 16px;
98
+ padding: 4px;
99
+ width: 20em;
100
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
101
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
102
+ }
103
+
104
+ div#profile-meta input.create.profile {
105
+ -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
106
+ -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
107
+ -moz-border-radius: 5px;
108
+ -webkit-border-radius: 5px;
109
+ background: #888;
110
+ color: white;
111
+ padding: 5px 10px 6px;
112
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
113
+ border-bottom: 1px solid rgba(0,0,0,0.25);
114
+ position: relative;
115
+ cursor: pointer;
116
+ font-weight: bold;
117
+ background-image: -webkit-gradient(
118
+ linear,
119
+ left bottom,
120
+ left top,
121
+ color-stop(0.1, rgb(136,136,136)),
122
+ color-stop(0.5, rgb(153,153,153))
123
+ );
124
+ background-image: -moz-linear-gradient(
125
+ center bottom,
126
+ rgb(136,136,136) 10%,
127
+ rgb(153,153,153) 50%
128
+ );
129
+ }
130
+
131
+ /*
132
+ * BUILDER
133
+ */
134
+
135
+ div.builder {
136
+ float: left;
137
+ width: 450px;
138
+ margin-left: 25px;
139
+ margin-bottom: 24px;
140
+ }
141
+
142
+ div.builder input.text {
143
+ border: 1px solid #bbb;
144
+ font-size: 16px;
145
+ padding: 4px;
146
+ width: 20em;
147
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
148
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
149
+ }
150
+
151
+ div.builder div.tokenWrapper {
152
+ border: 1px solid #bbb;
153
+ font-size: 16px;
154
+ padding: 4px;
155
+ padding-top: 0;
156
+ width: 350px;
157
+ height: 20px;
158
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
159
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
160
+ }
161
+
162
+ div.builder div.tokenWrapper div.token {
163
+ float: left;
164
+ margin: 2px 4px 2px 0px;
165
+ font-family: Lucida Grande, sans-serif;
166
+ font-size: 16px;
167
+ }
168
+
169
+ div.builder div.tokenWrapper div.token.finalized {
170
+ padding: 0 2px;
171
+ background-color: #D1E5FF;
172
+ color: black;
173
+ border: 1px solid #2F5A92;
174
+ font-size: 14px;
175
+ }
176
+
177
+ div.builder div.tokenWrapper div.token.finalized.selected {
178
+ background-color: #2F5A92;
179
+ color: white;
180
+ }
181
+
182
+ div.builder div.tokenWrapper div.token input.token {
183
+ border: 0;
184
+ font-size: 16px;
185
+ width: 80px;
186
+ }
187
+
188
+ div.builder input.text:focus {
189
+ border: 1px solid #666;
190
+ }
191
+
192
+ div.builder img.icon {
193
+ float: right;
194
+ }
195
+
196
+ div.builder h5 {
197
+ margin-top: 8px;
198
+ margin-left: 8px;
199
+ }
200
+
201
+ div.builder ul.results {
202
+ font-family: Lucida Grande, sans-serif;
203
+ font-size: 16px;
204
+ position: absolute;
205
+ z-index: 10;
206
+ }
207
+
208
+ div.builder ul.results li {
209
+ list-style-type: none;
210
+ padding: 4px 5px;
211
+ border-left: 1px #BBBBBB solid;
212
+ border-right: 1px #BBBBBB solid;
213
+ border-bottom: 1px #BBBBBB solid;
214
+ background-color: white;
215
+ width: 348px;
216
+ }
217
+
218
+ div.builder ul.results li.active {
219
+ background-color: #4C94F0;
220
+ color: white;
221
+ }
222
+
223
+ div.builder ul.results li.all {
224
+ color: gray;
225
+ }
226
+
227
+ div.builder ul.results li.all.active {
228
+ background-color: #A0BD29;
229
+ color: white;
230
+ }
231
+
232
+
233
+
234
+ /*
235
+ * GRAPHS + PROFILE VIEWER
236
+ */
237
+
238
+ div#graphs {
239
+ clear: both;
240
+ padding: 0 2em;
241
+ /* border-top: 1px dashed #babdb6; */
242
+ margin: 16px 0;
243
+ }
244
+
245
+ div.graph {
246
+ margin: 32px 0 48px;
247
+ }
248
+
249
+ h1, h2, h3, h4, h5 {
250
+ font-family: Bitstream Vera Sans, Helvetica Neue, sans-serif;
251
+ }
252
+
253
+ h2 {
254
+ font-weight: bold;
255
+ color: #333;
256
+ border-bottom: 4px solid #888;
257
+ margin-bottom: 12px;
258
+ }
259
+
260
+ h1 {
261
+ font-size: 4em;
262
+ }
263
+
264
+ h1 span.project-name {
265
+ padding: 0 0.1em 0.1em;
266
+ background-color: #3465a4;
267
+ color: white;
268
+ }
269
+
270
+ a#edit {
271
+ float: right;
272
+ display: block;
273
+ }
274
+
275
+ div#chart-builder-slider {
276
+ clear: both;
277
+ overflow-x: hidden;
278
+ overflow-y: hidden;
279
+ }
280
+
281
+ div#profile {
282
+ clear: both;
283
+ }
284
+
285
+ h2#profile_name {
286
+ margin: 36px 0;
287
+ }
288
+
289
+ h4.error {
290
+ margin: 8px 0;
291
+ }
292
+
293
+ div.graph pre {
294
+ line-height: 1.6em;
295
+ font-size: 90%;
296
+ margin-top: -10px;
297
+ }
298
+
299
+ div#bottom_nav {
300
+ margin: 32px 0;
301
+ border-top: 1px dotted #aaa;
302
+ padding-top: 12px;
303
+ font-size: 85%;
304
+ }
305
+
306
+ div#footer {
307
+ clear: both;
308
+ font-size: 0.6em;
309
+ color: gray;
310
+ text-align: center;
311
+ margin-bottom: 2em;
312
+ }
313
+
314
+ div#nothing {
315
+ margin-top: 1em;
316
+ }
317
+
318
+
319
+ div#profiles {
320
+ float: left;
321
+ margin-left: 25px;
322
+ width: 450px;
323
+ }
324
+
325
+ div#profiles div#sort {
326
+ text-align: right;
327
+ font-size: 85%;
328
+ color: #888;
329
+ }
330
+
331
+ div#profiles ul li {
332
+ margin-bottom: 8px;
333
+ padding-left: 24px;
334
+ margin-left: -24px;
335
+ list-style-type: none;
336
+ }
337
+
338
+ div#profiles ul li.active {
339
+ background: url("/images/active.png") no-repeat scroll 10px;
340
+ }
341
+
342
+ div#profiles ul {
343
+ margin-bottom: 16px;
344
+ }
345
+
346
+ div#profiles p.create {
347
+ border-top: 1px dotted #aaa;
348
+ padding-top: 8px;
349
+ margin-top: 24px;
350
+ font-size: 85%;
351
+ }
352
+
353
+ .mask {
354
+ position: absolute;
355
+ opacity: 0.7;
356
+ filter: alpha(opacity=90);
357
+ -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=90);
358
+ z-index: 999;
359
+ background: #000;
360
+ }
361
+
362
+ div#shortcuts {
363
+ font-family: Bitstream Vera Sans, Helvetica Neue, sans-serif;
364
+ z-index: 1000;
365
+ width: 600px;
366
+ position: absolute;
367
+ top: 100px;
368
+ left: 50%;
369
+ margin-left: -300px;
370
+ background-color: white;
371
+ padding: 8px;
372
+ }
373
+
374
+ div#shortcuts table td, div#shortcuts table th {
375
+ padding: 4px 8px;
376
+ }
377
+
378
+ div#shortcuts table th {
379
+ text-align: left;
380
+ }
381
+
382
+
383
+ .button {
384
+ -moz-border-radius: 5px;
385
+ -webkit-border-radius: 5px;
386
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
387
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
388
+ background-color: #637020;
389
+ background-repeat: repeat-x;
390
+ background: -moz-linear-gradient(100% 100% 90deg, #244671, #4C94F0);
391
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4C94F0), to(#244671));
392
+ border: medium none;
393
+ color: white;
394
+ cursor: pointer;
395
+ font-family: Lucida Grande,sans-serif;
396
+ font-weight: bold;
397
+ padding: 4px;
398
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
399
+ }
400
+
401
+ .button:hover, .button:focus {
402
+ text-shadow: 0 2px 1px rgba(255,255,255,0.1);
403
+ background: -webkit-gradient(linear, left top, left bottom, from(#529EFF), to(#274C7A));
404
+ background: -moz-linear-gradient(top, #529EFF, #274C7A);
405
+ outline: none;
406
+ }
407
+
408
+ input#show {
409
+ float: right;
410
+ font-size: 80%;
411
+ padding: 4px 8px;
412
+ font-family: 'Bitstream Vera Sans', 'Helvetica Neue', sans-serif;
413
+ margin-bottom: 16px;
414
+ margin-left: 16px;
415
+ }
416
+
417
+ input#save {
418
+ float: right;
419
+ font-size: 80%;
420
+ padding: 4px 8px;
421
+ font-family: 'Bitstream Vera Sans', 'Helvetica Neue', sans-serif;
422
+ margin-bottom: 16px;
423
+ margin-left: 16px;
424
+ }
425
+
426
+ button::-moz-focus-inner,
427
+ input[type="reset"]::-moz-focus-inner,
428
+ input[type="button"]::-moz-focus-inner,
429
+ input[type="submit"]::-moz-focus-inner,
430
+ input[type="file"] > input[type="button"]::-moz-focus-inner {
431
+ border: none;
432
+ }
433
+
434
+ input#profile_name {
435
+ border: 1px solid #bbb;
436
+ font-size: 16px;
437
+ padding: 4px;
438
+ padding-top: 0;
439
+ width: 200px;
440
+ height: 20px;
441
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
442
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
443
+ float: right;
444
+ }
@@ -0,0 +1,7 @@
1
+
2
+ %table
3
+ %tbody
4
+ - @metrics.each do |m|
5
+ %tr
6
+ %td
7
+ %a{:href => link_to("/hosts/#{@host}/metric/#{m}")}= m
@@ -0,0 +1,7 @@
1
+
2
+ %table
3
+ %tbody
4
+ - @hosts.each do |h|
5
+ %tr
6
+ %td
7
+ %a{:href => link_to("/hosts/#{h}")}= h
@@ -0,0 +1,27 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= "Collectd-Plot"
5
+ %link{:rel => "icon", :type => "image/gif", :href => "/favicon.gif"}
6
+ %link{:rel => 'stylesheet', :href => '/stylesheets/screen.css', :type => 'text/css'}
7
+
8
+ %body
9
+ %div#wrapper
10
+ %div#header
11
+ %div#nav
12
+ %ul
13
+ %li
14
+ %a{:href => link_to("/profiles")} profiles
15
+ %li
16
+ %a{:href => link_to("/builder")} builder
17
+
18
+ %div#content
19
+ = yield
20
+
21
+ %div#footer
22
+ Collectd-Plot
23
+ |
24
+ %a{:href => link_to("/profiles")} Profiles
25
+ |
26
+ %a{:href => link_to("/builder")} Builder
27
+
metadata ADDED
@@ -0,0 +1,239 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: collectd-plot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ prerelease: false
10
+ platform: ruby
11
+ authors:
12
+ - Tim Miller
13
+ autorequire: !!null
14
+ bindir: bin
15
+ cert_chain: []
16
+ date: 2012-04-08 00:00:00.000000000 +00:00
17
+ default_executable: !!null
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: haml
21
+ requirement: &14890980 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - =
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.4
27
+ segments:
28
+ - 3
29
+ - 1
30
+ - 4
31
+ type: :runtime
32
+ prerelease: false
33
+ version_requirements: *14890980
34
+ - !ruby/object:Gem::Dependency
35
+ name: tilt
36
+ requirement: &14890100 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - =
40
+ - !ruby/object:Gem::Version
41
+ version: 1.3.3
42
+ segments:
43
+ - 1
44
+ - 3
45
+ - 3
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *14890100
49
+ - !ruby/object:Gem::Dependency
50
+ name: sinatra
51
+ requirement: &14889180 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - =
55
+ - !ruby/object:Gem::Version
56
+ version: 1.3.2
57
+ segments:
58
+ - 1
59
+ - 3
60
+ - 2
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: *14889180
64
+ - !ruby/object:Gem::Dependency
65
+ name: errand
66
+ requirement: &14836780 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - =
70
+ - !ruby/object:Gem::Version
71
+ version: 0.7.3
72
+ segments:
73
+ - 0
74
+ - 7
75
+ - 3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: *14836780
79
+ - !ruby/object:Gem::Dependency
80
+ name: librrd
81
+ requirement: &14835820 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - =
85
+ - !ruby/object:Gem::Version
86
+ version: 1.0.2
87
+ segments:
88
+ - 1
89
+ - 0
90
+ - 2
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: *14835820
94
+ - !ruby/object:Gem::Dependency
95
+ name: gnuplot
96
+ requirement: &14834820 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - =
100
+ - !ruby/object:Gem::Version
101
+ version: 2.4.1
102
+ segments:
103
+ - 2
104
+ - 4
105
+ - 1
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: *14834820
109
+ - !ruby/object:Gem::Dependency
110
+ name: shotgun
111
+ requirement: &14833760 !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ segments:
118
+ - 0
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: *14833760
122
+ - !ruby/object:Gem::Dependency
123
+ name: rack-test
124
+ requirement: &14832840 !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ segments:
131
+ - 0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *14832840
135
+ - !ruby/object:Gem::Dependency
136
+ name: rspec
137
+ requirement: &14831980 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ segments:
144
+ - 0
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: *14831980
148
+ - !ruby/object:Gem::Dependency
149
+ name: cucumber
150
+ requirement: &14831220 !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ segments:
157
+ - 0
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: *14831220
161
+ - !ruby/object:Gem::Dependency
162
+ name: webrat
163
+ requirement: &14830200 !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ segments:
170
+ - 0
171
+ type: :development
172
+ prerelease: false
173
+ version_requirements: *14830200
174
+ - !ruby/object:Gem::Dependency
175
+ name: colorize
176
+ requirement: &14829420 !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ segments:
183
+ - 0
184
+ type: :development
185
+ prerelease: false
186
+ version_requirements: *14829420
187
+ description: Plot collectd data using gnuplot, with useful features such as host globbing.
188
+ email:
189
+ - ''
190
+ executables: []
191
+ extensions: []
192
+ extra_rdoc_files: []
193
+ files:
194
+ - Gemfile
195
+ - Gemfile.lock
196
+ - README.md
197
+ - collectd-plot.gemspec
198
+ - lib/collectd-plot.rb
199
+ - lib/collectd-plot/plot.rb
200
+ - lib/collectd-plot/plot_properties.rb
201
+ - lib/collectd-plot/rrd_read.rb
202
+ - lib/public/stylesheets/screen.css
203
+ - lib/views/host.haml
204
+ - lib/views/index.haml
205
+ - lib/views/layout.haml
206
+ has_rdoc: true
207
+ homepage: https://github.com/echohead/collectd-plot
208
+ licenses: []
209
+ post_install_message: !!null
210
+ rdoc_options: []
211
+ require_paths:
212
+ - lib
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ none: false
215
+ requirements:
216
+ - - ! '>='
217
+ - !ruby/object:Gem::Version
218
+ version: 1.9.1
219
+ segments:
220
+ - 1
221
+ - 9
222
+ - 1
223
+ required_rubygems_version: !ruby/object:Gem::Requirement
224
+ none: false
225
+ requirements:
226
+ - - ! '>='
227
+ - !ruby/object:Gem::Version
228
+ version: 1.3.7
229
+ segments:
230
+ - 1
231
+ - 3
232
+ - 7
233
+ requirements: []
234
+ rubyforge_project: !!null
235
+ rubygems_version: 1.3.7
236
+ signing_key: !!null
237
+ specification_version: 3
238
+ summary: A web interface for Collectd
239
+ test_files: []