pulse-meter 0.4.8 → 0.4.9
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/README.md +371 -353
- data/examples/full/client.rb +3 -2
- data/lib/pulse-meter.rb +1 -0
- data/lib/pulse-meter/command_aggregator/async.rb +1 -0
- data/lib/pulse-meter/mixins/utils.rb +13 -0
- data/lib/pulse-meter/observer.rb +18 -14
- data/lib/pulse-meter/observer/extended.rb +34 -0
- data/lib/pulse-meter/version.rb +1 -1
- data/lib/pulse-meter/visualize/public/css/application.css +6 -1
- data/lib/pulse-meter/visualize/views/main.haml +7 -10
- data/lib/pulse-meter/visualize/views/sensors.haml +5 -8
- data/lib/pulse-meter/visualize/views/widgets/area.haml +1 -1
- data/lib/pulse-meter/visualize/views/widgets/line.haml +1 -1
- data/lib/pulse-meter/visualize/views/widgets/table.haml +1 -1
- data/spec/pulse_meter/mixins/utils_spec.rb +8 -0
- data/spec/pulse_meter/observer/extended_spec.rb +92 -0
- data/spec/pulse_meter/observer_spec.rb +0 -45
- data/spec/support/observered.rb +40 -0
- metadata +7 -2
data/examples/full/client.rb
CHANGED
@@ -100,8 +100,9 @@ while true
|
|
100
100
|
sensors.shortest_minute_request(request_time)
|
101
101
|
sensors.perc90_minute_request(request_time)
|
102
102
|
|
103
|
-
|
104
|
-
|
103
|
+
sensors.sensor(agent_names.shuffle.first) do |s|
|
104
|
+
s.event(1)
|
105
|
+
end
|
105
106
|
|
106
107
|
sensors.cpu(Random.rand(100))
|
107
108
|
|
data/lib/pulse-meter.rb
CHANGED
@@ -88,6 +88,19 @@ module PulseMeter
|
|
88
88
|
(first_letter_upper ? first.capitalize : first.downcase) + terms.map(&:capitalize).join
|
89
89
|
end
|
90
90
|
|
91
|
+
# Converts string from CamelCase to snake_case
|
92
|
+
# @param str [String] string to be underscore
|
93
|
+
# @return [String]
|
94
|
+
# @raise [ArgumentError] unless passed value responds to to_s
|
95
|
+
def underscore(str)
|
96
|
+
raise ArgumentError unless str.respond_to?(:to_s)
|
97
|
+
str.to_s.gsub(/::/, '/').
|
98
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
99
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
100
|
+
tr("-", "_").
|
101
|
+
downcase
|
102
|
+
end
|
103
|
+
|
91
104
|
# Converts string of the form YYYYmmddHHMMSS (considered as UTC) to Time
|
92
105
|
# @param str [String] string to be converted
|
93
106
|
# @return [Time]
|
data/lib/pulse-meter/observer.rb
CHANGED
@@ -2,6 +2,8 @@ require 'pulse-meter'
|
|
2
2
|
|
3
3
|
module PulseMeter
|
4
4
|
class Observer
|
5
|
+
extend PulseMeter::Mixins::Utils
|
6
|
+
|
5
7
|
class << self
|
6
8
|
# Removes observation from instance method
|
7
9
|
# @param klass [Class] class
|
@@ -53,19 +55,8 @@ module PulseMeter
|
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
56
|
-
|
58
|
+
protected
|
57
59
|
|
58
|
-
def unchain_block(method)
|
59
|
-
with_observer = method_with_observer(method)
|
60
|
-
without_observer = method_without_observer(method)
|
61
|
-
|
62
|
-
Proc.new do
|
63
|
-
alias_method(method, without_observer)
|
64
|
-
remove_method(with_observer)
|
65
|
-
remove_method(without_observer)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
60
|
def define_instrumented_method(method_owner, method, receiver, &handler)
|
70
61
|
with_observer = method_with_observer(method)
|
71
62
|
without_observer = method_without_observer(method)
|
@@ -83,6 +74,19 @@ module PulseMeter
|
|
83
74
|
end
|
84
75
|
end
|
85
76
|
|
77
|
+
private
|
78
|
+
|
79
|
+
def unchain_block(method)
|
80
|
+
with_observer = method_with_observer(method)
|
81
|
+
without_observer = method_without_observer(method)
|
82
|
+
|
83
|
+
Proc.new do
|
84
|
+
alias_method(method, without_observer)
|
85
|
+
remove_method(with_observer)
|
86
|
+
remove_method(without_observer)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
86
90
|
def chain_block(method, receiver, &handler)
|
87
91
|
with_observer = method_with_observer(method)
|
88
92
|
without_observer = method_without_observer(method)
|
@@ -105,11 +109,11 @@ module PulseMeter
|
|
105
109
|
end
|
106
110
|
|
107
111
|
def method_with_observer(method)
|
108
|
-
"#{method}
|
112
|
+
"#{method}_with_#{underscore(self).tr('/', '_')}"
|
109
113
|
end
|
110
114
|
|
111
115
|
def method_without_observer(method)
|
112
|
-
"#{method}
|
116
|
+
"#{method}_without_#{underscore(self).tr('/', '_')}"
|
113
117
|
end
|
114
118
|
end
|
115
119
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pulse-meter'
|
2
|
+
|
3
|
+
module PulseMeter
|
4
|
+
class Observer::Extended < ::PulseMeter::Observer
|
5
|
+
class << self
|
6
|
+
protected
|
7
|
+
|
8
|
+
def define_instrumented_method(method_owner, method, receiver, &handler)
|
9
|
+
with_observer = method_with_observer(method)
|
10
|
+
without_observer = method_without_observer(method)
|
11
|
+
method_owner.send(:define_method, with_observer) do |*args, &block|
|
12
|
+
start_time = Time.now
|
13
|
+
begin
|
14
|
+
result = self.send(without_observer, *args, &block)
|
15
|
+
ensure
|
16
|
+
begin
|
17
|
+
delta = ((Time.now - start_time) * 1000).to_i
|
18
|
+
observe_parameters = {
|
19
|
+
self: self,
|
20
|
+
delta: delta,
|
21
|
+
result: result,
|
22
|
+
args: args,
|
23
|
+
exception: $!
|
24
|
+
}
|
25
|
+
receiver.instance_exec(observe_parameters, &handler)
|
26
|
+
rescue StandardError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/pulse-meter/version.rb
CHANGED
@@ -20,14 +20,11 @@
|
|
20
20
|
= partial "widgets/#{wtype}"
|
21
21
|
= partial "sensors"
|
22
22
|
|
23
|
-
.
|
24
|
-
.
|
25
|
-
.
|
26
|
-
.
|
27
|
-
|
28
|
-
.container
|
29
|
-
%a{href: '#/custom'}
|
30
|
-
%span.brand= @title
|
31
|
-
%ul.nav#page-titles
|
32
|
-
#widgets.row
|
23
|
+
.navbar.navbar-fixed-top
|
24
|
+
.navbar-inner
|
25
|
+
.container-fluid
|
26
|
+
%a.brand{href: '#/custom'}= @title
|
27
|
+
%ul.nav#page-titles
|
33
28
|
|
29
|
+
.container-fluid#main
|
30
|
+
.row-fluid#widgets
|
@@ -33,7 +33,7 @@
|
|
33
33
|
Refresh chart
|
34
34
|
.form-inline
|
35
35
|
Timespan:
|
36
|
-
%select#extend-timespan-val.btn-mini.
|
36
|
+
%select#extend-timespan-val.btn-mini.span3
|
37
37
|
= partial "widgets/extend_options"
|
38
38
|
%button#extend-timespan.btn.btn-mini
|
39
39
|
%i.icon-arrow-left
|
@@ -56,10 +56,7 @@
|
|
56
56
|
|
57
57
|
|
58
58
|
%script#dynamic-widget{type: 'text/template'}
|
59
|
-
.
|
60
|
-
#dynamic-plotarea
|
61
|
-
#errors
|
62
|
-
.span10
|
59
|
+
.span6
|
63
60
|
#sensor-controls.form-horizontal
|
64
61
|
%p.form-inline
|
65
62
|
Chart type
|
@@ -74,6 +71,6 @@
|
|
74
71
|
%i.icon-refresh
|
75
72
|
Refresh sensor list
|
76
73
|
#sensor-list-area
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
.span6
|
75
|
+
#dynamic-plotarea
|
76
|
+
#errors
|
@@ -156,6 +156,14 @@ describe PulseMeter::Mixins::Utils do
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
+
describe "#underscore" do
|
160
|
+
it "should underscore string" do
|
161
|
+
dummy.underscore("aaBbCc").should == "aa_bb_cc"
|
162
|
+
dummy.underscore("AaBbCc").should == "aa_bb_cc"
|
163
|
+
dummy.underscore("aaBb::Cc").should == "aa_bb/cc"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
159
167
|
describe "#camelize_keys" do
|
160
168
|
it "should deeply camelize keys in hashes" do
|
161
169
|
dummy.camelize_keys({ :aa_bb_cc => [ { :dd_ee => 123 }, 456 ] }).should =={ 'aaBbCc' => [ { 'ddEe' => 123 }, 456 ] }
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PulseMeter::Observer::Extended do
|
4
|
+
context "instance methods observation" do
|
5
|
+
let!(:dummy) {ObservedDummy.new}
|
6
|
+
let!(:sensor) {PulseMeter::Sensor::Counter.new(:foo)}
|
7
|
+
before do
|
8
|
+
[:incr, :error].each {|m| described_class.unobserve_method(ObservedDummy, m)}
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".observe_method" do
|
12
|
+
it "passes exended parameters to block in normal execution" do
|
13
|
+
Timecop.freeze do
|
14
|
+
parameters = {}
|
15
|
+
|
16
|
+
described_class.observe_method(ObservedDummy, :incr, sensor) do |params|
|
17
|
+
parameters = params
|
18
|
+
end
|
19
|
+
|
20
|
+
dummy.incr(40)
|
21
|
+
|
22
|
+
parameters[:self].should == dummy
|
23
|
+
parameters[:delta].should >= 1000
|
24
|
+
parameters[:result].should == 40
|
25
|
+
parameters[:exception].should be_nil
|
26
|
+
parameters[:args].should == [40]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "passes exended parameters to block with exception" do
|
31
|
+
Timecop.freeze do
|
32
|
+
parameters = {}
|
33
|
+
|
34
|
+
described_class.observe_method(ObservedDummy, :error, sensor) do |params|
|
35
|
+
parameters = params
|
36
|
+
end
|
37
|
+
|
38
|
+
lambda { dummy.error }.should raise_error(RuntimeError)
|
39
|
+
|
40
|
+
parameters[:self].should == dummy
|
41
|
+
parameters[:result].should == nil
|
42
|
+
parameters[:exception].class.should == RuntimeError
|
43
|
+
parameters[:args].should == []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "class methods observation" do
|
50
|
+
let!(:sensor) {PulseMeter::Sensor::Counter.new(:foo)}
|
51
|
+
before do
|
52
|
+
[:incr, :error].each {|m| described_class.unobserve_class_method(ObservedDummy, m)}
|
53
|
+
end
|
54
|
+
|
55
|
+
describe ".observe_class_method" do
|
56
|
+
it "passes exended parameters to block in normal execution" do
|
57
|
+
Timecop.freeze do
|
58
|
+
parameters = {}
|
59
|
+
|
60
|
+
described_class.observe_class_method(ObservedDummy, :incr, sensor) do |params|
|
61
|
+
parameters = params
|
62
|
+
end
|
63
|
+
|
64
|
+
ObservedDummy.incr(40)
|
65
|
+
|
66
|
+
parameters[:self].should == ObservedDummy
|
67
|
+
parameters[:delta].should >= 1000
|
68
|
+
parameters[:result].should == 40
|
69
|
+
parameters[:exception].should be_nil
|
70
|
+
parameters[:args].should == [40]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "passes exended parameters to block with exception" do
|
75
|
+
Timecop.freeze do
|
76
|
+
parameters = {}
|
77
|
+
|
78
|
+
described_class.observe_class_method(ObservedDummy, :error, sensor) do |params|
|
79
|
+
parameters = params
|
80
|
+
end
|
81
|
+
|
82
|
+
lambda { ObservedDummy.error }.should raise_error(RuntimeError)
|
83
|
+
|
84
|
+
parameters[:self].should == ObservedDummy
|
85
|
+
parameters[:result].should == nil
|
86
|
+
parameters[:exception].class.should == RuntimeError
|
87
|
+
parameters[:args].should == []
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -3,26 +3,6 @@ require 'spec_helper'
|
|
3
3
|
describe PulseMeter::Observer do
|
4
4
|
|
5
5
|
context "instance methods observation" do
|
6
|
-
|
7
|
-
class ObservedDummy
|
8
|
-
attr_reader :count
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@count = 0
|
12
|
-
end
|
13
|
-
|
14
|
-
def incr(value = 1, &proc)
|
15
|
-
Timecop.travel(Time.now + 1)
|
16
|
-
@count += value
|
17
|
-
@count += proc.call if proc
|
18
|
-
@count
|
19
|
-
end
|
20
|
-
|
21
|
-
def error
|
22
|
-
raise RuntimeError
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
6
|
let!(:dummy) {ObservedDummy.new}
|
27
7
|
let!(:sensor) {PulseMeter::Sensor::Counter.new(:foo)}
|
28
8
|
before do
|
@@ -124,31 +104,6 @@ describe PulseMeter::Observer do
|
|
124
104
|
end
|
125
105
|
|
126
106
|
context "class methods observation" do
|
127
|
-
|
128
|
-
class ObservedDummy
|
129
|
-
@@count = 0
|
130
|
-
class << self
|
131
|
-
def count
|
132
|
-
@@count
|
133
|
-
end
|
134
|
-
|
135
|
-
def reset
|
136
|
-
@@count = 0
|
137
|
-
end
|
138
|
-
|
139
|
-
def incr(value = 1, &proc)
|
140
|
-
Timecop.travel(Time.now + 1)
|
141
|
-
@@count += value
|
142
|
-
@@count += proc.call if proc
|
143
|
-
@@count
|
144
|
-
end
|
145
|
-
|
146
|
-
def error
|
147
|
-
raise RuntimeError
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
107
|
let!(:dummy) {ObservedDummy}
|
153
108
|
let!(:sensor) {PulseMeter::Sensor::Counter.new(:foo)}
|
154
109
|
before do
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class ObservedDummy
|
2
|
+
attr_reader :count
|
3
|
+
@@count = 0
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@count = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def incr(value = 1, &proc)
|
10
|
+
Timecop.travel(Time.now + 1)
|
11
|
+
@count += value
|
12
|
+
@count += proc.call if proc
|
13
|
+
@count
|
14
|
+
end
|
15
|
+
|
16
|
+
def error
|
17
|
+
raise RuntimeError
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def count
|
22
|
+
@@count
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
@@count = 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def incr(value = 1, &proc)
|
30
|
+
Timecop.travel(Time.now + 1)
|
31
|
+
@@count += value
|
32
|
+
@@count += proc.call if proc
|
33
|
+
@@count
|
34
|
+
end
|
35
|
+
|
36
|
+
def error
|
37
|
+
raise RuntimeError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|