prosperity 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/prosperity/application.js.coffee +2 -1
- data/app/assets/javascripts/prosperity/graph.js.coffee +74 -59
- data/app/assets/stylesheets/prosperity/application.css.scss +2 -1
- data/app/assets/stylesheets/prosperity/{graph.css → graph.css.scss} +8 -0
- data/app/controllers/prosperity/dashboards_controller.rb +14 -3
- data/app/controllers/prosperity/metrics_controller.rb +6 -1
- data/app/helpers/prosperity/application_helper.rb +12 -0
- data/app/views/layouts/prosperity/application.html.erb +2 -6
- data/app/views/prosperity/dashboards/edit.html.erb +5 -0
- data/app/views/prosperity/dashboards/index.html.erb +23 -9
- data/app/views/prosperity/dashboards/show.html.erb +6 -2
- data/lib/prosperity/extractors/base.rb +5 -1
- data/lib/prosperity/metric.rb +4 -0
- data/lib/prosperity/metrics/option.rb +4 -0
- data/lib/prosperity/version.rb +1 -1
- data/spec/controllers/prosperity/dashboards_controller_spec.rb +12 -1
- data/spec/controllers/prosperity/metrics_controller_spec.rb +6 -0
- data/spec/dummy/log/development.log +26773 -0
- data/spec/dummy/log/test.log +173 -0
- data/spec/dummy/tmp/cache/assets/development/sass/34a577735054231563e7022ea73e1468db9203ba/application.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/34a577735054231563e7022ea73e1468db9203ba/graph.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/141de7c3ad5525ad5025adc93847a47a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/197492ed379339e17a0f5d01d3b01b8c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1c55cf24465f311353197ce336df0178 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/204a30f61e29169229793bc31dd34207 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/210050da208fb75a75b701bfa4e8470f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/27a59e08207d3ae723f2b2b3d22264c3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/362e15a54951b12cfa5c6ad2c3dda49c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3be1fec30b381948e1e84408642a618f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3e6afb4834057e5b5c7e593d0894a8bb +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/526534cd50ee53edadd65c1df71398fc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5f7660fd92b228b2de09f92d54ca6b49 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6882b260ae69f1594eff540d803e5ac3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7eb9384654be8c4fc859b9736c0da9d0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/828a046f0e7dc2dad0eecfe49d31e14d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/872d17fb6fb4675e5c24b21bdd90bc86 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8ac3ddd03a0ca38df655faf85c8a054d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8c8bcb1384dcbb664e642754f197c899 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a2b14d5c46db32da9183354fb3fcd0bf +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a6d6196cfd275dea0718553a95f997a5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/aacfd4457155e8607cbe66d5fdaf11b3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d94883bc533251c5e4b4821c716ae300 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e0d03169ae2f0680d574ca2e19129450 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e76f5e84c165c22920d69c5dafce2fe1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f4648036e284d9aa3468f4f7b9bbb967 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/34a577735054231563e7022ea73e1468db9203ba/application.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sass/34a577735054231563e7022ea73e1468db9203ba/graph.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/141de7c3ad5525ad5025adc93847a47a +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/197492ed379339e17a0f5d01d3b01b8c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/1c55cf24465f311353197ce336df0178 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/210050da208fb75a75b701bfa4e8470f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/27a59e08207d3ae723f2b2b3d22264c3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/362e15a54951b12cfa5c6ad2c3dda49c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3be1fec30b381948e1e84408642a618f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3e6afb4834057e5b5c7e593d0894a8bb +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6882b260ae69f1594eff540d803e5ac3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7eb9384654be8c4fc859b9736c0da9d0 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a2b14d5c46db32da9183354fb3fcd0bf +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a6d6196cfd275dea0718553a95f997a5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/aacfd4457155e8607cbe66d5fdaf11b3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d94883bc533251c5e4b4821c716ae300 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e76f5e84c165c22920d69c5dafce2fe1 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f4648036e284d9aa3468f4f7b9bbb967 +0 -0
- data/vendor/assets/javascripts/morris.min-0.5.js +7 -0
- data/vendor/assets/javascripts/raphael-min-2.1.2.js +11 -0
- data/vendor/assets/stylesheets/morris.css +2 -0
- metadata +56 -4
- data/vendor/assets/javascripts/highcharts.js +0 -285
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a2b4fadf928d57f33383ad55b6a989b2dfd8d22
|
4
|
+
data.tar.gz: 01781f83c18c0da2e1ea23b94c220d480f523f1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78b242530b5999fbdde7a9a1bba6b444a95d6073a143cd9f47d80be04498badcad408b5bbe64fe79d871f09be4588d007f3e7107034a7d4713336781e6a9c214
|
7
|
+
data.tar.gz: 8d0875abb61818781caa6445711a0bbb92330838185d920d89937609f26e4f1c2fd0d82ccac8dc33cbad67301dae8878d9ad8d14ca54d4c64b1e09342737ab75
|
@@ -1,67 +1,82 @@
|
|
1
|
+
class SubGraph
|
2
|
+
constructor: (options = {}) ->
|
3
|
+
@el = $('<div>', class: 'sub-graph')
|
4
|
+
if options.showTitle
|
5
|
+
@el.append("<div class='title'>Loading...</div>")
|
1
6
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
@el
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
chart:
|
11
|
-
type: 'line'
|
12
|
-
renderTo: @el
|
13
|
-
tooltip:
|
14
|
-
crosshairs: [true, true]
|
7
|
+
@el.find('.title').html(options.label)
|
8
|
+
|
9
|
+
chartEl = $('<div>', class: 'sub-graph-chart')
|
10
|
+
@el.append(chartEl)
|
11
|
+
|
12
|
+
@data = []
|
13
|
+
@chartOptions =
|
14
|
+
element: chartEl
|
15
15
|
series: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
max: Math.max.apply(Math, json.data)
|
40
|
-
|
41
|
-
|
42
|
-
if json.key == 'change'
|
43
|
-
axisSettings = $.extend axisSettings, {
|
44
|
-
min: 0,
|
45
|
-
max: Math.max.apply(Math, json.data),
|
46
|
-
labels: {formatter: -> this.value + '%' },
|
47
|
-
opposite: true
|
48
|
-
}
|
49
|
-
|
50
|
-
serie = $.extend serie, {
|
51
|
-
tooltip: {valueDecimals: 2, valueSuffix: '%'}
|
52
|
-
}
|
53
|
-
|
54
|
-
chart.yAxis[axisIndex].update(axisSettings)
|
55
|
-
chart.addSeries(serie)
|
56
|
-
|
57
|
-
$.getJSON @url, (json) ->
|
58
|
-
chart.setTitle {text: json.title}
|
16
|
+
xkey: "x"
|
17
|
+
ykeys: []
|
18
|
+
labels: []
|
19
|
+
smooth: false
|
20
|
+
data: @data
|
21
|
+
|
22
|
+
@chartOptions.postUnits = '%' if options.key == 'change'
|
23
|
+
|
24
|
+
addSeries: (json) ->
|
25
|
+
data = @data
|
26
|
+
|
27
|
+
start_time = Date.parse(json.start_time)
|
28
|
+
for point, i in json.data
|
29
|
+
time = start_time + i * json.period_milliseconds
|
30
|
+
data[i] ||= {
|
31
|
+
x: time
|
32
|
+
}
|
33
|
+
data[i][json.uid] = point
|
34
|
+
|
35
|
+
@chartOptions.ykeys.push(json.uid)
|
36
|
+
@chartOptions.labels.push(json.uid)
|
37
|
+
|
38
|
+
@el
|
59
39
|
|
40
|
+
draw: ->
|
41
|
+
# Because of a bug in Morris (https://github.com/morrisjs/morris.js/issues/388)
|
42
|
+
# it's not possible to add data on a hidden element. We just redraw the
|
43
|
+
# entire thing in the meantime.
|
44
|
+
@chart = new Morris.Line(@chartOptions)
|
45
|
+
|
46
|
+
class Graph
|
47
|
+
constructor: (options) ->
|
48
|
+
@url = options.url
|
49
|
+
@el = options.el
|
50
|
+
@$el = $(options.el)
|
51
|
+
console.log(@$el)
|
52
|
+
|
53
|
+
render: =>
|
54
|
+
$.getJSON @url, (json) =>
|
60
55
|
for extractor, index in json.extractors
|
61
|
-
|
62
|
-
|
56
|
+
$.get extractor.url, (line_json) =>
|
57
|
+
subgraph = @getSubgraph(label: line_json.label, key: line_json.key)
|
58
|
+
subgraph.addSeries(line_json)
|
59
|
+
|
60
|
+
if @$el.hasClass('dashboard')
|
61
|
+
if subgraph.chartOptions.ykeys.length == json.extractors.length
|
62
|
+
subgraph.draw()
|
63
|
+
else
|
64
|
+
subgraph.draw()
|
65
|
+
|
63
66
|
@
|
64
|
-
|
67
|
+
|
68
|
+
getSubgraph: (options) =>
|
69
|
+
create = (options) =>
|
70
|
+
subgraph = new SubGraph(options)
|
71
|
+
@$el.append(subgraph.el)
|
72
|
+
subgraph
|
73
|
+
|
74
|
+
# Render 1 subgraph if it's a dashboard graph, mulltiple otherwise.
|
75
|
+
if @$el.hasClass('dashboard')
|
76
|
+
@subGraph ||= create(options)
|
77
|
+
else
|
78
|
+
create($.extend(options, showTitle: true))
|
79
|
+
|
65
80
|
@Prosperity ||= {}
|
66
81
|
@Prosperity.Graph = Graph
|
67
82
|
|
@@ -11,11 +11,11 @@ module Prosperity
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def show
|
14
|
-
|
14
|
+
dashboard
|
15
15
|
end
|
16
16
|
|
17
17
|
def edit
|
18
|
-
|
18
|
+
dashboard
|
19
19
|
end
|
20
20
|
|
21
21
|
def create
|
@@ -23,11 +23,22 @@ module Prosperity
|
|
23
23
|
@dashboard.title = params.fetch(:dashboard, {})[:title]
|
24
24
|
@dashboard.default = false
|
25
25
|
if @dashboard.save
|
26
|
-
redirect_to
|
26
|
+
redirect_to edit_dashboard_path(@dashboard)
|
27
27
|
else
|
28
28
|
flash[:error] = @dashboard.errors.full_messages.to_sentence
|
29
29
|
render action: :new
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
def destroy
|
34
|
+
dashboard.destroy
|
35
|
+
redirect_to action: 'index'
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def dashboard
|
41
|
+
@dashboard ||= Dashboard.find(params[:id])
|
42
|
+
end
|
32
43
|
end
|
33
44
|
end
|
@@ -36,7 +36,11 @@ module Prosperity
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def data
|
39
|
-
|
39
|
+
ext_name = params.fetch(:extractor, "interval")
|
40
|
+
ext_klass = Metric.extractors.fetch(ext_name) do
|
41
|
+
render_json_error "Could not find extractor #{ext_name} for #{@metric}. Possible values are #{Metric.extractors.keys.join(", ")}.", 404
|
42
|
+
return
|
43
|
+
end
|
40
44
|
|
41
45
|
p = Prosperity::Periods::ALL.fetch(period)
|
42
46
|
ext = ext_klass.new(@metric, option, start_time, end_time, p)
|
@@ -44,6 +48,7 @@ module Prosperity
|
|
44
48
|
json = {
|
45
49
|
data: ext.to_a,
|
46
50
|
key: ext.key,
|
51
|
+
uid: ext.uid,
|
47
52
|
label: ext.label,
|
48
53
|
start_time: p.actual_start_time(start_time).iso8601,
|
49
54
|
end_time: p.actual_end_time(end_time).iso8601,
|
@@ -7,5 +7,17 @@ module Prosperity
|
|
7
7
|
def link_to_metric(metric)
|
8
8
|
link_to metric.new.title, metric_path(id: metric.name)
|
9
9
|
end
|
10
|
+
|
11
|
+
def navbar_item(name, url, *controllers)
|
12
|
+
classes = []
|
13
|
+
|
14
|
+
if controllers.any?{ |c| controller.is_a?(c) }
|
15
|
+
classes << 'active'
|
16
|
+
end
|
17
|
+
|
18
|
+
content_tag(:li, class: classes) do
|
19
|
+
link_to name, url
|
20
|
+
end
|
21
|
+
end
|
10
22
|
end
|
11
23
|
end
|
@@ -27,12 +27,8 @@
|
|
27
27
|
</div>
|
28
28
|
<div class="collapse navbar-collapse">
|
29
29
|
<ul class="nav navbar-nav">
|
30
|
-
|
31
|
-
|
32
|
-
</li>
|
33
|
-
<li>
|
34
|
-
<a href="<%= metrics_path %>">All Metrics</a>
|
35
|
-
</li>
|
30
|
+
<%= navbar_item 'Dashboards', dashboards_path, Prosperity::DashboardsController, Prosperity::GraphsController %>
|
31
|
+
<%= navbar_item 'Browse Metrics', metrics_path, Prosperity::MetricsController %>
|
36
32
|
</ul>
|
37
33
|
</div>
|
38
34
|
</div>
|
@@ -1,15 +1,29 @@
|
|
1
1
|
<h1>Dashboards</h1>
|
2
2
|
|
3
3
|
<p>
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
<% if @dashboards.present? %>
|
5
|
+
<table class="table">
|
6
|
+
<thead>
|
7
|
+
<tr>
|
8
|
+
<th>Dashboard</th>
|
9
|
+
<th></th>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
<tbody>
|
13
|
+
<% for dashboard in @dashboards %>
|
14
|
+
<tr>
|
15
|
+
<td> <%= link_to dashboard.title, dashboard_path(dashboard) %> </td>
|
16
|
+
<td>
|
17
|
+
<%= link_to 'Edit', edit_dashboard_path(dashboard), class: 'btn btn-primary' %>
|
18
|
+
<%= link_to 'Delete', dashboard_path(dashboard), method: 'delete', class: 'btn btn-danger' %>
|
19
|
+
</td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</body>
|
23
|
+
</table>
|
24
|
+
<% else %>
|
25
|
+
You currently don't have any dashboard. Click the button bellow to create your first!
|
26
|
+
<% end %>
|
13
27
|
</p>
|
14
28
|
|
15
29
|
<a href="<%= new_dashboard_path %>" class="btn btn-primary">New Dashboard</a>
|
@@ -5,10 +5,14 @@
|
|
5
5
|
<%= submit_tag "Update", class: 'btn btn-primary' %>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
+
<% if @dashboard.graphs.empty? %>
|
9
|
+
<p>No Graphs</p>
|
10
|
+
<% end %>
|
11
|
+
|
8
12
|
<% @dashboard.graphs.each do |graph| %>
|
9
|
-
<div class="graph">
|
13
|
+
<div class="graph dashboard-graph">
|
10
14
|
<h2><%= graph.title %></h2>
|
11
15
|
|
12
|
-
<div class="metric" data-url="<%= graph_path(graph, start_time: start_time) %>"></div>
|
16
|
+
<div class="metric dashboard" data-url="<%= graph_path(graph, start_time: start_time) %>"></div>
|
13
17
|
</div>
|
14
18
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Prosperity
|
2
|
-
class Extractors::Base
|
2
|
+
class Extractors::Base
|
3
3
|
attr_reader :metric, :start_time, :end_time, :period, :option
|
4
4
|
|
5
5
|
def initialize(metric, option, start_time, end_time, period)
|
@@ -15,6 +15,10 @@ module Prosperity
|
|
15
15
|
self.class.key
|
16
16
|
end
|
17
17
|
|
18
|
+
def uid
|
19
|
+
"#{@metric.to_s.underscore}_#{@option}_#{key}"
|
20
|
+
end
|
21
|
+
|
18
22
|
def label
|
19
23
|
"#{metric.title} by #{key} with option #{option}"
|
20
24
|
end
|
data/lib/prosperity/metric.rb
CHANGED
data/lib/prosperity/version.rb
CHANGED
@@ -41,7 +41,9 @@ module Prosperity
|
|
41
41
|
expect do
|
42
42
|
post 'create', dashboard: {title: 'test'}
|
43
43
|
end.to change(Dashboard, :count).by(1)
|
44
|
-
|
44
|
+
dashboard = assigns(:dashboard)
|
45
|
+
dashboard.should be_a(Dashboard)
|
46
|
+
response.should redirect_to(edit_dashboard_path(dashboard))
|
45
47
|
end
|
46
48
|
|
47
49
|
it "should handle validation error" do
|
@@ -50,5 +52,14 @@ module Prosperity
|
|
50
52
|
flash[:error].should be_present
|
51
53
|
end
|
52
54
|
end
|
55
|
+
|
56
|
+
describe "DELETE 'destroy'" do
|
57
|
+
it "deleted the dashboard" do
|
58
|
+
delete 'destroy', id: dashboard.id
|
59
|
+
response.should redirect_to(dashboards_path)
|
60
|
+
|
61
|
+
Dashboard.find_by(id: dashboard.id).should be_nil
|
62
|
+
end
|
63
|
+
end
|
53
64
|
end
|
54
65
|
end
|
@@ -95,6 +95,12 @@ module Prosperity
|
|
95
95
|
response.code.to_i.should == 404
|
96
96
|
json['error'].should be_present
|
97
97
|
end
|
98
|
+
|
99
|
+
it "returns 404 for a known metric, but unknowd extractor" do
|
100
|
+
get :data, id: metric.id, extractor: 'does-not-exist', format: 'json'
|
101
|
+
response.code.to_i.should == 404
|
102
|
+
json['error'].should be_present
|
103
|
+
end
|
98
104
|
end
|
99
105
|
end
|
100
106
|
end
|