pulse-meter 0.4.8 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|