riemann-dash 0.0.3
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/LICENSE +21 -0
- data/README.markdown +51 -0
- data/bin/riemann-dash +7 -0
- data/lib/riemann/dash/controller/css.rb +5 -0
- data/lib/riemann/dash/controller/index.rb +5 -0
- data/lib/riemann/dash/helper/renderer.rb +258 -0
- data/lib/riemann/dash/rack/static.rb +16 -0
- data/lib/riemann/dash/version.rb +4 -0
- data/lib/riemann/dash/views/css.scss +39 -0
- data/lib/riemann/dash/views/index.erubis +8 -0
- data/lib/riemann/dash/views/layout.erubis +21 -0
- data/lib/riemann/dash.rb +126 -0
- metadata +112 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Kyle Kingsbury
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Riemann-Dash
|
2
|
+
============
|
3
|
+
|
4
|
+
An extensible Sinatra dashboard for Riemann. Connects to Riemann over the
|
5
|
+
network and shows events matching the queries you configure.
|
6
|
+
|
7
|
+
Get started
|
8
|
+
==========
|
9
|
+
|
10
|
+
``` bash
|
11
|
+
gem install riemann-dash
|
12
|
+
riemann-dash
|
13
|
+
```
|
14
|
+
|
15
|
+
Riemann-dash will connect to a local Riemann server on port 5555, and display a
|
16
|
+
basic dashboard of all events in that server's index.
|
17
|
+
|
18
|
+
Configuring
|
19
|
+
===========
|
20
|
+
|
21
|
+
Riemann-dash takes an optional config file, which you can specify as the first
|
22
|
+
command-line argument. If none is given, it looks for a file in the local
|
23
|
+
directory: config.rb. That file can override any configuration options on the
|
24
|
+
Dash class (hence all Sinatra configuration) as well as the Riemann client
|
25
|
+
options, etc.
|
26
|
+
|
27
|
+
``` ruby
|
28
|
+
set :port, 6000 # HTTP server on port 6000
|
29
|
+
config[:client][:host] = 'my.ustate.server'
|
30
|
+
```
|
31
|
+
|
32
|
+
You'll probably want a more specific dashboard:
|
33
|
+
|
34
|
+
``` ruby
|
35
|
+
config[:view] = 'my/custom/view'
|
36
|
+
```
|
37
|
+
|
38
|
+
Then you can write your own index.erb (and other views too, if you like). I've
|
39
|
+
provided an default stylesheet, layout, and dashboard in
|
40
|
+
lib/riemann/dash/views--as well as an extensive set of functions for laying out
|
41
|
+
events from a given query: see lib/riemann/dash/helper/renderer.rb.
|
42
|
+
|
43
|
+
A long history with cacti, nagios, and the like has convinced me that a.) web
|
44
|
+
configuration of dashboards is inevitably slower than just writing the code and
|
45
|
+
b.) you're almost certainly going to want to need more functions than I can
|
46
|
+
give you. My goal is to give you the tools to make it easier and get out of
|
47
|
+
your way.
|
48
|
+
|
49
|
+
An example config.rb, additional controllers, views, and public directory are
|
50
|
+
all in doc/dash. Should give you ideas for extending the dashboard for your own
|
51
|
+
needs.
|
data/bin/riemann-dash
ADDED
@@ -0,0 +1,258 @@
|
|
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
|
+
'?'
|
75
|
+
end
|
76
|
+
|
77
|
+
# Size
|
78
|
+
size = begin
|
79
|
+
(x || 0) * 100 / opts[:max]
|
80
|
+
rescue ZeroDivisionError
|
81
|
+
0
|
82
|
+
end
|
83
|
+
size = "%.2f" % size
|
84
|
+
|
85
|
+
tag opts[:tag], h(text),
|
86
|
+
:class => "state #{s.state}",
|
87
|
+
style: "opacity: #{age_fraction s.time}; width: #{size}%",
|
88
|
+
title: s.description
|
89
|
+
end
|
90
|
+
|
91
|
+
# Renders a set of states in a chart. Each row is a given host, each
|
92
|
+
# service is a column. Each state is shown as a bar with an inferred
|
93
|
+
# maximum for the entire service, so you can readily compare multiple
|
94
|
+
# hosts.
|
95
|
+
#
|
96
|
+
# Takes a a set of states and options:
|
97
|
+
# title: the title of the chart. Inferred to be the longest common
|
98
|
+
# prefix of all services.
|
99
|
+
# maxima: maps each service to the maximum value used to display its
|
100
|
+
# bar.
|
101
|
+
# service_names: maps each service to a friendly name. Default service
|
102
|
+
# names have common prefixes removed.
|
103
|
+
# hosts: an array of hosts for rows. Default is every host present in
|
104
|
+
# states, sorted.
|
105
|
+
# transpose: Hosts go across, services go down. Enables :global_maxima.
|
106
|
+
# global_maximum: Compute default maxima for services globally,
|
107
|
+
# instead of a different maximum for each service.
|
108
|
+
def state_chart(states, opts = {})
|
109
|
+
o = {
|
110
|
+
:maxima => {},
|
111
|
+
:service_names => {}
|
112
|
+
}.merge opts
|
113
|
+
if o[:transpose] and not o.include?(:global_maximum)
|
114
|
+
o[:global_maximum] = true
|
115
|
+
end
|
116
|
+
|
117
|
+
# Get all services
|
118
|
+
services = states.map { |s| s.service }.compact.uniq.sort
|
119
|
+
|
120
|
+
# Figure out what name to use for each service.
|
121
|
+
prefix = longest_common_prefix services
|
122
|
+
service_names = services.inject({}) do |names, service|
|
123
|
+
names[service] = service[prefix.length..-1]
|
124
|
+
names
|
125
|
+
end.merge o[:service_names]
|
126
|
+
|
127
|
+
# Compute maximum for each service
|
128
|
+
maxima = if o[:global_maximum]
|
129
|
+
max = states.map(&:metric).compact.max
|
130
|
+
services.inject({}) do |m, s|
|
131
|
+
m[s] = max
|
132
|
+
m
|
133
|
+
end.merge o[:maxima]
|
134
|
+
else
|
135
|
+
states.inject(Hash.new(0)) do |m, s|
|
136
|
+
if s.metric
|
137
|
+
m[s.service] = [s.metric, m[s.service]].max
|
138
|
+
end
|
139
|
+
m
|
140
|
+
end.merge o[:maxima]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Compute union of all hosts for these states, if no
|
144
|
+
# list of hosts explicitly given.
|
145
|
+
hosts = o[:hosts] || states.map do |state|
|
146
|
+
state.host
|
147
|
+
end
|
148
|
+
hosts = hosts.uniq.sort { |a, b|
|
149
|
+
if !a
|
150
|
+
-1
|
151
|
+
elsif !b
|
152
|
+
1
|
153
|
+
else
|
154
|
+
a <=> b
|
155
|
+
end
|
156
|
+
}
|
157
|
+
|
158
|
+
# Construct index
|
159
|
+
by = states.inject({}) do |index, s|
|
160
|
+
index[[s.host, s.service]] = s
|
161
|
+
index
|
162
|
+
end
|
163
|
+
|
164
|
+
# Title
|
165
|
+
title = o[:title] || prefix.capitalize rescue 'Unknown'
|
166
|
+
|
167
|
+
if o[:transpose]
|
168
|
+
h2(title) +
|
169
|
+
table(
|
170
|
+
tr(
|
171
|
+
th,
|
172
|
+
*hosts.map do |host|
|
173
|
+
th host
|
174
|
+
end
|
175
|
+
),
|
176
|
+
*services.map do |service|
|
177
|
+
tr(
|
178
|
+
th(service_names[service]),
|
179
|
+
*hosts.map do |host|
|
180
|
+
s = by[[host, service]]
|
181
|
+
td(
|
182
|
+
s ? state_bar(s, max: maxima[service]) : nil
|
183
|
+
)
|
184
|
+
end
|
185
|
+
)
|
186
|
+
end,
|
187
|
+
:class => 'chart'
|
188
|
+
)
|
189
|
+
else
|
190
|
+
h2(title) +
|
191
|
+
table(
|
192
|
+
tr(
|
193
|
+
th,
|
194
|
+
*services.map do |service|
|
195
|
+
th service_names[service]
|
196
|
+
end
|
197
|
+
),
|
198
|
+
*hosts.map do |host|
|
199
|
+
tr(
|
200
|
+
th(host),
|
201
|
+
*services.map do |service|
|
202
|
+
s = by[[host, service]]
|
203
|
+
td(
|
204
|
+
s ? state_bar(s, max: maxima[service]) : nil
|
205
|
+
)
|
206
|
+
end
|
207
|
+
)
|
208
|
+
end,
|
209
|
+
:class => 'chart'
|
210
|
+
)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Renders a state as a short tag.
|
215
|
+
def state_short(s, opts={tag: 'li'})
|
216
|
+
if s
|
217
|
+
"<#{opts[:tag]} class=\"state #{s.state}\" style=\"opacity: #{age_fraction s.time}\" title=\"#{h s.description}\">#{h s.host} #{h s.service}</#{opts[:tag]}>"
|
218
|
+
else
|
219
|
+
"<#{opts[:tag]} class=\"service\"></#{opts[:tag]}>"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Renders a time to an HTML tag.
|
224
|
+
def time(unix)
|
225
|
+
t = Time.at(unix)
|
226
|
+
"<time datetime=\"#{t.iso8601}\">#{t.strftime(Dash.config[:strftime])}</time>"
|
227
|
+
end
|
228
|
+
|
229
|
+
# Renders an HTML tag
|
230
|
+
def tag(tag, *a)
|
231
|
+
if Hash === a.last
|
232
|
+
opts = a.pop
|
233
|
+
else
|
234
|
+
opts = {}
|
235
|
+
end
|
236
|
+
|
237
|
+
attrs = opts.map do |k,v|
|
238
|
+
"#{k}=\"#{h v}\""
|
239
|
+
end.join ' '
|
240
|
+
|
241
|
+
content = if block_given?
|
242
|
+
a << yield
|
243
|
+
else
|
244
|
+
a
|
245
|
+
end.flatten.join("\n")
|
246
|
+
|
247
|
+
s = "<#{tag} #{attrs}>#{content}</#{tag}>"
|
248
|
+
end
|
249
|
+
|
250
|
+
# Specific tag aliases
|
251
|
+
%w(div span h1 h2 h3 h4 h5 h6 ul ol li table th tr td u i b).each do |tag|
|
252
|
+
class_eval "def #{tag}(*a, &block)
|
253
|
+
tag #{tag.inspect}, *a, &block
|
254
|
+
end"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Riemann::Dash::Static
|
2
|
+
def initialize(app, options = {})
|
3
|
+
@app = app
|
4
|
+
@root = options[:root] or raise ArgumentError, "no root"
|
5
|
+
@file_server = ::Rack::File.new(@root)
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
r = @file_server.call env
|
10
|
+
if r[0] == 404
|
11
|
+
@app.call env
|
12
|
+
else
|
13
|
+
r
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
html,table {
|
2
|
+
font-family: Helvetica Nueue, Helvetica, sans;
|
3
|
+
font-size: 8pt;
|
4
|
+
}
|
5
|
+
h1 {
|
6
|
+
margin-bottom: 0.2em;
|
7
|
+
}
|
8
|
+
h2 {
|
9
|
+
margin-top: 0;
|
10
|
+
margin-bottom: 0.1em;
|
11
|
+
}
|
12
|
+
|
13
|
+
.box {
|
14
|
+
float: left;
|
15
|
+
margin: 4px;
|
16
|
+
}
|
17
|
+
|
18
|
+
.ok {
|
19
|
+
background: #B8F1BC;
|
20
|
+
}
|
21
|
+
.warning {
|
22
|
+
background: #F7D18E;
|
23
|
+
}
|
24
|
+
.critical {
|
25
|
+
background: #FF3C43;
|
26
|
+
}
|
27
|
+
|
28
|
+
.chart {
|
29
|
+
width: 140px;
|
30
|
+
border: 1px solid #ccc;
|
31
|
+
}
|
32
|
+
.chart td {
|
33
|
+
min-width: 40px;
|
34
|
+
overflow: hidden;
|
35
|
+
}
|
36
|
+
.chart th {
|
37
|
+
width: 1px;
|
38
|
+
text-align: left;
|
39
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<h2>Problems</h2>
|
2
|
+
<div class="box"><%= state_list query('state != "ok"') %></div>
|
3
|
+
|
4
|
+
<div class="box">
|
5
|
+
<%= state_chart query('service = "cpu" or service = "memory" or service =~ "disk%" or service = "load"'), title: "Health" %>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="box"><%= state_chart query('true'), title: "Everything" %></div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Dashboard</title>
|
4
|
+
<link rel="stylesheet" type="text/css" href="/css" />
|
5
|
+
|
6
|
+
<script type="text/javascript">
|
7
|
+
setTimeout(function() {
|
8
|
+
location.reload(true);
|
9
|
+
}, 10000);
|
10
|
+
</script>
|
11
|
+
</head>
|
12
|
+
|
13
|
+
<body onload="refresh();">
|
14
|
+
<div>
|
15
|
+
<h1>Dashboard</h1>
|
16
|
+
<span style="position: absolute; top: 4px; right: 4px;">(as of <%= time Time.now.to_i %>)</span>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<%= yield %>
|
20
|
+
</body>
|
21
|
+
</html>
|
data/lib/riemann/dash.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'riemann/client'
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
module Riemann
|
5
|
+
class Dash < Sinatra::Base
|
6
|
+
# A little dashboard sinatra application.
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
require 'find'
|
10
|
+
require 'erubis'
|
11
|
+
require 'sass'
|
12
|
+
|
13
|
+
def self.config
|
14
|
+
@config ||= {
|
15
|
+
client: {},
|
16
|
+
age_scale: 60 * 30,
|
17
|
+
state_order: {
|
18
|
+
'critical' => 3,
|
19
|
+
'warning' => 2,
|
20
|
+
'ok' => 1
|
21
|
+
},
|
22
|
+
strftime: '%H:%M:%S',
|
23
|
+
controllers: [File.join(File.dirname(__FILE__), 'dash', 'controller')],
|
24
|
+
helpers: [File.join(File.dirname(__FILE__), 'dash', 'helper')],
|
25
|
+
views: File.join(File.dirname(__FILE__), 'dash', 'views')
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.client
|
30
|
+
@client ||= Riemann::Client.new(config[:client])
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.load(filename)
|
34
|
+
unless load_config(filename || 'config.rb')
|
35
|
+
# Configuration failed; load a default view.
|
36
|
+
puts "No configuration loaded; using defaults."
|
37
|
+
end
|
38
|
+
|
39
|
+
config[:controllers].each { |d| load_controllers d }
|
40
|
+
config[:helpers].each { |d| load_helpers d }
|
41
|
+
set :views, File.expand_path(config[:views])
|
42
|
+
end
|
43
|
+
|
44
|
+
# Executes the configuration file.
|
45
|
+
def self.load_config(filename)
|
46
|
+
begin
|
47
|
+
instance_eval File.read(filename)
|
48
|
+
true
|
49
|
+
rescue Errno::ENOENT
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Load controllers.
|
55
|
+
# Controllers can be regular old one-file-per-class, but if you prefer a little
|
56
|
+
# more modularity, this method will allow you to define all controller methods
|
57
|
+
# in their own files. For example, get "/posts/*/edit" can live in
|
58
|
+
# controller/posts/_/edit.rb. The sorting system provided here requires
|
59
|
+
# files in the correct order to handle wildcards appropriately.
|
60
|
+
def self.load_controllers(dir)
|
61
|
+
rbs = []
|
62
|
+
Find.find(
|
63
|
+
File.expand_path(dir)
|
64
|
+
) do |path|
|
65
|
+
rbs << path if path =~ /\.rb$/
|
66
|
+
end
|
67
|
+
|
68
|
+
# Sort paths with _ last, becase those are wildcards.
|
69
|
+
rbs.sort! do |a, b|
|
70
|
+
as = a.split File::SEPARATOR
|
71
|
+
bs = b.split File::SEPARATOR
|
72
|
+
|
73
|
+
# Compare common subpaths
|
74
|
+
l = [as.size, bs.size].min
|
75
|
+
catch :x do
|
76
|
+
(0...l).each do |i|
|
77
|
+
a, b = as[i], bs[i]
|
78
|
+
if a[/^_/] and not b[/^_/]
|
79
|
+
throw :x, 1
|
80
|
+
elsif b[/^_/] and not a[/^_/]
|
81
|
+
throw :x, -1
|
82
|
+
elsif ord = (a <=> b) and ord != 0
|
83
|
+
throw :x, ord
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# All subpaths are identical; sort longest first
|
88
|
+
if as.size > bs.size
|
89
|
+
throw :x, -1
|
90
|
+
elsif as.size < bs.size
|
91
|
+
throw :x, -1
|
92
|
+
else
|
93
|
+
throw :x, 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
rbs.each do |r|
|
99
|
+
require r
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Load helpers
|
104
|
+
def self.load_helpers(dir)
|
105
|
+
Find.find(
|
106
|
+
File.expand_path(dir)
|
107
|
+
) do |path|
|
108
|
+
require path if path =~ /\.rb$/
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Add an additional public directory.
|
113
|
+
def self.public_dir(dir)
|
114
|
+
require 'riemann/dash/rack/static'
|
115
|
+
use Riemann::Dash::Static, :root => dir
|
116
|
+
end
|
117
|
+
|
118
|
+
def client
|
119
|
+
self.class.client
|
120
|
+
end
|
121
|
+
|
122
|
+
def query(*a)
|
123
|
+
self.class.client.query(*a).events || []
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: riemann-dash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kyle Kingsbury
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: riemann-client
|
16
|
+
requirement: &9900960 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.0.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *9900960
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: erubis
|
27
|
+
requirement: &9900240 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.7.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *9900240
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sinatra
|
38
|
+
requirement: &9899640 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.3.2
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *9899640
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sass
|
49
|
+
requirement: &9898820 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.1.14
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *9898820
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: thin
|
60
|
+
requirement: &9898320 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.3.1
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *9898320
|
69
|
+
description:
|
70
|
+
email: aphyr@aphyr.com
|
71
|
+
executables:
|
72
|
+
- riemann-dash
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/riemann/dash.rb
|
77
|
+
- lib/riemann/dash/version.rb
|
78
|
+
- lib/riemann/dash/rack/static.rb
|
79
|
+
- lib/riemann/dash/views/index.erubis
|
80
|
+
- lib/riemann/dash/views/layout.erubis
|
81
|
+
- lib/riemann/dash/views/css.scss
|
82
|
+
- lib/riemann/dash/controller/index.rb
|
83
|
+
- lib/riemann/dash/controller/css.rb
|
84
|
+
- lib/riemann/dash/helper/renderer.rb
|
85
|
+
- bin/riemann-dash
|
86
|
+
- LICENSE
|
87
|
+
- README.markdown
|
88
|
+
homepage: https://github.com/aphyr/riemann-dash
|
89
|
+
licenses: []
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.9.1
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project: riemann-dash
|
108
|
+
rubygems_version: 1.8.10
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: HTTP dashboard for the distributed event system Riemann.
|
112
|
+
test_files: []
|