riemann-dash 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +31 -9
- data/README.markdown +18 -2
- data/example/config.rb +5 -0
- data/lib/riemann/dash.rb +1 -0
- data/lib/riemann/dash/app.rb +1 -0
- data/lib/riemann/dash/browser_config.rb +72 -0
- data/lib/riemann/dash/browser_config/file.rb +39 -0
- data/lib/riemann/dash/browser_config/s3.rb +30 -0
- data/lib/riemann/dash/config.rb +21 -41
- data/lib/riemann/dash/controller/index.rb +4 -4
- data/lib/riemann/dash/public/dash.js +4 -1
- data/lib/riemann/dash/public/eventPane.js +63 -0
- data/lib/riemann/dash/public/keys.js +1 -1
- data/lib/riemann/dash/public/strings.js +14 -2
- data/lib/riemann/dash/public/subs.js +13 -11
- data/lib/riemann/dash/public/util.js +41 -3
- data/lib/riemann/dash/public/view.js +56 -32
- data/lib/riemann/dash/public/views/flot.js +6 -1
- data/lib/riemann/dash/public/views/gauge.js +14 -1
- data/lib/riemann/dash/public/views/grid.js +155 -235
- data/lib/riemann/dash/public/views/help.js +1 -1
- data/lib/riemann/dash/public/views/list.js +73 -0
- data/lib/riemann/dash/public/views/log.js +3 -0
- data/lib/riemann/dash/version.rb +1 -1
- data/lib/riemann/dash/views/css.scss +60 -1
- data/lib/riemann/dash/views/index.erubis +3 -0
- data/riemann-dash.gemspec +2 -3
- metadata +15 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1dcb96d79006cd63317f46f52072596a7e8d8191
|
4
|
+
data.tar.gz: 57dbb5238edab2d60bdb09613be4ccb58cbd977f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6cf10ac7232174d526ae3666265e374246e89f7bb8a8e2a0a39b1199ef7c9e4f0db1f2b02ec6199c7e283a19902cda08639d81909f62cba726f07c53c90622e
|
7
|
+
data.tar.gz: 0aab886e0f0531fe1e5c075b2a54664b8e00da4d3f78028b21276c8b903c9c0cc34906fed09988d3180779e00866066917609946a9e43c274db388c5224edebe
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
riemann-dash (0.2.
|
4
|
+
riemann-dash (0.2.8)
|
5
5
|
erubis (>= 2.7.0)
|
6
|
+
fog
|
6
7
|
multi_json (= 1.3.6)
|
7
8
|
riemann-client (>= 0.0.7)
|
8
9
|
sass (>= 3.1.14)
|
@@ -12,34 +13,55 @@ PATH
|
|
12
13
|
GEM
|
13
14
|
remote: https://rubygems.org/
|
14
15
|
specs:
|
15
|
-
beefcake (0.
|
16
|
+
beefcake (0.5.0)
|
17
|
+
builder (3.2.2)
|
16
18
|
coderay (1.0.9)
|
17
19
|
daemons (1.1.9)
|
18
20
|
erubis (2.7.0)
|
19
21
|
eventmachine (1.0.3)
|
22
|
+
excon (0.31.0)
|
23
|
+
fog (1.19.0)
|
24
|
+
builder
|
25
|
+
excon (~> 0.31.0)
|
26
|
+
formatador (~> 0.2.0)
|
27
|
+
mime-types
|
28
|
+
multi_json (~> 1.0)
|
29
|
+
net-scp (~> 1.1)
|
30
|
+
net-ssh (>= 2.1.3)
|
31
|
+
nokogiri (~> 1.5)
|
32
|
+
ruby-hmac
|
33
|
+
formatador (0.2.4)
|
20
34
|
method_source (0.8.1)
|
35
|
+
mime-types (2.0)
|
36
|
+
mini_portile (0.5.2)
|
21
37
|
mtrc (0.0.4)
|
22
38
|
multi_json (1.3.6)
|
39
|
+
net-scp (1.1.2)
|
40
|
+
net-ssh (>= 2.6.5)
|
41
|
+
net-ssh (2.7.0)
|
42
|
+
nokogiri (1.6.1)
|
43
|
+
mini_portile (~> 0.5.0)
|
23
44
|
pry (0.9.12)
|
24
45
|
coderay (~> 1.0.5)
|
25
46
|
method_source (~> 0.8)
|
26
47
|
slop (~> 3.4)
|
27
48
|
rack (1.5.2)
|
28
|
-
rack-protection (1.5.
|
49
|
+
rack-protection (1.5.2)
|
29
50
|
rack
|
30
51
|
riemann-client (0.2.2)
|
31
52
|
beefcake (>= 0.3.5)
|
32
53
|
mtrc (>= 0.0.4)
|
33
54
|
trollop (>= 1.16.2)
|
34
|
-
|
35
|
-
|
55
|
+
ruby-hmac (0.4.0)
|
56
|
+
sass (3.3.2)
|
57
|
+
sinatra (1.4.4)
|
36
58
|
rack (~> 1.4)
|
37
|
-
rack-protection (~> 1.
|
38
|
-
tilt (~> 1.3, >= 1.3.
|
59
|
+
rack-protection (~> 1.4)
|
60
|
+
tilt (~> 1.3, >= 1.3.4)
|
39
61
|
slop (3.4.3)
|
40
|
-
thin (1.
|
62
|
+
thin (1.6.2)
|
41
63
|
daemons (>= 1.0.9)
|
42
|
-
eventmachine (>= 0.
|
64
|
+
eventmachine (>= 1.0.0)
|
43
65
|
rack (>= 1.0.0)
|
44
66
|
tilt (1.4.1)
|
45
67
|
trollop (2.0)
|
data/README.markdown
CHANGED
@@ -11,7 +11,10 @@ Get started
|
|
11
11
|
$ riemann-dash
|
12
12
|
```
|
13
13
|
|
14
|
-
Then open http://localhost:4567 in a browser. Riemann-dash will connect to the
|
14
|
+
Then open http://localhost:4567 in a browser. Riemann-dash will connect to the
|
15
|
+
local host (relative to your browser) by default, and show you a small manual.
|
16
|
+
Change the IP address in the top right field to point to your Riemann server's
|
17
|
+
websocket port.
|
15
18
|
|
16
19
|
Configuring
|
17
20
|
===========
|
@@ -19,7 +22,8 @@ Configuring
|
|
19
22
|
Riemann-dash takes an optional config file, which you can specify as the first
|
20
23
|
command-line argument. If none is given, it looks for a file in the local
|
21
24
|
directory: config.rb. That file can override any configuration options on the
|
22
|
-
Dash class, and hence, all Sinatra configuration.
|
25
|
+
Dash class, and hence, all Sinatra configuration. You'll find a few usage
|
26
|
+
examples in "example/config.rb".
|
23
27
|
|
24
28
|
``` ruby
|
25
29
|
set :port, 6000 # HTTP server on port 6000
|
@@ -27,7 +31,19 @@ set :bind, "1.2.3.4" # Bind to a different interface
|
|
27
31
|
config[:ws_config] = 'custom/config.json' # Specify custom workspace config
|
28
32
|
```
|
29
33
|
|
34
|
+
Putting in production
|
35
|
+
=====================
|
30
36
|
|
37
|
+
If you expect more than a couple of simultaneous users, you should consider
|
38
|
+
running Riemann-dash in a proper application server. The easiest way is to
|
39
|
+
install thin or puma. Riemann-dash will automatically use one of them if they
|
40
|
+
are present. You'll need the C/C++ compiler, as well as the ruby and openssl
|
41
|
+
libraries and headers installed.
|
42
|
+
|
43
|
+
``` bash
|
44
|
+
$ gem install riemann-dash thin
|
45
|
+
$ riemann-dash
|
46
|
+
```
|
31
47
|
|
32
48
|
Development
|
33
49
|
===========
|
data/example/config.rb
CHANGED
@@ -15,3 +15,8 @@ config.store[:ws_config] = "#{riemann_base}/config/config.json"
|
|
15
15
|
|
16
16
|
# Serve static files from this directory
|
17
17
|
config.store[:public] = "#{riemann_src}/public"
|
18
|
+
|
19
|
+
# Save workspace configuration to Amazon S3 (you'll need to have the "fog"
|
20
|
+
# gem installed)
|
21
|
+
# config.store[:ws_config] = 's3://my-bucket/config.json'
|
22
|
+
# config.store[:s3_config] = {:aws_access_key_id => "123ABC", :aws_secret_access_key => "789XYZ"}
|
data/lib/riemann/dash.rb
CHANGED
data/lib/riemann/dash/app.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Riemann::Dash::BrowserConfig
|
2
|
+
require 'multi_json'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
def self.backend
|
7
|
+
@backend
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.backend=(backend)
|
11
|
+
@backend = backend
|
12
|
+
end
|
13
|
+
|
14
|
+
# TODO: this is gonna take significant restructuring of the dashboard itself,
|
15
|
+
# but we should move to http://arxiv.org/abs/1201.1784 or equivalent CRDTs.
|
16
|
+
|
17
|
+
# Given a function to extract a key from an element, and a list of elements,
|
18
|
+
# returns a map of keys to elements. Keys are assumed unique.
|
19
|
+
def self.index_by(keyfn, list)
|
20
|
+
list.reduce({}) do |index, element|
|
21
|
+
index[keyfn.call(element)] = element
|
22
|
+
index
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Merges two lists, given a key function which determines equivalent
|
27
|
+
# elements, and a merge function to combine equivalent elements.
|
28
|
+
def self.merge_lists(keyfn, mergefn, as, bs)
|
29
|
+
asi = index_by keyfn, as
|
30
|
+
bsi = index_by keyfn, bs
|
31
|
+
ids = (as + bs).map(&keyfn).uniq.map do |key|
|
32
|
+
mergefn.call asi[key], bsi[key]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Merge two workspaces together
|
37
|
+
def self.merge_workspace(a, b)
|
38
|
+
# TODO: workspace versions
|
39
|
+
return a unless b
|
40
|
+
return b unless a
|
41
|
+
if (a['view']['version'] || 0) < (b['view']['version'] || 0)
|
42
|
+
b
|
43
|
+
else
|
44
|
+
a
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Merge a list of workspaces together
|
49
|
+
def self.merge_workspaces(as, bs)
|
50
|
+
return as unless bs
|
51
|
+
return bs unless as
|
52
|
+
merge_lists(lambda { |x| x['name'] },
|
53
|
+
method(:merge_workspace),
|
54
|
+
as,
|
55
|
+
bs)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Merge two configs together
|
59
|
+
def self.merge_configs(a, b)
|
60
|
+
a.merge 'server' => (a['server'] or b['server']),
|
61
|
+
'server_type' => (a['server_type'] or b['server_type']),
|
62
|
+
'workspaces' => merge_workspaces(a['workspaces'], b['workspaces'])
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.read
|
66
|
+
backend.read
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.update(update)
|
70
|
+
backend.update(update)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Riemann::Dash::BrowserConfig::File
|
2
|
+
require 'multi_json'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def read
|
10
|
+
if ::File.exists? @path
|
11
|
+
::File.open(@path, 'r') do |f|
|
12
|
+
f.flock ::File::LOCK_SH
|
13
|
+
f.read
|
14
|
+
end
|
15
|
+
else
|
16
|
+
MultiJson.encode({})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(update)
|
21
|
+
update = MultiJson.decode update
|
22
|
+
|
23
|
+
# Read old config
|
24
|
+
old = MultiJson.decode read
|
25
|
+
|
26
|
+
new = Riemann::Dash::BrowserConfig.merge_configs update, old
|
27
|
+
|
28
|
+
# Save new config
|
29
|
+
FileUtils.mkdir_p ::File.dirname(@path)
|
30
|
+
begin
|
31
|
+
::File.open(@path, ::File::RDWR|::File::CREAT, 0644) do |f|
|
32
|
+
f.flock ::File::LOCK_EX
|
33
|
+
f.write(MultiJson.encode(new, :pretty => true))
|
34
|
+
f.flush
|
35
|
+
f.truncate f.pos
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Riemann::Dash::BrowserConfig::S3
|
2
|
+
require 'multi_json'
|
3
|
+
require 'fog'
|
4
|
+
|
5
|
+
def initialize(bucket, path, config = {})
|
6
|
+
@bucket = bucket
|
7
|
+
@path = path
|
8
|
+
@config = config
|
9
|
+
|
10
|
+
@storage = Fog::Storage::AWS.new(config)
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
begin
|
15
|
+
@storage.get_object(@bucket, @path).body
|
16
|
+
rescue Excon::Errors::NotFound
|
17
|
+
MultiJson.encode({})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update(update)
|
22
|
+
update = MultiJson.decode update
|
23
|
+
|
24
|
+
# Read old config
|
25
|
+
old = MultiJson.decode read
|
26
|
+
|
27
|
+
new = Riemann::Dash::BrowserConfig.merge_configs update, old
|
28
|
+
@storage.put_object @bucket, @path, MultiJson.encode(new, :pretty => true)
|
29
|
+
end
|
30
|
+
end
|
data/lib/riemann/dash/config.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
class Riemann::Dash::Config
|
2
|
+
require 'uri'
|
3
|
+
|
2
4
|
attr_accessor :config_path
|
3
5
|
attr_accessor :store
|
4
6
|
|
@@ -62,6 +64,25 @@ class Riemann::Dash::Config
|
|
62
64
|
Riemann::Dash::App.use Riemann::Dash::Static, :root => store[:public]
|
63
65
|
end
|
64
66
|
|
67
|
+
def setup_storage_backend
|
68
|
+
uri = URI.parse(ws_config_file)
|
69
|
+
backend = case uri.scheme
|
70
|
+
when "s3"
|
71
|
+
begin
|
72
|
+
require 'riemann/dash/browser_config/s3'
|
73
|
+
Riemann::Dash::BrowserConfig::S3.new(uri.host, uri.path.sub(/^\//, ''), store[:s3_config])
|
74
|
+
rescue LoadError
|
75
|
+
raise Exception.new 'Fog library required to save to S3. Run: "gem install fog"'
|
76
|
+
end
|
77
|
+
when nil, "file"
|
78
|
+
require 'riemann/dash/browser_config/file'
|
79
|
+
Riemann::Dash::BrowserConfig::File.new(uri.path)
|
80
|
+
else
|
81
|
+
raise Exception.new "Unknown backend for #{ws_config_file}"
|
82
|
+
end
|
83
|
+
Riemann::Dash::BrowserConfig.backend = backend
|
84
|
+
end
|
85
|
+
|
65
86
|
# Load controllers.
|
66
87
|
def load_controllers_from(dir)
|
67
88
|
sorted_controller_list(dir).each do |r|
|
@@ -113,45 +134,4 @@ class Riemann::Dash::Config
|
|
113
134
|
end
|
114
135
|
end
|
115
136
|
end
|
116
|
-
|
117
|
-
|
118
|
-
require 'multi_json'
|
119
|
-
require 'fileutils'
|
120
|
-
|
121
|
-
|
122
|
-
def read_ws_config
|
123
|
-
if File.exists? ws_config_file
|
124
|
-
File.read(ws_config_file)
|
125
|
-
else
|
126
|
-
MultiJson.encode({})
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def update_ws_config(update)
|
131
|
-
update = MultiJson.decode(update)
|
132
|
-
|
133
|
-
# Read old config
|
134
|
-
if File.exists? ws_config_file
|
135
|
-
old = MultiJson.decode File.read(ws_config_file)
|
136
|
-
else
|
137
|
-
old = {}
|
138
|
-
end
|
139
|
-
|
140
|
-
new_config = {}
|
141
|
-
|
142
|
-
# Server
|
143
|
-
new_config['server'] = update['server'] or old['server']
|
144
|
-
|
145
|
-
# Server Type
|
146
|
-
new_config['server_type'] = update['server_type'] or old['server_type']
|
147
|
-
|
148
|
-
#p update['workspaces']
|
149
|
-
new_config['workspaces'] = update['workspaces'] or old['workspaces']
|
150
|
-
|
151
|
-
# Save new config
|
152
|
-
FileUtils.mkdir_p File.dirname(ws_config_file)
|
153
|
-
File.open(ws_config_file, 'w') do |f|
|
154
|
-
f.write(MultiJson.encode(new_config, :pretty => true))
|
155
|
-
end
|
156
|
-
end
|
157
137
|
end
|
@@ -5,16 +5,16 @@ class Riemann::Dash::App
|
|
5
5
|
|
6
6
|
get '/config', :provides => 'json' do
|
7
7
|
content_type "application/json"
|
8
|
-
|
8
|
+
Riemann::Dash::BrowserConfig.read
|
9
9
|
end
|
10
10
|
|
11
11
|
post '/config' do
|
12
12
|
# Read update
|
13
13
|
request.body.rewind
|
14
|
-
|
14
|
+
Riemann::Dash::BrowserConfig.update request.body.read
|
15
15
|
|
16
16
|
# Return current config
|
17
17
|
content_type "application/json"
|
18
|
-
|
18
|
+
Riemann::Dash::BrowserConfig.read
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
@@ -193,17 +193,20 @@ dash = (function() {
|
|
193
193
|
'<li><b>e</b>: edit the view</li>' +
|
194
194
|
'<li><b>?</b>: display this help box</li>' +
|
195
195
|
'<li><b>s</b>: save the dashboard</li>' +
|
196
|
+
'<li><b>r</b>: reload the dashboard from last saved config</li>' +
|
196
197
|
'<li><b>+</b>: increase the size of the view</li>' +
|
197
198
|
'<li><b>-</b>: decrease the size of the view</li>' +
|
198
199
|
'<li><b>v</b>: split the view vertically</li>' +
|
199
200
|
'<li><b>h</b>: split the view horizontally</li>' +
|
200
201
|
'<li><b>←</b>: left arrow move the view to the left</li>' +
|
201
202
|
'<li><b>→</b>: right arrow move the view to the right</li>' +
|
202
|
-
'<li><b>↑</b>: up arrow move the view up>' +
|
203
|
+
'<li><b>↑</b>: up arrow move the view up</li>' +
|
203
204
|
'<li><b>↓</b>: down arrow move the view down</li>' +
|
205
|
+
'<li><b>pageup</b>: select the parent of the current view</li>' +
|
204
206
|
'<li><b>d</b>: delete a view</li>' +
|
205
207
|
'<li><b>delete</b>: delete a view</li>' +
|
206
208
|
'<li><b>alt-1, alt-2, etc</b>: switch to a different workplace</li>' +
|
209
|
+
'<li><b>p</b>: pause/unpause the event stream(s)</li>' +
|
207
210
|
'</ul></div>'
|
208
211
|
);
|
209
212
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
// Pane at the bottom of the dashboard for displaying events in context.
|
2
|
+
|
3
|
+
var eventPane = (function() {
|
4
|
+
var el = $('#event-pane');
|
5
|
+
var fixedFields = ['host', 'service', 'time', 'state', 'metric', 'ttl', 'description', 'tags'];
|
6
|
+
var fixedTemplate =
|
7
|
+
_.template(
|
8
|
+
'<div class="host">{{-host}}</div>' +
|
9
|
+
'<div class="service">{{-service}}</div>' +
|
10
|
+
'<div class="state {{-state}}">{{-state}}</div>' +
|
11
|
+
'<div class="metric">{{-metric}}</div>' +
|
12
|
+
'<time class="absolute">{{-time}}</time>' +
|
13
|
+
'<div class="ttl">{{-ttl}}</div>' +
|
14
|
+
'<div class="tags">{{-tags}}</div>' +
|
15
|
+
'<div class="description">{{-description}}</description>');
|
16
|
+
|
17
|
+
var rowTemplate =
|
18
|
+
_.template("<tr><td>{{-field}}</td><td>{{-value}}</td></tr>");
|
19
|
+
|
20
|
+
// Hide the pane
|
21
|
+
var hide = function() {
|
22
|
+
if (el.hasClass("active")) {
|
23
|
+
el.empty();
|
24
|
+
el.removeClass("active");
|
25
|
+
}
|
26
|
+
};
|
27
|
+
|
28
|
+
// Show an event in the pane
|
29
|
+
var show = function(event) {
|
30
|
+
hide();
|
31
|
+
|
32
|
+
if (! el.hasClass("active")) {
|
33
|
+
el.addClass("active");
|
34
|
+
}
|
35
|
+
|
36
|
+
el.append(
|
37
|
+
fixedTemplate(
|
38
|
+
_.defaults(
|
39
|
+
util.merge(event, {time: new Date(event.time)}),
|
40
|
+
{host: "nil",
|
41
|
+
service: "nil",
|
42
|
+
state: "nil",
|
43
|
+
metric: "nil",
|
44
|
+
ttl: "nil",
|
45
|
+
tags: "nil",
|
46
|
+
description: "nil"})));
|
47
|
+
|
48
|
+
var table = el.append('<table></table>');
|
49
|
+
|
50
|
+
// Remaining fields
|
51
|
+
_.each(event, function(value, field) {
|
52
|
+
if (! _.contains(fixedFields, field)) {
|
53
|
+
table.append(rowTemplate({field: field, value: value}));
|
54
|
+
}
|
55
|
+
});
|
56
|
+
};
|
57
|
+
|
58
|
+
// Hide on escape.
|
59
|
+
keys.bind(27, hide);
|
60
|
+
|
61
|
+
return {show: show,
|
62
|
+
hide: hide};
|
63
|
+
})();
|