riemann-dash 0.1.1 → 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.
data/lib/riemann/dash.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'rubygems'
2
- require 'riemann/client'
3
2
  require 'sinatra/base'
4
3
 
5
4
  module Riemann
@@ -13,24 +12,11 @@ module Riemann
13
12
 
14
13
  def self.config
15
14
  @config ||= {
16
- :client => {},
17
- :age_scale => 60 * 30,
18
- :state_order => {
19
- 'critical' => 3,
20
- 'warning' => 2,
21
- 'ok' => 1
22
- },
23
- :strftime => '%H:%M:%S',
24
15
  :controllers => [File.join(File.dirname(__FILE__), 'dash', 'controller')],
25
- :helpers => [File.join(File.dirname(__FILE__), 'dash', 'helper')],
26
16
  :views => File.join(File.dirname(__FILE__), 'dash', 'views')
27
17
  }
28
18
  end
29
19
 
30
- def self.client
31
- @client ||= Riemann::Client.new(config[:client])
32
- end
33
-
34
20
  def self.load(filename)
35
21
  unless load_config(filename || 'config.rb')
36
22
  # Configuration failed; load a default view.
@@ -38,7 +24,6 @@ module Riemann
38
24
  end
39
25
 
40
26
  config[:controllers].each { |d| load_controllers d }
41
- config[:helpers].each { |d| load_helpers d }
42
27
  set :views, File.expand_path(config[:views])
43
28
 
44
29
  # Fallback pub dir
@@ -55,12 +40,13 @@ module Riemann
55
40
  end
56
41
  end
57
42
 
58
- # Load controllers.
59
- # Controllers can be regular old one-file-per-class, but if you prefer a little
60
- # more modularity, this method will allow you to define all controller methods
61
- # in their own files. For example, get "/posts/*/edit" can live in
62
- # controller/posts/_/edit.rb. The sorting system provided here requires
63
- # files in the correct order to handle wildcards appropriately.
43
+ # Load controllers.
44
+ # Controllers can be regular old one-file-per-class, but
45
+ # if you prefer a little more modularity, this method will allow you to
46
+ # define all controller methods in their own files. For example, get
47
+ # "/posts/*/edit" can live in controller/posts/_/edit.rb. The sorting
48
+ # system provided here requires files in the correct order to handle
49
+ # wildcards appropriately.
64
50
  def self.load_controllers(dir)
65
51
  rbs = []
