metrician 0.0.11 → 0.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +1 -1
- data/gemfiles/Gemfile.4.2.sidekiq-4.lock +1 -1
- data/gemfiles/Gemfile.5.0.pg.lock +1 -1
- data/gemfiles/Gemfile.dalli_not_memcached.lock +2 -2
- data/gemfiles/Gemfile.minimal.lock +2 -2
- data/lib/metrician/reporter.rb +1 -1
- data/lib/metrician/reporters/memcache.rb +5 -5
- data/lib/metrician/reporters/method_timer.rb +70 -0
- data/lib/metrician/reporters/net_http.rb +5 -5
- data/lib/metrician/reporters/redis.rb +5 -5
- data/lib/metrician/version.rb +1 -1
- data/metrician.defaults.yaml +3 -3
- data/metrician.example.yaml +3 -3
- data/spec/metrician_spec.rb +27 -0
- metadata +3 -3
- data/lib/metrician/reporters/method_tracer.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0061f0ebb86e501bc59c0b0ec001bcc7371b725c
|
4
|
+
data.tar.gz: 17fe4bb8fd8faa906a197dc95f15d518ae2af77c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3060f34b98a589e141a0dd337291f9f016ab4186595cec5db7681abb0095e25a09a6490c76efeafefd31a4442db30a0faf74f3ffcd83eecaec4c6c74acb8ea9
|
7
|
+
data.tar.gz: b17b46f886d8351c54a5001835106c46eae4d59b3a6badb5f6f8765f8252f644ed32a0d7c36e15fac154286cae782d528a702b6bd83108eab1b9aec7f3fa90cc
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
data/lib/metrician/reporter.rb
CHANGED
@@ -33,7 +33,7 @@ require "metrician/reporters/active_record"
|
|
33
33
|
require "metrician/reporters/delayed_job"
|
34
34
|
require "metrician/reporters/honeybadger"
|
35
35
|
require "metrician/reporters/memcache"
|
36
|
-
require "metrician/reporters/
|
36
|
+
require "metrician/reporters/method_timer"
|
37
37
|
require "metrician/reporters/middleware"
|
38
38
|
require "metrician/reporters/net_http"
|
39
39
|
require "metrician/reporters/redis"
|
@@ -31,22 +31,22 @@ module Metrician
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def instrument_class(client_class)
|
34
|
-
return if client_class.method_defined?(:
|
34
|
+
return if client_class.method_defined?(:get_with_metrician_time)
|
35
35
|
METHODS.each do |method_name|
|
36
36
|
next unless client_class.method_defined?(method_name)
|
37
37
|
client_class.class_eval <<-RUBY
|
38
|
-
def #{method_name}
|
38
|
+
def #{method_name}_with_metrician_time(*args, &blk)
|
39
39
|
start_time = Time.now
|
40
40
|
begin
|
41
|
-
#{method_name}
|
41
|
+
#{method_name}_without_metrician_time(*args, &blk)
|
42
42
|
ensure
|
43
43
|
duration = (Time.now - start_time).to_f
|
44
44
|
Metrician.gauge(::Metrician::Memcache::CACHE_METRIC, duration) if Metrician.configuration[:cache][:command][:enabled]
|
45
45
|
Metrician.gauge("#{::Metrician::Memcache::CACHE_METRIC}.#{method_name}", duration) if Metrician.configuration[:cache][:command_specific][:enabled]
|
46
46
|
end
|
47
47
|
end
|
48
|
-
alias #{method_name}
|
49
|
-
alias #{method_name} #{method_name}
|
48
|
+
alias #{method_name}_without_metrician_time #{method_name}
|
49
|
+
alias #{method_name} #{method_name}_with_metrician_time
|
50
50
|
RUBY
|
51
51
|
end
|
52
52
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Metrician
|
2
|
+
|
3
|
+
class MethodTimer < Reporter
|
4
|
+
|
5
|
+
def self.enabled?
|
6
|
+
Metrician.configuration[:method_timer][:enabled]
|
7
|
+
end
|
8
|
+
|
9
|
+
def instrument
|
10
|
+
Module.send(:include, TimingMethodInterceptor)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
module TimingMethodInterceptor
|
16
|
+
|
17
|
+
def self.default_metric_name(klass, is_klass_method, method_name)
|
18
|
+
name = klass.name.underscore
|
19
|
+
name = "#{name}.self" if is_klass_method
|
20
|
+
"timer.#{name}.#{method_name}".downcase.tr_s("^a-zA-Z0-9.", "_")
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.timeable_method?(klass, method_name)
|
24
|
+
klass.method_defined?(method_name) ||
|
25
|
+
klass.private_method_defined?(method_name) ||
|
26
|
+
klass.methods.include?(method_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.already_timed_method?(klass, is_klass_method, timed_name)
|
30
|
+
is_klass_method ?
|
31
|
+
klass.methods.include?(timed_name) :
|
32
|
+
klass.method_defined?(timed_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.code_to_eval(is_klass_method, method_name, timed_name, untimed_name, metric_name)
|
36
|
+
<<-EOD
|
37
|
+
#{'class << self' if is_klass_method}
|
38
|
+
def #{timed_name}(*args, &block)
|
39
|
+
start_time = Time.now
|
40
|
+
begin
|
41
|
+
#{untimed_name}(*args, &block)
|
42
|
+
ensure
|
43
|
+
Metrician.gauge("#{metric_name}", (Time.now - start_time).to_f)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias :#{untimed_name} :#{method_name}
|
47
|
+
alias :#{method_name} :#{timed_name}
|
48
|
+
#{'end' if is_klass_method}
|
49
|
+
EOD
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_metrician_method_timer(method_name, metric_name = nil)
|
53
|
+
return false unless TimingMethodInterceptor.timeable_method?(self, method_name)
|
54
|
+
|
55
|
+
is_klass_method = methods.include?(method_name)
|
56
|
+
timed_name = "with_metrician_time_#{method_name}"
|
57
|
+
return false if TimingMethodInterceptor.already_timed_method?(self, is_klass_method, timed_name)
|
58
|
+
|
59
|
+
metric_name ||= TimingMethodInterceptor.default_metric_name(self, is_klass_method, method_name)
|
60
|
+
untimed_name = "without_metrician_time_#{method_name}"
|
61
|
+
|
62
|
+
timed_method_code =
|
63
|
+
TimingMethodInterceptor.code_to_eval(is_klass_method, method_name, timed_name,
|
64
|
+
untimed_name, metric_name)
|
65
|
+
class_eval(timed_method_code, __FILE__, __LINE__)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -11,18 +11,18 @@ module Metrician
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def instrument
|
14
|
-
return if ::Net::HTTP.method_defined?(:
|
14
|
+
return if ::Net::HTTP.method_defined?(:request_with_metrician_time)
|
15
15
|
::Net::HTTP.class_eval do
|
16
|
-
def
|
16
|
+
def request_with_metrician_time(req, body = nil, &block)
|
17
17
|
start_time = Time.now
|
18
18
|
begin
|
19
|
-
|
19
|
+
request_without_metrician_time(req, body, &block)
|
20
20
|
ensure
|
21
21
|
Metrician.gauge(REQUEST_METRIC, (Time.now - start_time).to_f) if Metrician.configuration[:external_service][:request][:enabled]
|
22
22
|
end
|
23
23
|
end
|
24
|
-
alias_method :
|
25
|
-
alias_method :request, :
|
24
|
+
alias_method :request_without_metrician_time, :request
|
25
|
+
alias_method :request, :request_with_metrician_time
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -9,12 +9,12 @@ module Metrician
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def instrument
|
12
|
-
return if ::Redis::Client.method_defined?(:
|
12
|
+
return if ::Redis::Client.method_defined?(:call_with_metrician_time)
|
13
13
|
::Redis::Client.class_eval do
|
14
|
-
def
|
14
|
+
def call_with_metrician_time(*args, &blk)
|
15
15
|
start_time = Time.now
|
16
16
|
begin
|
17
|
-
|
17
|
+
call_without_metrician_time(*args, &blk)
|
18
18
|
ensure
|
19
19
|
duration = (Time.now - start_time).to_f
|
20
20
|
Metrician.gauge(CACHE_METRIC, duration) if Metrician.configuration[:cache][:command][:enabled]
|
@@ -24,8 +24,8 @@ module Metrician
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
|
-
alias_method :
|
28
|
-
alias_method :call, :
|
27
|
+
alias_method :call_without_metrician_time, :call
|
28
|
+
alias_method :call, :call_with_metrician_time
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
data/lib/metrician/version.rb
CHANGED
data/metrician.defaults.yaml
CHANGED
@@ -131,10 +131,10 @@
|
|
131
131
|
:exception_specific:
|
132
132
|
:enabled: false
|
133
133
|
|
134
|
-
# "
|
134
|
+
# "method_timer" settings control hooking into Module and allowing
|
135
135
|
# ruby methods to be timed
|
136
|
-
:
|
136
|
+
:method_timer:
|
137
137
|
|
138
|
-
# hook into Module with
|
138
|
+
# hook into Module with add_metrician_method_timer added as a base
|
139
139
|
# feature of every ruby object
|
140
140
|
:enabled: false
|
data/metrician.example.yaml
CHANGED
@@ -127,10 +127,10 @@
|
|
127
127
|
# :exception_specific:
|
128
128
|
# :enabled: false
|
129
129
|
|
130
|
-
# # "
|
130
|
+
# # "method_timer" settings control hooking into Module and allowing
|
131
131
|
# # ruby methods to be timed
|
132
|
-
:
|
132
|
+
:method_timer:
|
133
133
|
|
134
|
-
# # hook into Module with
|
134
|
+
# # hook into Module with add_metrician_method_timer added as a base
|
135
135
|
# # feature of every ruby object
|
136
136
|
# :enabled: true
|
data/spec/metrician_spec.rb
CHANGED
@@ -67,6 +67,33 @@ RSpec.describe Metrician do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
describe "method timing" do
|
71
|
+
before do
|
72
|
+
Metrician.configuration[:method_timer][:enabled] = true
|
73
|
+
@agent = Metrician.null_agent
|
74
|
+
Metrician.activate(@agent)
|
75
|
+
end
|
76
|
+
|
77
|
+
let(:test_instance) do
|
78
|
+
class TestClass
|
79
|
+
def instance_it; end
|
80
|
+
add_metrician_method_timer :instance_it
|
81
|
+
|
82
|
+
def self.class_it; end
|
83
|
+
add_metrician_method_timer :class_it
|
84
|
+
end
|
85
|
+
TestClass.new
|
86
|
+
end
|
87
|
+
|
88
|
+
specify "instance method timings are reported" do
|
89
|
+
@agent.stub(:gauge)
|
90
|
+
@agent.should_receive(:gauge).with("app.timer.test_class.instance_it", anything)
|
91
|
+
test_instance.instance_it
|
92
|
+
@agent.should_receive(:gauge).with("app.timer.test_class.self.class_it", anything)
|
93
|
+
test_instance.class.class_it
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
70
97
|
describe "exception tracking" do
|
71
98
|
before do
|
72
99
|
Metrician.configuration[:exception][:enabled] = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metrician
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Expected Behavior
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: instrumental_agent
|
@@ -150,7 +150,7 @@ files:
|
|
150
150
|
- lib/metrician/reporters/delayed_job.rb
|
151
151
|
- lib/metrician/reporters/honeybadger.rb
|
152
152
|
- lib/metrician/reporters/memcache.rb
|
153
|
-
- lib/metrician/reporters/
|
153
|
+
- lib/metrician/reporters/method_timer.rb
|
154
154
|
- lib/metrician/reporters/middleware.rb
|
155
155
|
- lib/metrician/reporters/net_http.rb
|
156
156
|
- lib/metrician/reporters/redis.rb
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module Metrician
|
2
|
-
|
3
|
-
class MethodTracer < Reporter
|
4
|
-
|
5
|
-
def self.enabled?
|
6
|
-
Metrician.configuration[:method_tracer][:enabled]
|
7
|
-
end
|
8
|
-
|
9
|
-
def instrument
|
10
|
-
Module.send(:include, TracingMethodInterceptor)
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
module TracingMethodInterceptor
|
16
|
-
|
17
|
-
def self.default_metric_name(klass, is_klass_method, method_name)
|
18
|
-
name = klass.name.underscore
|
19
|
-
name = "#{name}.self" if is_klass_method
|
20
|
-
"tracer.#{name}.#{method_name}".downcase.tr_s("^a-zA-Z0-9.", "_")
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.traceable_method?(klass, method_name)
|
24
|
-
klass.method_defined?(method_name) ||
|
25
|
-
klass.private_method_defined?(method_name) ||
|
26
|
-
klass.methods.include?(method_name.to_s)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.already_traced_method?(klass, is_klass_method, traced_name)
|
30
|
-
is_klass_method ?
|
31
|
-
klass.methods.include?(traced_name) :
|
32
|
-
klass.method_defined?(traced_name)
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.code_to_eval(is_klass_method, method_name, traced_name, untraced_name, metric_name)
|
36
|
-
<<-EOD
|
37
|
-
#{'class << self' if is_klass_method}
|
38
|
-
def #{traced_name}(*args, &block)
|
39
|
-
start_time = Time.now
|
40
|
-
begin
|
41
|
-
#{untraced_name}(*args, &block)
|
42
|
-
ensure
|
43
|
-
Metrician.gauge("#{metric_name}", (Time.now - start_time).to_f)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
alias :#{untraced_name} :#{method_name}
|
47
|
-
alias :#{method_name} :#{traced_name}
|
48
|
-
#{'end' if is_klass_method}
|
49
|
-
EOD
|
50
|
-
end
|
51
|
-
|
52
|
-
def add_metrician_method_tracer(method_name, metric_name = nil)
|
53
|
-
return false unless TracingMethodInterceptor.traceable_method?(self, method_name)
|
54
|
-
|
55
|
-
is_klass_method = methods.include?(method_name.to_s)
|
56
|
-
traced_name = "with_metrician_trace_#{method_name}"
|
57
|
-
return false if TracingMethodInterceptor.already_traced_method?(self, is_klass_method, traced_name)
|
58
|
-
|
59
|
-
metric_name ||= TracingMethodInterceptor.default_metric_name(self, is_klass_method, method_name)
|
60
|
-
untraced_name = "without_metrician_trace_#{method_name}"
|
61
|
-
|
62
|
-
traced_method_code =
|
63
|
-
TracingMethodInterceptor.code_to_eval(is_klass_method, method_name, traced_name,
|
64
|
-
untraced_name, metric_name)
|
65
|
-
class_eval(traced_method_code, __FILE__, __LINE__)
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|