visage-app 0.1.8 → 0.2.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.
@@ -8,7 +8,7 @@ body {
8
8
  padding: 0;
9
9
  }
10
10
 
11
- a {
11
+ a {
12
12
  text-decoration: none;
13
13
  }
14
14
 
@@ -24,33 +24,168 @@ p {
24
24
  margin: 0 0 1em;
25
25
  }
26
26
 
27
- li {
28
- margin: 0.55em 0 0.55em 1em;
29
- list-style-type: none;
30
- }
31
-
32
27
  body {
33
28
  font-family: Bitstream Vera Serif, Baskerville, Garamond, serif;
34
29
  font-size: 1.2em;
35
30
  }
36
31
 
37
32
  div#header {
33
+ height: 40px;
34
+ background-color: #3465a4;
35
+ margin-bottom: 16px;
36
+ border-bottom: 6px solid #c5d6ed;
37
+ }
38
+
39
+ div#nav {
40
+ padding-top: 10px;
41
+ color: white;
42
+ font-family: sans-serif;
43
+ text-align: right;
44
+ font-size: 16px;
45
+ }
46
+
47
+ div#nav a {
48
+ margin-top: 8px;
49
+ margin-left: 12px;
50
+ color: white;
51
+ font-weight: bold;
52
+ }
53
+
54
+ div#nav a:hover {
55
+ text-shadow: 0 1px 6px rgba(115,157,211,0.9);
56
+ background-color: #3465a4;
57
+ }
58
+
59
+ div#content, div#nav {
60
+ width: 950px;
61
+ margin: auto;
62
+ }
63
+
64
+ div#hosts {
65
+ clear: left;
66
+ }
67
+
68
+ div#profile-meta, div#profile-preview {
38
69
  float: left;
70
+ margin-left: 25px;
71
+ width: 450px;
72
+ }
73
+
74
+ div#profile-meta input.text {
75
+ border: 1px solid #bbb;
76
+ font-size: 16px;
77
+ padding: 4px;
39
78
  width: 20em;
79
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
80
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
40
81
  }
41
82
 
42
- div.nav {
83
+ div#profile-meta input.create.profile {
84
+ -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
85
+ -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
86
+ -moz-border-radius: 5px;
87
+ -webkit-border-radius: 5px;
88
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
89
+ background: #888;
90
+ color: white;
91
+ padding: 5px 10px 6px;
92
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
93
+ border-bottom: 1px solid rgba(0,0,0,0.25);
94
+ position: relative;
95
+ cursor: pointer;
96
+ font-weight: bold;
97
+ background-image: -webkit-gradient(
98
+ linear,
99
+ left bottom,
100
+ left top,
101
+ color-stop(0.1, rgb(136,136,136)),
102
+ color-stop(0.5, rgb(153,153,153))
103
+ );
104
+ background-image: -moz-linear-gradient(
105
+ center bottom,
106
+ rgb(136,136,136) 10%,
107
+ rgb(153,153,153) 50%
108
+ );
109
+ }
110
+
111
+ p.error {
112
+ color: red;
113
+ font-size: 80%;
114
+ }
115
+
116
+ div.builder {
43
117
  float: left;
44
- margin: 1em;
45
- margin-right: 2em;
118
+ margin-left: 25px;
119
+ width: 450px;
120
+ margin-bottom: 24px;
46
121
  }
47
122
 