66
52
  Find.find(
@@ -104,27 +90,10 @@ module Riemann
104
90
  end
105
91
  end
106
92
 
107
- # Load helpers
108
- def self.load_helpers(dir)
109
- Find.find(
110
- File.expand_path(dir)
111
- ) do |path|
112
- require path if path =~ /\.rb$/
113
- end
114
- end
115
-
116
93
  # Add an additional public directory.
117
94
  def self.public_dir(dir)
118
95
  require 'riemann/dash/rack/static'
119
96
  use Riemann::Dash::Static, :root => dir
120
97
  end
121
-
122
- def client
123
- self.class.client
124
- end
125
-
126
- def query(*a)
127
- self.class.client.query(*a).events || []
128
- end
129
98
  end
130
99
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riemann-dash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-18 00:00:00.000000000 Z
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: riemann-client
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &11919920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: 0.0.7
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: 0.0.7
24
+ version_requirements: *11919920
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: erubis
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &11918520 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: 2.7.0
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: 2.7.0
35
+ version_requirements: *11918520
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: sinatra
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &11917660 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ! '>='
@@ -53,15 +43,10 @@ dependencies:
53
43
  version: 1.3.2
54
44
  type: :runtime
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: 1.3.2
46
+ version_requirements: *11917660
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: sass
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &11916360 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
52
  - - ! '>='
@@ -69,15 +54,10 @@ dependencies:
69
54
  version: 3.1.14
70
55
  type: :runtime
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: 3.1.14
57
+ version_requirements: *11916360
78
58
  - !ruby/object:Gem::Dependency
79
59
  name: thin
80
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &11914740 !ruby/object:Gem::Requirement
81
61
  none: false
82
62
  requirements:
83
63
  - - ! '>='
@@ -85,28 +65,18 @@ dependencies:
85
65
  version: 1.3.1
86
66
  type: :runtime
87
67
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: 1.3.1
68
+ version_requirements: *11914740
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: multi_json
96
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &11540560 !ruby/object:Gem::Requirement
97
72
  none: false
98
73
  requirements:
99
- - - '='
74
+ - - =
100
75
  - !ruby/object:Gem::Version
101
76
  version: 1.3.6
102
77
  type: :runtime
103
78
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - '='
108
- - !ruby/object:Gem::Version
109
- version: 1.3.6
79
+ version_requirements: *11540560
110
80
  description:
111
81
  email: aphyr@aphyr.com
112
82
  executables:
@@ -115,38 +85,37 @@ extensions: []
115
85
  extra_rdoc_files: []
116
86
  files:
117
87
  - lib/riemann/dash.rb
118
- - lib/riemann/dash/version.rb
119
- - lib/riemann/dash/public/keys.js
120
- - lib/riemann/dash/public/jquery-ui-1.9.0.custom.min.js
121
- - lib/riemann/dash/public/toolbar.js
122
- - lib/riemann/dash/public/subs.js
123
- - lib/riemann/dash/public/underscore-min.js
88
+ - lib/riemann/dash/rack/static.rb
89
+ - lib/riemann/dash/public/format.js
90
+ - lib/riemann/dash/public/view.js
124
91
  - lib/riemann/dash/public/jquery-1.7.2.min.js
92
+ - lib/riemann/dash/public/mustache.js
125
93
  - lib/riemann/dash/public/x.png
126
- - lib/riemann/dash/public/jquery.quickfit.js
127
- - lib/riemann/dash/public/view.js
94
+ - lib/riemann/dash/public/util.js
95
+ - lib/riemann/dash/public/jquery-ui-1.9.0.custom.min.js
96
+ - lib/riemann/dash/public/underscore-min.js
97
+ - lib/riemann/dash/public/persistence.js
98
+ - lib/riemann/dash/public/subs.js
99
+ - lib/riemann/dash/public/jquery.simplemodal.1.4.3.min.js
128
100
  - lib/riemann/dash/public/views/help.js
129
- - lib/riemann/dash/public/views/title.js
130
101
  - lib/riemann/dash/public/views/grid.js
102
+ - lib/riemann/dash/public/views/title.js
131
103
  - lib/riemann/dash/public/views/gauge.js
132
- - lib/riemann/dash/public/jquery.simplemodal.1.4.3.min.js
104
+ - lib/riemann/dash/public/jquery.quickfit.js
105
+ - lib/riemann/dash/public/toastr.js
106
+ - lib/riemann/dash/public/toolbar.js
107
+ - lib/riemann/dash/public/toastr.css
133
108
  - lib/riemann/dash/public/dash.js
134
- - lib/riemann/dash/public/format.js
135
109
  - lib/riemann/dash/public/profile.js
136
- - lib/riemann/dash/public/mustache.js
137
- - lib/riemann/dash/public/persistence.js
138
- - lib/riemann/dash/public/util.js
139
110
  - lib/riemann/dash/public/clock.js
140
111
  - lib/riemann/dash/public/jquery.json-2.2.min.js
141
- - lib/riemann/dash/controller/css.rb
112
+ - lib/riemann/dash/public/keys.js
113
+ - lib/riemann/dash/version.rb
142
114
  - lib/riemann/dash/controller/index.rb
143
- - lib/riemann/dash/controller/websockets.rb
115
+ - lib/riemann/dash/controller/css.rb
116
+ - lib/riemann/dash/views/css.scss
144
117
  - lib/riemann/dash/views/layout.erubis
145
118
  - lib/riemann/dash/views/index.erubis
146
- - lib/riemann/dash/views/css.scss
147
- - lib/riemann/dash/views/websockets.erubis
148
- - lib/riemann/dash/helper/renderer.rb
149
- - lib/riemann/dash/rack/static.rb
150
119
  - bin/riemann-dash
151
120
  - LICENSE
152
121
  - README.markdown
@@ -170,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
139
  version: '0'
171
140
  requirements: []
172
141
  rubyforge_project: riemann-dash
173
- rubygems_version: 1.8.22
142
+ rubygems_version: 1.8.10
174
143
  signing_key:
175
144
  specification_version: 3
176
145
  summary: HTTP dashboard for the distributed event system Riemann.
@@ -1,50 +0,0 @@
1
- class Riemann::Dash
2
- require 'multi_json'
3
- require 'fileutils'
4
- require 'set'
5
-
6
- WS_CONFIG_FILE = "ws/config.json"
7
-
8
- get '/ws' do
9
- erb :websockets, :layout => false
10
- end
11
-
12
- get '/ws/config', :provides => 'json' do
13
- if File.exists? WS_CONFIG_FILE
14
- send_file WS_CONFIG_FILE, :type => :json
15
- else
16
- MultiJson.encode({})
17
- end
18
- end
19
-
20
- post '/ws/config' do
21
- # Read update
22
- request.body.rewind
23
- update = MultiJson.decode(request.body.read)
24
-
25
- # Read old config
26
- if File.exists? WS_CONFIG_FILE
27
- old = MultiJson.decode File.read WS_CONFIG_FILE
28
- else
29
- old = {}
30
- end
31
-
32
- new = {}
33
-
34
- # Server
35
- new['server'] = update['server'] or old['server']
36
-
37
- p update['workspaces']
38
- new['workspaces'] = update['workspaces'] or old['workspaces']
39
-
40
- # Save new config
41
- FileUtils.mkdir_p 'ws'
42
- File.open(WS_CONFIG_FILE, 'w') do |f|
43
- f.write(MultiJson.encode(new))
44
- end
45
-
46
- # Return current config
47
- content_type "application/json"
48
- MultiJson.encode(new)
49
- end
50
- end
@@ -1,266 +0,0 @@
1
- module Riemann
2
- class Dash
3
- helpers do
4
- include ::Rack::Utils
5
-
6
- alias_method :h, :escape_html
7
-
8
- # Returns a scalar factor from 0.2 to 1, where 0.2 is "on the order of
9
- # age_scale ago", and 1 is "very recent"
10
- def age_fraction(time)
11
- return 1 if time.nil?
12
-
13
- x = 1 - ((Time.now.to_f - time) / Dash.config[:age_scale])
14
- if x < 0.2
15
- 0.2
16
- elsif x > 1
17
- 1
18
- else
19
- x
20
- end
21
- end
22
-
23
- # Finds the longest common prefix of a list of strings.
24
- # i.e. 'abc, 'ab', 'abdf' => 'ab'
25
- def longest_common_prefix(strings, prefix = '')
26
- return strings.first if strings.size <= 1
27
-
28
- first = strings[0][0,1] or return prefix
29
- tails = strings[1..-1].inject([strings[0][1..-1]]) do |tails, string|
30
- if string[0,1] != first
31
- return prefix
32
- else
33
- tails << string[1..-1]
34
- end
35
- end
36
-
37
- longest_common_prefix(tails, prefix + first)
38
- end
39
-
40
- # An overview of states
41
- def state_list(states)
42
- ul(states.map { |s| state_short s })
43
- end
44
-
45
- def state_grid(states = Dash.client.query)
46
- h2('States by Host') +
47
- table(
48
- *Event.partition(states, :host).map do |host, states|
49
- tr(
50
- th(host, :class => 'host'),
51
- *Event.sort(states, :service).map do |state|
52
- state_short state
53
- end
54
- )
55
- end
56
- )
57
- end
58
-
59
- # Renders a state as the given HTML tag with a % width corresponding to
60
- # metric / max.
61
- def state_bar(s, opts = {})
62
- opts = {:tag => 'div', :max => 1}.merge opts
63
-
64
- return '' unless s
65
- x = s.metric
66
-
67
- # Text
68
- text = case x
69
- when Float
70
- '%.2f' % x
71
- when Integer
72
- x.to_s
73
- else
74
- s.state || '?'
75
- end
76
-
77
- # Size
78
- size = case x
79
- when 0
80
- 0
81
- when nil
82
- 100
83
- else
84
- begin
85
- x * 100 / opts[:max]
86
- rescue ZeroDivisionError
87
- 0
88
- end
89
- end
90
- size = "%.2f" % size
91
-
92
- time = Time.at(s.time).strftime(Dash.config[:strftime])
93
-
94
- tag opts[:tag], h(text),
95
- :class => "state #{s.state}",
96
- :style => "opacity: #{age_fraction s.time}; width: #{size}%",
97
- :title => "#{s.state}\n#{s.description}\n\n(at #{time})"
98
- end
99
-
100
- # Renders a set of states in a chart. Each row is a given host, each
101
- # service is a column. Each state is shown as a bar with an inferred
102
- # maximum for the entire service, so you can readily compare multiple
103
- # hosts.
104
- #
105
- # Takes a a set of states and options:
106
- # title: the title of the chart. Inferred to be the longest common
107
- # prefix of all services.
108
- # maxima: maps each service to the maximum value used to display its
109
- # bar.
110
- # service_names: maps each service to a friendly name. Default service
111
- # names have common prefixes removed.
112
- # hosts: an array of hosts for rows. Default is every host present in
113
- # states, sorted.
114
- # transpose: Hosts go across, services go down. Enables :global_maxima.
115
- # global_maximum: Compute default maxima for services globally,
116
- # instead of a different maximum for each service.
117
- def state_chart(states, opts = {})
118
- o = {
119
- :maxima => {},
120
- :service_names => {}
121
- }.merge opts
122
- if o[:transpose] and not o.include?(:global_maximum)
123
- o[:global_maximum] = true
124
- end
125
-
126
- # Get all services
127
- services = states.map { |s| s.service }.compact.uniq.sort
128
-
129
- # Figure out what name to use for each service.
130
- prefix = longest_common_prefix services
131
- service_names = services.inject({}) do |names, service|
132
- names[service] = service[prefix.length..-1]
133
- names
134
- end.merge o[:service_names]
135
-
136
- # Compute maximum for each service
137
- maxima = if o[:global_maximum]
138
- max = states.map(&:metric).compact.max
139
- services.inject({}) do |m, s|
140
- m[s] = max
141
- m
142
- end.merge o[:maxima]
143
- else
144
- states.inject(Hash.new(0)) do |m, s|
145
- if s.metric && !(s.metric.nan?)
146
- m[s.service] = [s.metric, m[s.service]].max
147
- end
148
- m
149
- end.merge o[:maxima]
150
- end
151
-
152
- # Compute union of all hosts for these states, if no
153
- # list of hosts explicitly given.
154
- hosts = o[:hosts] || states.map do |state|
155
- state.host
156
- end
157
- hosts = hosts.uniq.sort { |a, b|
158
- if !a
159
- -1
160
- elsif !b
161
- 1
162
- else
163
- a <=> b
164
- end
165
- }
166
-
167
- # Construct index
168
- by = states.inject({}) do |index, s|
169
- index[[s.host, s.service]] = s
170
- index
171
- end
172
-
173
- # Title
174
- title = o[:title] || prefix.capitalize rescue 'Unknown'
175
-
176
- if o[:transpose]
177
- h2(title) +
178
- table(
179
- tr(
180
- th,
181
- *hosts.map do |host|
182
- th host
183
- end
184
- ),
185
- *services.map do |service|
186
- tr(
187
- th(service_names[service]),
188
- *hosts.map do |host|
189
- s = by[[host, service]]
190
- td(
191
- s ? state_bar(s, :max => maxima[service]) : nil
192
- )
193
- end
194
- )
195
- end << {:class => 'chart'} # ruby 1.8.7 this is your fault
196
- )
197
- else
198
- h2(title) +
199
- table(
200
- tr(
201
- th,
202
- *services.map do |service|
203
- th service_names[service]
204
- end
205
- ),
206
- *hosts.map do |host|
207
- tr(
208
- th(host),
209
- *services.map do |service|
210
- s = by[[host, service]]
211
- td(
212
- s ? state_bar(s, :max => maxima[service]) : nil
213
- )
214
- end
215
- )
216
- end <<
217
- {:class => 'chart'}
218
- )
219
- end
220
- end
221
-
222
- # Renders a state as a short tag.
223
- def state_short(s, opts={:tag => 'li'})
224
- if s
225
- "<#{opts[:tag]} class=\"state #{s.state}\" style=\"opacity: #{age_fraction s.time}\" title=\"#{h s.description}\">#{h s.host} #{h s.service}</#{opts[:tag]}>"
226
- else
227
- "<#{opts[:tag]} class=\"service\"></#{opts[:tag]}>"
228
- end
229
- end
230
-
231
- # Renders a time to an HTML tag.
232
- def time(unix)
233
- t = Time.at(unix)
234
- "<time datetime=\"#{t.iso8601}\">#{t.strftime(Dash.config[:strftime])}</time>"
235
- end
236
-
237
- # Renders an HTML tag
238
- def tag(tag, *a)
239
- if Hash === a.last
240
- opts = a.pop
241
- else
242
- opts = {}
243
- end
244
-
245
- attrs = opts.map do |k,v|
246
- "#{k}=\"#{h v}\""
247
- end.join ' '
248
-
249
- content = if block_given?
250
- a << yield
251
- else
252
- a
253
- end.flatten.join("\n")
254
-
255
- s = "<#{tag} #{attrs}>#{content}</#{tag}>"
256
- end
257
-
258
- # Specific tag aliases
259
- %w(div span h1 h2 h3 h4 h5 h6 ul ol li table th tr td u i b).each do |tag|
260
- class_eval "def #{tag}(*a, &block)
261
- tag #{tag.inspect}, *a, &block
262
- end"
263
- end
264
- end
265
- end
266
- end