pulse-meter 0.0.1
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/.gitignore +19 -0
- data/.rbenv-version +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/Procfile +3 -0
- data/README.md +440 -0
- data/Rakefile +53 -0
- data/bin/pulse +6 -0
- data/examples/basic.ru +109 -0
- data/examples/basic_sensor_data.rb +38 -0
- data/examples/full/Procfile +2 -0
- data/examples/full/client.rb +82 -0
- data/examples/full/server.ru +114 -0
- data/examples/minimal/Procfile +2 -0
- data/examples/minimal/client.rb +16 -0
- data/examples/minimal/server.ru +20 -0
- data/examples/readme_client_example.rb +52 -0
- data/lib/cmd.rb +150 -0
- data/lib/pulse-meter.rb +17 -0
- data/lib/pulse-meter/mixins/dumper.rb +72 -0
- data/lib/pulse-meter/mixins/utils.rb +91 -0
- data/lib/pulse-meter/sensor.rb +44 -0
- data/lib/pulse-meter/sensor/base.rb +75 -0
- data/lib/pulse-meter/sensor/counter.rb +36 -0
- data/lib/pulse-meter/sensor/hashed_counter.rb +31 -0
- data/lib/pulse-meter/sensor/indicator.rb +33 -0
- data/lib/pulse-meter/sensor/timeline.rb +180 -0
- data/lib/pulse-meter/sensor/timelined/average.rb +26 -0
- data/lib/pulse-meter/sensor/timelined/counter.rb +16 -0
- data/lib/pulse-meter/sensor/timelined/hashed_counter.rb +22 -0
- data/lib/pulse-meter/sensor/timelined/max.rb +25 -0
- data/lib/pulse-meter/sensor/timelined/median.rb +14 -0
- data/lib/pulse-meter/sensor/timelined/min.rb +25 -0
- data/lib/pulse-meter/sensor/timelined/percentile.rb +31 -0
- data/lib/pulse-meter/version.rb +3 -0
- data/lib/pulse-meter/visualize/app.rb +43 -0
- data/lib/pulse-meter/visualize/dsl.rb +0 -0
- data/lib/pulse-meter/visualize/dsl/errors.rb +46 -0
- data/lib/pulse-meter/visualize/dsl/layout.rb +55 -0
- data/lib/pulse-meter/visualize/dsl/page.rb +50 -0
- data/lib/pulse-meter/visualize/dsl/sensor.rb +21 -0
- data/lib/pulse-meter/visualize/dsl/widget.rb +84 -0
- data/lib/pulse-meter/visualize/layout.rb +54 -0
- data/lib/pulse-meter/visualize/page.rb +30 -0
- data/lib/pulse-meter/visualize/public/css/application.css +19 -0
- data/lib/pulse-meter/visualize/public/css/bootstrap.css +4883 -0
- data/lib/pulse-meter/visualize/public/css/bootstrap.min.css +729 -0
- data/lib/pulse-meter/visualize/public/favicon.ico +0 -0
- data/lib/pulse-meter/visualize/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/pulse-meter/visualize/public/img/glyphicons-halflings.png +0 -0
- data/lib/pulse-meter/visualize/public/js/application.coffee +262 -0
- data/lib/pulse-meter/visualize/public/js/application.js +279 -0
- data/lib/pulse-meter/visualize/public/js/backbone-min.js +38 -0
- data/lib/pulse-meter/visualize/public/js/bootstrap.js +1835 -0
- data/lib/pulse-meter/visualize/public/js/highcharts.js +203 -0
- data/lib/pulse-meter/visualize/public/js/jquery-1.7.2.min.js +4 -0
- data/lib/pulse-meter/visualize/public/js/json2.js +487 -0
- data/lib/pulse-meter/visualize/public/js/underscore-min.js +32 -0
- data/lib/pulse-meter/visualize/sensor.rb +60 -0
- data/lib/pulse-meter/visualize/views/main.haml +40 -0
- data/lib/pulse-meter/visualize/widget.rb +68 -0
- data/lib/pulse-meter/visualizer.rb +30 -0
- data/lib/test_helpers/matchers.rb +36 -0
- data/pulse-meter.gemspec +39 -0
- data/spec/pulse_meter/mixins/dumper_spec.rb +158 -0
- data/spec/pulse_meter/mixins/utils_spec.rb +134 -0
- data/spec/pulse_meter/sensor/base_spec.rb +97 -0
- data/spec/pulse_meter/sensor/counter_spec.rb +54 -0
- data/spec/pulse_meter/sensor/hashed_counter_spec.rb +39 -0
- data/spec/pulse_meter/sensor/indicator_spec.rb +43 -0
- data/spec/pulse_meter/sensor/timeline_spec.rb +58 -0
- data/spec/pulse_meter/sensor/timelined/average_spec.rb +6 -0
- data/spec/pulse_meter/sensor/timelined/counter_spec.rb +6 -0
- data/spec/pulse_meter/sensor/timelined/hashed_counter_spec.rb +8 -0
- data/spec/pulse_meter/sensor/timelined/max_spec.rb +7 -0
- data/spec/pulse_meter/sensor/timelined/median_spec.rb +7 -0
- data/spec/pulse_meter/sensor/timelined/min_spec.rb +7 -0
- data/spec/pulse_meter/sensor/timelined/percentile_spec.rb +17 -0
- data/spec/pulse_meter/visualize/app_spec.rb +27 -0
- data/spec/pulse_meter/visualize/dsl/layout_spec.rb +64 -0
- data/spec/pulse_meter/visualize/dsl/page_spec.rb +75 -0
- data/spec/pulse_meter/visualize/dsl/sensor_spec.rb +30 -0
- data/spec/pulse_meter/visualize/dsl/widget_spec.rb +127 -0
- data/spec/pulse_meter/visualize/layout_spec.rb +55 -0
- data/spec/pulse_meter/visualize/page_spec.rb +150 -0
- data/spec/pulse_meter/visualize/sensor_spec.rb +120 -0
- data/spec/pulse_meter/visualize/widget_spec.rb +113 -0
- data/spec/pulse_meter/visualizer_spec.rb +42 -0
- data/spec/pulse_meter_spec.rb +16 -0
- data/spec/shared_examples/timeline_sensor.rb +279 -0
- data/spec/shared_examples/timelined_subclass.rb +23 -0
- data/spec/spec_helper.rb +29 -0
- metadata +435 -0
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require "yard"
|
5
|
+
require 'yard/rake/yardoc_task'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
YARD::Rake::YardocTask.new(:yard)
|
10
|
+
|
11
|
+
ROOT = File.dirname(__FILE__)
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
namespace :coffee do
|
16
|
+
desc "Complile coffee to js"
|
17
|
+
task :compile do
|
18
|
+
system 'coffee', '-c', "#{ROOT}/lib/pulse-meter/visualize/public/"
|
19
|
+
puts "Done"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Watch coffee files and recomplile them immediately"
|
23
|
+
task :watch do
|
24
|
+
system 'coffee', '--watch', '-c', "#{ROOT}/lib/pulse-meter/visualize/public/"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
namespace :yard do
|
30
|
+
desc "Open doc index in a browser"
|
31
|
+
task :open do
|
32
|
+
system 'open', "#{ROOT}/doc/index.html"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
namespace :example do
|
37
|
+
desc "Run minimal example"
|
38
|
+
task :minimal do
|
39
|
+
chdir(ROOT) do
|
40
|
+
system "bundle"
|
41
|
+
system "cd examples/minimal && bundle exec foreman start"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Run full example"
|
46
|
+
task :full do
|
47
|
+
chdir(ROOT) do
|
48
|
+
system "bundle"
|
49
|
+
system "cd examples/full && bundle exec foreman start"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/bin/pulse
ADDED
data/examples/basic.ru
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require 'pulse-meter/visualizer'
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
layout = PulseMeter::Visualizer.draw do |l|
|
8
|
+
|
9
|
+
l.title "WunderZoo Stats"
|
10
|
+
|
11
|
+
l.page "Counts" do |p|
|
12
|
+
|
13
|
+
p.spline "Lama count", sensor: :lama_count do |c|
|
14
|
+
c.redraw_interval 5
|
15
|
+
c.values_label 'Count'
|
16
|
+
c.width 5
|
17
|
+
c.show_last_point true
|
18
|
+
c.timespan 1200
|
19
|
+
end
|
20
|
+
|
21
|
+
p.area "Rhino count", sensor: :rhino_count do |c|
|
22
|
+
c.redraw_interval 5
|
23
|
+
c.values_label 'Count'
|
24
|
+
c.width 5
|
25
|
+
c.show_last_point true
|
26
|
+
c.timespan 1200
|
27
|
+
end
|
28
|
+
|
29
|
+
p.spline "Rhino & Lama count comparison" do |c|
|
30
|
+
c.redraw_interval 5
|
31
|
+
c.values_label 'Count'
|
32
|
+
c.width 5
|
33
|
+
c.show_last_point true
|
34
|
+
c.timespan 1200
|
35
|
+
|
36
|
+
c.sensor :rhino_count, color: '#AAAAAA'
|
37
|
+
c.sensor :lama_count, color: '#CC1155'
|
38
|
+
end
|
39
|
+
|
40
|
+
p.pie "Rhino & Lama count comparison" do |c|
|
41
|
+
c.redraw_interval 5
|
42
|
+
c.values_label 'Count'
|
43
|
+
c.width 5
|
44
|
+
c.show_last_point false
|
45
|
+
c.timespan 1200
|
46
|
+
|
47
|
+
c.sensor :rhino_count, color: '#AAAAAA'
|
48
|
+
c.sensor :lama_count, color: '#CC1155'
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
l.page "Ages" do |p|
|
54
|
+
|
55
|
+
p.line "Lama average age", sensor: :lama_average_age do |c|
|
56
|
+
c.redraw_interval 5
|
57
|
+
c.values_label 'Age'
|
58
|
+
c.width 5
|
59
|
+
c.show_last_point true
|
60
|
+
c.timespan 1200
|
61
|
+
end
|
62
|
+
|
63
|
+
p.line "Rhino average age", sensor: :rhino_average_age do |c|
|
64
|
+
c.redraw_interval 5
|
65
|
+
c.values_label 'Age'
|
66
|
+
c.width 5
|
67
|
+
c.show_last_point true
|
68
|
+
c.timespan 1200
|
69
|
+
end
|
70
|
+
|
71
|
+
p.area "Rhino & Lama average age comparison" do |c|
|
72
|
+
c.redraw_interval 5
|
73
|
+
c.values_label 'Age'
|
74
|
+
c.width 5
|
75
|
+
c.show_last_point true
|
76
|
+
c.timespan 1200
|
77
|
+
|
78
|
+
c.sensor :lama_average_age
|
79
|
+
c.sensor :rhino_average_age
|
80
|
+
end
|
81
|
+
|
82
|
+
p.pie "Rhino & Lama average age comparison" do |c|
|
83
|
+
c.redraw_interval 5
|
84
|
+
c.values_label 'Age'
|
85
|
+
c.width 5
|
86
|
+
c.show_last_point false
|
87
|
+
c.timespan 1200
|
88
|
+
|
89
|
+
c.sensor :lama_average_age
|
90
|
+
c.sensor :rhino_average_age
|
91
|
+
end
|
92
|
+
|
93
|
+
p.highchart_options({
|
94
|
+
chart: {
|
95
|
+
height: 300
|
96
|
+
}
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
l.use_utc false
|
101
|
+
l.outlier_color '#FF0000'
|
102
|
+
l.highchart_options({
|
103
|
+
tooltip: {
|
104
|
+
value_decimals: 2
|
105
|
+
}
|
106
|
+
})
|
107
|
+
end
|
108
|
+
|
109
|
+
run layout.to_app
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require "pulse-meter"
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
lama_counter = PulseMeter::Sensor::Timelined::Counter.new(:lama_count,
|
8
|
+
annotation: 'Lama Count',
|
9
|
+
interval: 10,
|
10
|
+
ttl: 3600
|
11
|
+
)
|
12
|
+
|
13
|
+
lama_average_age = PulseMeter::Sensor::Timelined::Average.new(:lama_average_age,
|
14
|
+
annotation: 'Lama Average Age',
|
15
|
+
interval: 20,
|
16
|
+
ttl: 3600
|
17
|
+
)
|
18
|
+
|
19
|
+
rhino_counter = PulseMeter::Sensor::Timelined::Counter.new(:rhino_count,
|
20
|
+
annotation: 'Rhino Count',
|
21
|
+
interval: 10,
|
22
|
+
ttl: 3600
|
23
|
+
)
|
24
|
+
|
25
|
+
rhino_average_age = PulseMeter::Sensor::Timelined::Average.new(:rhino_average_age,
|
26
|
+
annotation: 'Rhino average age',
|
27
|
+
interval: 20,
|
28
|
+
ttl: 3600
|
29
|
+
)
|
30
|
+
|
31
|
+
while true
|
32
|
+
sleep(Random.rand)
|
33
|
+
STDERR.puts "tick"
|
34
|
+
lama_counter.event(1)
|
35
|
+
rhino_counter.event(2)
|
36
|
+
lama_average_age.event(Random.rand(50))
|
37
|
+
rhino_average_age.event(Random.rand(100))
|
38
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', '..', 'lib')
|
2
|
+
|
3
|
+
require "pulse-meter"
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
requests_per_minute = PulseMeter::Sensor::Timelined::Counter.new(:requests_per_minute,
|
8
|
+
:annotation => 'Requests per minute',
|
9
|
+
:interval => 60,
|
10
|
+
:ttl => 60 * 60 * 24 # keep data one day
|
11
|
+
)
|
12
|
+
|
13
|
+
requests_per_hour = PulseMeter::Sensor::Timelined::Counter.new(:requests_per_hour,
|
14
|
+
:annotation => 'Requests per hour',
|
15
|
+
:interval => 60 * 60,
|
16
|
+
:ttl => 60 * 60 * 24 * 30 # keep data 30 days
|
17
|
+
# when ActiveSupport extentions are loaded, a better way is to write just
|
18
|
+
# :interval => 1.hour,
|
19
|
+
# :ttl => 30.days
|
20
|
+
)
|
21
|
+
|
22
|
+
errors_per_minute = PulseMeter::Sensor::Timelined::Counter.new(:errors_per_minute,
|
23
|
+
:annotation => 'Errors per minute',
|
24
|
+
:interval => 60,
|
25
|
+
:ttl => 60 * 60 * 24
|
26
|
+
)
|
27
|
+
|
28
|
+
errors_per_hour = PulseMeter::Sensor::Timelined::Counter.new(:errors_per_hour,
|
29
|
+
:annotation => 'Errors per hour',
|
30
|
+
:interval => 60 * 60,
|
31
|
+
:ttl => 60 * 60 * 24 * 30
|
32
|
+
)
|
33
|
+
|
34
|
+
longest_minute_request = PulseMeter::Sensor::Timelined::Max.new(:longest_minute_request,
|
35
|
+
:annotation => 'Longest minute requests',
|
36
|
+
:interval => 60,
|
37
|
+
:ttl => 60 * 60 * 24
|
38
|
+
)
|
39
|
+
|
40
|
+
shortest_minute_request = PulseMeter::Sensor::Timelined::Min.new(:shortest_minute_request,
|
41
|
+
:annotation => 'Shortest minute requests',
|
42
|
+
:interval => 60,
|
43
|
+
:ttl => 60 * 60 * 24
|
44
|
+
)
|
45
|
+
|
46
|
+
perc90_minute_request = PulseMeter::Sensor::Timelined::Percentile.new(:perc90_minute_request,
|
47
|
+
:annotation => 'Minute request 90-percent percentile',
|
48
|
+
:interval => 60,
|
49
|
+
:ttl => 60 * 60 * 24,
|
50
|
+
:p => 0.9
|
51
|
+
)
|
52
|
+
|
53
|
+
agent_names = [:ie, :firefox, :chrome, :other]
|
54
|
+
hour_agents = agent_names.each_with_object({}) do |agent, h|
|
55
|
+
h[agent] = PulseMeter::Sensor::Timelined::Counter.new(agent,
|
56
|
+
:annotation => "Requests from #{agent} browser",
|
57
|
+
:interval => 60 * 60,
|
58
|
+
:ttl => 60 * 60 * 24 * 30
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
while true
|
64
|
+
requests_per_minute.event(1)
|
65
|
+
requests_per_hour.event(1)
|
66
|
+
|
67
|
+
if Random.rand(10) < 1 # let "errors" sometimes occur
|
68
|
+
errors_per_minute.event(1)
|
69
|
+
errors_per_hour.event(1)
|
70
|
+
end
|
71
|
+
|
72
|
+
request_time = 0.1 + Random.rand
|
73
|
+
|
74
|
+
longest_minute_request.event(request_time)
|
75
|
+
shortest_minute_request.event(request_time)
|
76
|
+
perc90_minute_request.event(request_time)
|
77
|
+
|
78
|
+
agent_counter = hour_agents[agent_names.shuffle.first]
|
79
|
+
agent_counter.event(1)
|
80
|
+
|
81
|
+
sleep(Random.rand / 10)
|
82
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require "pulse-meter/visualizer"
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
layout = PulseMeter::Visualizer.draw do |l|
|
8
|
+
|
9
|
+
# Application title
|
10
|
+
l.title "Full Example"
|
11
|
+
|
12
|
+
# Use local time for x-axis of charts
|
13
|
+
l.use_utc false
|
14
|
+
|
15
|
+
# Color for values cut off
|
16
|
+
l.outlier_color '#FF0000'
|
17
|
+
|
18
|
+
# Transfer some global parameters to Highcharts
|
19
|
+
l.highchart_options({
|
20
|
+
tooltip: {
|
21
|
+
value_decimals: 2
|
22
|
+
}
|
23
|
+
})
|
24
|
+
|
25
|
+
# Add some pages
|
26
|
+
l.page "Request count" do |p|
|
27
|
+
|
28
|
+
# Add chart (of Highcharts `area' style, `spline', `pie' and `line' are also available)
|
29
|
+
p.area "Requests per minute" do |w|
|
30
|
+
|
31
|
+
# Plot :requests_per_minute values on this chart with black color
|
32
|
+
w.sensor :requests_per_minute, color: '#000000'
|
33
|
+
|
34
|
+
# Plot :errors_per_minute values on this chart with red color
|
35
|
+
w.sensor :errors_per_minute, color: '#FF0000'
|
36
|
+
|
37
|
+
# Plot values for the last hour
|
38
|
+
w.timespan 60 * 60
|
39
|
+
|
40
|
+
# Redraw chart every 10 seconds
|
41
|
+
w.redraw_interval 10
|
42
|
+
|
43
|
+
# Plot incomplete data
|
44
|
+
w.show_last_point true
|
45
|
+
|
46
|
+
# Meaning of the y-axis
|
47
|
+
w.values_label "Request count"
|
48
|
+
|
49
|
+
# Occupy half (5/10) of the page (horizontally)
|
50
|
+
w.width 5
|
51
|
+
|
52
|
+
# Transfer page-wide (and page-specific) options to Highcharts
|
53
|
+
p.highchart_options({
|
54
|
+
chart: {
|
55
|
+
height: 300
|
56
|
+
}
|
57
|
+
})
|
58
|
+
end
|
59
|
+
|
60
|
+
p.area "Requests per hour" do |w|
|
61
|
+
|
62
|
+
w.sensor :requests_per_hour, color: '#555555'
|
63
|
+
w.sensor :errors_per_hour, color: '#FF0000'
|
64
|
+
|
65
|
+
w.timespan 24 * 60 * 60
|
66
|
+
w.redraw_interval 10
|
67
|
+
w.show_last_point true
|
68
|
+
w.values_label "Request count"
|
69
|
+
w.width 5
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
l.page "Request times" do |p|
|
75
|
+
p.area "Requests time" do |w|
|
76
|
+
|
77
|
+
w.sensor :longest_minute_request
|
78
|
+
w.sensor :shortest_minute_request
|
79
|
+
w.sensor :perc90_minute_request
|
80
|
+
|
81
|
+
w.timespan 60 * 60
|
82
|
+
w.redraw_interval 10
|
83
|
+
w.show_last_point true
|
84
|
+
w.values_label "Time in seconds"
|
85
|
+
w.width 10
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
l.page "Browsers" do |p|
|
91
|
+
p.pie "Requests from browser" do |w|
|
92
|
+
|
93
|
+
[:ie, :firefox, :chrome, :other].each do |sensor|
|
94
|
+
w.sensor sensor
|
95
|
+
end
|
96
|
+
|
97
|
+
w.timespan 24 * 60 * 60
|
98
|
+
w.redraw_interval 10
|
99
|
+
w.show_last_point true
|
100
|
+
w.values_label "Request count"
|
101
|
+
w.width 10
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
p.highchart_options({
|
106
|
+
chart: {
|
107
|
+
height: 500
|
108
|
+
}
|
109
|
+
})
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
run layout.to_app
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', '..', 'lib')
|
2
|
+
|
3
|
+
require "pulse-meter"
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
sensor = PulseMeter::Sensor::Timelined::Counter.new(:simple_sample_counter,
|
8
|
+
:interval => 5,
|
9
|
+
:ttl => 60 * 60
|
10
|
+
)
|
11
|
+
|
12
|
+
while true
|
13
|
+
STDERR.puts "tick"
|
14
|
+
sensor.event(1)
|
15
|
+
sleep(Random.rand)
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
$: << File.join(File.absolute_path(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require "pulse-meter/visualizer"
|
4
|
+
|
5
|
+
PulseMeter.redis = Redis.new
|
6
|
+
|
7
|
+
layout = PulseMeter::Visualizer.draw do |l|
|
8
|
+
|
9
|
+
l.title "Minimal App"
|
10
|
+
|
11
|
+
l.page "Main Page" do |p|
|
12
|
+
p.area "Live Counter",
|
13
|
+
sensor: :simple_sample_counter,
|
14
|
+
timespan: 5 * 60,
|
15
|
+
redraw_interval: 1
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
run layout.to_app
|