48
- div.nav li {
49
- margin-left: 2px;
123
+ div.builder input.text {
124
+ border: 1px solid #bbb;
125
+ font-size: 16px;
126
+ padding: 4px;
127
+ width: 20em;
128
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
129
+ -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
50
130
  }
51
131
 
52
- div#header {
53
- margin: 1em 0.5em;
132
+ div.builder input.text:focus {
133
+ border: 1px solid #666;
134
+ }
135
+
136
+ div.builder input.submit {
137
+ opacity: 0;
138
+ }
139
+
140
+ div.builder ul {
141
+ margin-top: 16px;
142
+ }
143
+
144
+ div.builder img.icon {
145
+ float: right;
146
+ }
147
+
148
+ div.builder li {
149
+ list-style-type: none;
150
+ padding: 4px 8px;
151
+ }
152
+
153
+ div.builder h5 {
154
+ margin-top: 8px;
155
+ margin-left: 8px;
156
+ }
157
+
158
+ div.builder ul.available {
159
+ margin-top: 4px;
160
+ }
161
+
162
+ div.builder ul.selected {
163
+ background-color: #fffaba;
164
+ }
165
+
166
+ div.builder li:hover {
167
+ /*background-color: #fffaba;*/
168
+ }
169
+
170
+ div.builder li td {
171
+ padding: 4px;
172
+ }
173
+
174
+ div.builder li td.name {
175
+ width: 350px;
176
+ }
177
+
178
+ div.builder li td.meta {
179
+ width: 80px;
180
+ text-align: right;
181
+ padding-right: 8px;
182
+ }
183
+
184
+ span.glob.example {
185
+ display: block;
186
+ font-size: 80%;
187
+ font-style: italic;
188
+ margin-top: 8px;
54
189
  }
55
190
 
56
191
  div#graphs {
@@ -69,8 +204,11 @@ h1, h2, h3, h4, h5 {
69
204
  font-family: Bitstream Vera Sans, Helvetica Neue, sans-serif;
70
205
  }
71
206
 
72
- h2, h3, h4, h5 {
73
- /*text-transform: uppercase;*/
207
+ h2 {
208
+ font-weight: bold;
209
+ color: #666;
210
+ border-bottom: 4px solid #888;
211
+ margin-bottom: 12px;
74
212
  }
75
213
 
76
214
  h1 {
@@ -94,3 +232,22 @@ div#nothing {
94
232
  margin-top: 1em;
95
233
  }
96
234
 
235
+
236
+ div#profiles {
237
+ float: left;
238
+ margin-left: 25px;
239
+ width: 450px;
240
+ }
241
+
242
+ div#profiles ul li {
243
+ margin-bottom: 8px;
244
+ list-style-type: none;
245
+ }
246
+
247
+ div#profiles ul {
248
+ margin-bottom: 16px;
249
+ }
250
+
251
+ div#profiles p.create {
252
+ font-size: 85%;
253
+ }
@@ -0,0 +1,52 @@
1
+ - page_title "Profile builder"
2
+
3
+ %div#builder
4
+ %form{:action => "/builder", :method => :get}
5
+
6
+ - if @profile.selected_hosts.size > 0 && @profile.selected_metrics.size > 0
7
+ %div#profile-preview
8
+ %h2 Preview
9
+ %div#graph
10
+ %p Coming soon!
11
+ %div#profile-meta
12
+ %h2 Profile name
13
+ %p
14
+ %input{:name => "profile_name", :value => params[:profile_name], :type => "text", :class => "text"}
15
+ %p.error
16
+ = @profile.errors[:profile_name]
17
+ %p
18
+ %input{:type => "submit", :value => "create", :class => "create", :name => "submit"}
19
+
20
+ %div#hosts.builder
21
+ %h2 Hosts
22
+ %input{:name => "hosts", :type => "text", :class => "text", :value => params[:hosts]}
23
+ %input{:name => "submit", :type => "submit", :class => "submit", :value => "hosts"}
24
+ %img{:src => link_to("/images/hosts.png"), :class => "icon hosts"}
25
+ %span{:class => "glob example"} e.g. “charlie”, “*.bravo*”, “echo, foxtrot*”
26
+
27
+ %ul.selected
28
+ - @profile.selected_hosts.each do |name|
29
+ %li= name
30
+
31
+ %h5 Available
32
+ %ul.available
33
+ - @profile.hosts.each do |name|
34
+ %li= name
35
+
36
+ %div#metrics.builder
37
+ %h2 Metrics
38
+ %input{:name => "metrics", :type => "text", :class => "text", :value => params[:metrics]}
39
+ %input{:name => "submit", :type => "submit", :class => "submit", :value => "metrics"}
40
+ %img{:src => link_to("/images/metrics.png"), :class => "icon metrics"}
41
+ %span{:class => "glob example"} e.g. “cpu*/*”, “disk*/*ops, disk*/*time”
42
+
43
+ %ul.selected
44
+ - @profile.selected_metrics.each do |name|
45
+ %li= name
46
+
47
+ %h5 Available
48
+ %ul.available
49
+ - @profile.metrics.each do |name|
50
+ %li= name
51
+
52
+
@@ -1,22 +1,24 @@
1
- !!!
1
+ !!!
2
2
  %html
3
3
  %head
4
- %title Visage
4
+ %title= include_page_title
5
5
  %link{:rel => "icon", :type => "image/gif", :href => "/favicon.gif"}
6
6
  %link{:rel => 'stylesheet', :href => '/stylesheets/screen.css', :type => 'text/css'}
7
- %script{:type => "text/javascript", :src => "/javascripts/raphael-min.js"}
8
- %script{:type => "text/javascript", :src => "/javascripts/g.raphael.js"}
9
- %script{:type => "text/javascript", :src => "/javascripts/g.line.js"}
10
- %script{:type => "text/javascript", :src => "/javascripts/mootools-1.2.3-core.js"}
11
- %script{:type => "text/javascript", :src => "/javascripts/mootools-1.2.3.1-more.js"}
12
- %script{:type => "text/javascript", :src => "/javascripts/graph.js"}
13
- %script{:type => "text/javascript", :src => "/javascripts/application.js"}
7
+ %script{:type => "text/javascript", :src => link_to("/javascripts/raphael.js")}
8
+ %script{:type => "text/javascript", :src => link_to("/javascripts/g.raphael.js")}
9
+ %script{:type => "text/javascript", :src => link_to("/javascripts/g.line.js")}
10
+ %script{:type => "text/javascript", :src => link_to("/javascripts/mootools-1.2.3-core.js")}
11
+ %script{:type => "text/javascript", :src => link_to("/javascripts/mootools-1.2.3.1-more.js")}
12
+ %script{:type => "text/javascript", :src => link_to("/javascripts/graph.js")}
13
+ %script{:type => "text/javascript", :src => link_to("/javascripts/application.js")}
14
14
 
15
15
  %body
16
16
  %div#wrapper
17
17
  %div#header
18
- %h1.project
19
- %span.project-name Visage
18
+ %div#nav
19
+ %a{:href => link_to("/profiles")} profiles
20
+ %a{:href => link_to("/builder")} builder
21
+
20
22
  %div#content
21
23
  = yield
22
24
 
@@ -0,0 +1,18 @@
1
+ - page_title @profile.options[:profile_name]
2
+
3
+ %div#profile
4
+ - @profile.graphs.each do |graph|
5
+ %div{:id => graph.id, :class => 'graph'}
6
+ :javascript
7
+ window.addEvent('domready', function() {
8
+ var graph = new visageGraph('#{graph.id}', '#{graph.host}', '#{graph.plugin}', {
9
+ width: 900,
10
+ height: 220,
11
+ gridWidth: 800,
12
+ gridHeight: 200,
13
+ shade: false,
14
+ pluginInstance: '#{graph.instances.join(',')}',
15
+ name: '#{graph.plugin} on #{graph.host}'
16
+ });
17
+ });
18
+
@@ -0,0 +1,13 @@
1
+ - page_title 'Profiles'
2
+
3
+ %div#profiles
4
+ %h2 Profiles
5
+
6
+ %ul
7
+ - @profiles.each do |prof|
8
+ %li
9
+ %a{:href => link_to("/profiles/#{prof.url}")}= prof.profile_name
10
+
11
+ %p.create
12
+ %a{:href => link_to("/builder")} Create a new profile.
13
+
data/lib/visage-app.rb CHANGED
@@ -4,78 +4,113 @@ require 'pathname'
4
4
  @root = Pathname.new(File.dirname(__FILE__)).parent.expand_path
5
5
  $: << @root.to_s
6
6
 
7
- require 'sinatra'
8
- require 'errand'
9
- require 'yajl'
7
+ require 'sinatra/base'
10
8
  require 'haml'
9
+ require 'lib/visage/profile'
11
10
  require 'lib/visage/config'
12
11
  require 'lib/visage/helpers'
13
12
  require 'lib/visage/config/init'
13
+ require 'lib/visage/collectd/rrds'
14
14
  require 'lib/visage/collectd/json'
15
+ require 'yajl/json_gem'
15
16
 
16
- set :public, @root.join('lib/visage/public')
17
- set :views, @root.join('lib/visage/views')
17
+ module Visage
18
+ class Application < Sinatra::Base
19
+ @root = Pathname.new(File.dirname(__FILE__)).parent.expand_path
20
+ set :public, @root.join('lib/visage/public')
21
+ set :views, @root.join('lib/visage/views')
18
22
 
19
- configure do
20
- CollectdJSON.rrddir = Visage::Config.rrddir
21
- Visage::Config::Profiles.profiles = Visage::Config.profiles
22
- end
23
+ helpers Sinatra::LinkToHelper
24
+ helpers Sinatra::PageTitleHelper
25
+ end
26
+
27
+ class Profiles < Application
28
+ get '/' do
29
+ redirect '/profiles'
30
+ end
23
31
 
24
- # infrastructure for embedding
25
- get '/javascripts/visage.js' do
26
- javascript = ""
27
- %w{raphael-min g.raphael g.line mootools-1.2.3-core mootools-1.2.3.1-more graph}.each do |js|
28
- javascript += File.read(File.join(__DIR__, 'public', 'javascripts', "#{js}.js"))
32
+ get '/profiles/:url' do
33
+ @profile = Visage::Profile.get(params[:url])
34
+ raise Sinatra::NotFound unless @profile
35
+ haml :profile
36
+ end
37
+
38
+ get '/profiles' do
39
+ @profiles = Visage::Profile.all
40
+ haml :profiles
41
+ end
29
42
  end
30
- javascript
31
- end
32
43
 
33
- # user facing
34
- get '/' do
35
- @hosts = CollectdJSON.hosts
36
- haml :index
37
- end
38
44
 
39
- get '/:host' do
40
- @hosts = CollectdJSON.hosts
41
- @profiles = Visage::Config::Profiles.all
45
+ class Builder < Application
42
46
 
43
- haml :index
44
- end
47
+ get "/builder" do
48
+ if params[:submit] == "create"
49
+ @profile = Visage::Profile.new(params)
45
50
 
46
- get '/:host/:profile' do
47
- @hosts = CollectdJSON.hosts
48
- @profiles = Visage::Config::Profiles.all
49
- @profile = Visage::Config::Profiles.get(params[:profile])
51
+ if @profile.save
52
+ redirect "/profiles/#{@profile.url}"
53
+ else
54
+ haml :builder
55
+ end
56
+ else
57
+ @profile = Visage::Profile.new(params)
50
58
 
51
- haml :index
52
- end
59
+ haml :builder
60
+ end
61
+ end
53
62
 
54
- # JSON data backend
55
-
56
- # /data/:host/:plugin/:optional_plugin_instance
57
- get %r{/data/([^/]+)/([^/]+)((/[^/]+)*)} do
58
- host = params[:captures][0]
59
- plugin = params[:captures][1]
60
- plugin_instances = params[:captures][2]
61
-
62
- collectd = CollectdJSON.new(:rrddir => Visage::Config.rrddir,
63
- :fallback_colors => Visage::Config.fallback_colors)
64
- json = collectd.json(:host => host,
65
- :plugin => plugin,
66
- :plugin_instances => plugin_instances,
67
- :start => params[:start],
68
- :finish => params[:finish],
69
- :plugin_colors => Visage::Config.plugin_colors)
70
- # if the request is cross-domain, we need to serve JSONP
71
- maybe_wrap_with_callback(json)
72
- end
63
+ # infrastructure for embedding
64
+ get '/javascripts/visage.js' do
65
+ javascript = ""
66
+ %w{raphael-min g.raphael g.line mootools-1.2.3-core mootools-1.2.3.1-more graph}.each do |js|
67
+ javascript += File.read(@root.join('lib/visage/public/javascripts', "#{js}.js"))
68
+ end
69
+ javascript
70
+ end
71
+
72
+ end
73
+
74
+ class JSON < Application
75
+
76
+ # JSON data backend
77
+
78
+ # /data/:host/:plugin/:optional_plugin_instance
79
+ get %r{/data/([^/]+)/([^/]+)((/[^/]+)*)} do
80
+ host = params[:captures][0]
81
+ plugin = params[:captures][1]
82
+ plugin_instances = params[:captures][2]
83
+
84
+ collectd = CollectdJSON.new(:rrddir => Visage::Config.rrddir,
85
+ :fallback_colors => Visage::Config.fallback_colors)
86
+ json = collectd.json(:host => host,
87
+ :plugin => plugin,
88
+ :plugin_instances => plugin_instances,
89
+ :start => params[:start],
90
+ :finish => params[:finish],
91
+ :plugin_colors => Visage::Config.plugin_colors)
92
+ # if the request is cross-domain, we need to serve JSONP
93
+ maybe_wrap_with_callback(json)
94
+ end
95
+
96
+ get %r{/data/([^/]+)} do
97
+ host = params[:captures][0]
98
+ metrics = Visage::Collectd::RRDs.metrics(:host => host)
99
+
100
+ json = { host => metrics }.to_json
101
+ maybe_wrap_with_callback(json)
102
+ end
103
+
104
+ get %r{/data(/)*} do
105
+ hosts = Visage::Collectd::RRDs.hosts
106
+ json = { :hosts => hosts }.to_json
107
+ maybe_wrap_with_callback(json)
108
+ end
109
+
110
+ # wraps json with a callback method that JSONP clients can call
111
+ def maybe_wrap_with_callback(json)
112
+ params[:callback] ? params[:callback] + '(' + json + ')' : json
113
+ end
73
114
 
74
- # wraps json with a callback method that JSONP clients can call
75
- def maybe_wrap_with_callback(json)
76
- if params[:callback]
77
- params[:callback] + '(' + json + ')'
78
- else
79
- json
80
115
  end
81
116
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 8
9
- version: 0.1.8
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lindsay Holmwood
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-25 00:00:00 -07:00
17
+ date: 2010-06-27 00:00:00 +10:00
18
18
  default_executable: visage
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -113,18 +113,26 @@ files:
113
113
  - lib/visage-app.rb
114
114
  - lib/visage/collectd/json.rb
115
115
  - lib/visage/collectd/profile.rb
116
+ - lib/visage/collectd/rrds.rb
116
117
  - lib/visage/config.rb
117
118
  - lib/visage/config.ru
118
119
  - lib/visage/config/fallback-colors.yaml
119
120
  - lib/visage/config/init.rb
120
121
  - lib/visage/config/plugin-colors.yaml
121
- - lib/visage/config/profiles.yaml
122
122
  - lib/visage/config/profiles.yaml.sample
123
+ - lib/visage/graph.rb
123
124
  - lib/visage/helpers.rb
124
125
  - lib/visage/patches.rb
126
+ - lib/visage/profile.rb
125
127
  - lib/visage/public/favicon.gif
128
+ - lib/visage/public/images/add.png
129
+ - lib/visage/public/images/hosts.png
130
+ - lib/visage/public/images/metrics.png
131
+ - lib/visage/public/images/search.png
126
132
  - lib/visage/public/javascripts/application.js
133
+ - lib/visage/public/javascripts/g.line-min.js
127
134
  - lib/visage/public/javascripts/g.line.js
135
+ - lib/visage/public/javascripts/g.raphael-min.js
128
136
  - lib/visage/public/javascripts/g.raphael.js
129
137
  - lib/visage/public/javascripts/graph.js
130
138
  - lib/visage/public/javascripts/mootools-1.2.3-core.js
@@ -132,8 +140,10 @@ files:
132
140
  - lib/visage/public/javascripts/raphael-min.js
133
141
  - lib/visage/public/javascripts/raphael.js
134
142
  - lib/visage/public/stylesheets/screen.css
135
- - lib/visage/views/index.haml
143
+ - lib/visage/views/builder.haml
136
144
  - lib/visage/views/layout.haml
145
+ - lib/visage/views/profile.haml
146
+ - lib/visage/views/profiles.haml
137
147
  has_rdoc: true
138
148
  homepage: http://auxesis.github.com/visage
139
149
  licenses: []
@@ -1,35 +0,0 @@
1
- ---
2
- profiles:
3
- CPU + Load:
4
- plugins:
5
- - cpu-0/cpu-user/cpu-system/cpu-idle/cpu-wait/cpu-interrupt
6
- - cpu-1
7
- - load/load
8
- - battery-0
9
- splat: cpu+load
10
- order: 1
11
- Memory:
12
- plugins:
13
- - memory
14
- - swap
15
- splat: memory
16
- order: 2
17
- Disk Usage:
18
- plugins:
19
- - df/df-root
20
- - disk-sda
21
- splat: disk+usage
22
- order: 3
23
- Networking:
24
- plugins:
25
- - tcpconns-9393-local
26
- - tcpconns-80-local
27
- - tcpconns-22-local
28
- splat: network
29
- order: 4
30
- Processes:
31
- plugins:
32
- - processes
33
- - processes-collectd
34
- splat: processes
35
- order: 5
@@ -1,48 +0,0 @@
1
- %div#nav
2
- %div#hosts.nav
3
- %h2 Hosts
4
- %ul
5
- - if !Visage::Config.rrddir
6
- %li
7
- You need to specify <strong>rrddir</strong> in config/init.rb!
8
- - elsif @hosts.empty?
9
- %li
10
- No hosts found. Please check <strong>rrddir</strong> in config/init.rb!
11
- - else
12
- - @hosts.each do |host|
13
- %li
14
- %a{:href => link_to("/#{host}")}= host
15
-
16
- - if host = params[:host]
17
- %div#profiles.nav
18
- %h2 Profiles
19
-
20
- %ul
21
- - @profiles.each do |profile|
22
- %li
23
- %a{:href => link_to("/#{host}/#{profile.splat}")}= profile.name
24
-
25
- %div#graphs
26
- - if @profile && @profile.plugins
27
- - @profile.plugins.each do |graph|
28
- - plugin, plugin_instances = graph.split('/', 2)
29
- - graph_id = "graph#{graph.gsub(/[^\w+]/, '_')}"
30
- %div.graph
31
- %div{:id => graph_id}
32
- :javascript
33
- window.addEvent('domready', function() {
34
- var graph = new visageGraph('#{graph_id}', '#{params[:host]}', '#{plugin}', {
35
- width: 900,
36
- height: 220,
37
- gridWidth: 800,
38
- gridHeight: 200,
39
- shade: #{Visage::Config.shade || false},
40
- pluginInstance: '#{plugin_instances || ''}',
41
- name: '#{plugin} on #{host}'
42
- });
43
- });
44
-
45
- - else
46
- %div#nothing
47
- Sorry, nothing to display!
48
-