metriks 0.8.1 → 0.8.2
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/Gemfile +4 -0
- data/README.md +3 -4
- data/benchmark/samplers.rb +58 -0
- data/lib/metriks.rb +1 -1
- data/lib/metriks/exponentially_decaying_sample.rb +80 -0
- data/lib/metriks/histogram.rb +9 -0
- data/lib/metriks/reporter/logger.rb +12 -2
- data/lib/metriks/snapshot.rb +56 -0
- data/lib/metriks/timer.rb +6 -2
- data/lib/metriks/uniform_sample.rb +5 -0
- data/metriks.gemspec +5 -1
- data/test/histogram_test.rb +73 -4
- data/test/logger_reporter_test.rb +1 -0
- metadata +20 -4
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -9,13 +9,12 @@ I find needs while developing [Papertrail](https://papertrailapp.com/).
|
|
9
9
|
|
10
10
|
# Installing
|
11
11
|
|
12
|
-
|
13
|
-
the gem
|
14
|
-
releasing a gem.
|
12
|
+
The API is still in flux, but you can add this to your project by installing
|
13
|
+
the gem.
|
15
14
|
|
16
15
|
To install, add this to your `Gemfile`:
|
17
16
|
|
18
|
-
gem 'metriks'
|
17
|
+
gem 'metriks'
|
19
18
|
|
20
19
|
and re-run `bundle`.
|
21
20
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'metriks'
|
5
|
+
|
6
|
+
|
7
|
+
def fib(n)
|
8
|
+
n < 2 ? n : fib(n-1) + fib(n-2)
|
9
|
+
end
|
10
|
+
|
11
|
+
uniform_timer = Metriks::Timer.new(Metriks::Histogram.new_uniform)
|
12
|
+
exponential_timer = Metriks::Timer.new(Metriks::Histogram.new_exponentially_decaying)
|
13
|
+
|
14
|
+
fib_times = ARGV[0] ? ARGV[0].to_i : 10
|
15
|
+
iter = ARGV[1] ? ARGV[1].to_i : 100000
|
16
|
+
|
17
|
+
puts "fib(#{fib_times}): #{iter} iterations"
|
18
|
+
puts "-" * 50
|
19
|
+
|
20
|
+
plain = Benchmark.realtime do
|
21
|
+
for i in 1..iter
|
22
|
+
fib(fib_times)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "%15s: %f secs %f secs/call" % [ 'plain', plain, plain / iter ]
|
27
|
+
|
28
|
+
uniform = Benchmark.realtime do
|
29
|
+
for i in 1..iter
|
30
|
+
uniform_timer.time do
|
31
|
+
fib(fib_times)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "%15s: %f secs %f secs/call -- %.1f%% slower than plain (%f secs/call)" % [
|
37
|
+
'uniform', uniform, uniform / iter,
|
38
|
+
(uniform - plain) / plain * 100 ,
|
39
|
+
(uniform - plain) / iter,
|
40
|
+
]
|
41
|
+
|
42
|
+
exponential = Benchmark.realtime do
|
43
|
+
for i in 1..iter
|
44
|
+
exponential_timer.time do
|
45
|
+
fib(fib_times)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "%15s: %f secs %f secs/call -- %.1f%% slower than plain (%f secs/call) -- %.1f%% slower than uniform (%f secs/call)" % [
|
51
|
+
'exponential', exponential, exponential / iter,
|
52
|
+
(exponential - plain) / plain * 100 ,
|
53
|
+
(exponential - plain) / iter,
|
54
|
+
(exponential - uniform) / uniform * 100 ,
|
55
|
+
(exponential - uniform) / iter
|
56
|
+
]
|
57
|
+
|
58
|
+
|
data/lib/metriks.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'atomic'
|
2
|
+
require 'rbtree'
|
3
|
+
require 'metriks/snapshot'
|
4
|
+
|
5
|
+
module Metriks
|
6
|
+
class ExponentiallyDecayingSample
|
7
|
+
RESCALE_THRESHOLD = 60 * 60 # 1 hour
|
8
|
+
|
9
|
+
def initialize(reservoir_size, alpha)
|
10
|
+
@values = RBTree.new
|
11
|
+
@count = Atomic.new(0)
|
12
|
+
@next_scale_time = Atomic.new(0)
|
13
|
+
@alpha = alpha
|
14
|
+
@reservoir_size = reservoir_size
|
15
|
+
@mutex = Mutex.new
|
16
|
+
clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear
|
20
|
+
@mutex.synchronize do
|
21
|
+
@values.clear
|
22
|
+
@count.value = 0
|
23
|
+
@next_scale_time.value = Time.now + RESCALE_THRESHOLD
|
24
|
+
@start_time = Time.now
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
count = @count.value
|
30
|
+
count < @reservoir_size ? count : @reservoir_size
|
31
|
+
end
|
32
|
+
|
33
|
+
def snapshot
|
34
|
+
@mutex.synchronize do
|
35
|
+
Snapshot.new(@values.values)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def update(value, timestamp = Time.now)
|
40
|
+
@mutex.synchronize do
|
41
|
+
priority = Math.exp(timestamp - @start_time) / rand
|
42
|
+
new_count = @count.update { |v| v + 1 }
|
43
|
+
if new_count <= @reservoir_size
|
44
|
+
@values[priority] = value
|
45
|
+
else
|
46
|
+
first_priority = @values.first[0]
|
47
|
+
if first_priority < priority
|
48
|
+
unless @values[priority]
|
49
|
+
@values[priority] = value
|
50
|
+
|
51
|
+
until @values.delete(first_priority)
|
52
|
+
first_priority = @values.first[0]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
now = Time.new
|
60
|
+
next_time = @next_scale_time.value
|
61
|
+
if now >= next_time
|
62
|
+
rescale(now, next_time)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def rescale(now, next_time)
|
67
|
+
if @next_scale_time.compare_and_swap(next_time, now + RESCALE_THRESHOLD)
|
68
|
+
@mutex.synchronize do
|
69
|
+
old_start_time = @start_time
|
70
|
+
@start_time = Time.now
|
71
|
+
keys = @values.keys
|
72
|
+
keys.each do |key|
|
73
|
+
value = @values.delete(key)
|
74
|
+
@values[key* Math.exp(-@alpha * (@start_time - old_start_time))] = value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/metriks/histogram.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'atomic'
|
2
2
|
require 'metriks/uniform_sample'
|
3
|
+
require 'metriks/exponentially_decaying_sample'
|
3
4
|
|
4
5
|
module Metriks
|
5
6
|
class Histogram
|
@@ -10,6 +11,10 @@ module Metriks
|
|
10
11
|
new(Metriks::UniformSample.new(DEFAULT_SAMPLE_SIZE))
|
11
12
|
end
|
12
13
|
|
14
|
+
def self.new_exponentially_decaying
|
15
|
+
new(Metriks::ExponentiallyDecayingSample.new(DEFAULT_SAMPLE_SIZE, DEFAULT_ALPHA))
|
16
|
+
end
|
17
|
+
|
13
18
|
def initialize(sample)
|
14
19
|
@sample = sample
|
15
20
|
@count = Atomic.new(0)
|
@@ -37,6 +42,10 @@ module Metriks
|
|
37
42
|
update_variance(value)
|
38
43
|
end
|
39
44
|
|
45
|
+
def snapshot
|
46
|
+
@sample.snapshot
|
47
|
+
end
|
48
|
+
|
40
49
|
def count
|
41
50
|
@count.value
|
42
51
|
end
|
@@ -51,12 +51,16 @@ module Metriks::Reporter
|
|
51
51
|
:min, :max, :mean, :stddev,
|
52
52
|
:one_minute_utilization, :five_minute_utilization,
|
53
53
|
:fifteen_minute_utilization, :mean_utilization,
|
54
|
+
], [
|
55
|
+
:median, :get_95th_percentile
|
54
56
|
]
|
55
57
|
when Metriks::Timer
|
56
58
|
log_metric name, 'timer', metric, [
|
57
59
|
:count, :one_minute_rate, :five_minute_rate,
|
58
60
|
:fifteen_minute_rate, :mean_rate,
|
59
61
|
:min, :max, :mean, :stddev
|
62
|
+
], [
|
63
|
+
:median, :get_95th_percentile
|
60
64
|
]
|
61
65
|
end
|
62
66
|
end
|
@@ -64,11 +68,12 @@ module Metriks::Reporter
|
|
64
68
|
|
65
69
|
def extract_from_metric(metric, *keys)
|
66
70
|
keys.flatten.collect do |key|
|
67
|
-
|
71
|
+
name = key.to_s.gsub(/^get_/, '')
|
72
|
+
[ { name => metric.send(key) } ]
|
68
73
|
end
|
69
74
|
end
|
70
75
|
|
71
|
-
def log_metric(name, type, metric,
|
76
|
+
def log_metric(name, type, metric, keys, snapshot_keys = [])
|
72
77
|
message = []
|
73
78
|
|
74
79
|
message << @prefix if @prefix
|
@@ -78,6 +83,11 @@ module Metriks::Reporter
|
|
78
83
|
message << { :type => type }
|
79
84
|
message += extract_from_metric(metric, keys)
|
80
85
|
|
86
|
+
unless snapshot_keys.empty?
|
87
|
+
snapshot = metric.snapshot
|
88
|
+
message += extract_from_metric(snapshot, snapshot_keys)
|
89
|
+
end
|
90
|
+
|
81
91
|
@logger.add(@log_level, format_message(message))
|
82
92
|
end
|
83
93
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
class Snapshot
|
3
|
+
MEDIAN_Q = 0.5
|
4
|
+
P75_Q = 0.75
|
5
|
+
P95_Q = 0.95
|
6
|
+
P98_Q = 0.98
|
7
|
+
P99_Q = 0.99
|
8
|
+
P999_Q = 0.999
|
9
|
+
|
10
|
+
def initialize(values)
|
11
|
+
@values = values.sort
|
12
|
+
end
|
13
|
+
|
14
|
+
def value(quantile)
|
15
|
+
raise ArgumentError, "quantile must be between 0.0 and 1.0" if quantile < 0.0 || quantile > 1.0
|
16
|
+
|
17
|
+
return 0.0 if @values.empty?
|
18
|
+
|
19
|
+
pos = quantile * (@values.length + 1)
|
20
|
+
|
21
|
+
return @values.first if pos < 1
|
22
|
+
return @values.last if pos >= @values.length
|
23
|
+
|
24
|
+
lower = @values[pos.to_i - 1]
|
25
|
+
upper = @values[pos.to_i]
|
26
|
+
lower + (pos - pos.floor) + (upper - lower)
|
27
|
+
end
|
28
|
+
|
29
|
+
def size
|
30
|
+
@values.length
|
31
|
+
end
|
32
|
+
|
33
|
+
def median
|
34
|
+
value(MEDIAN_Q)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_75th_percentile
|
38
|
+
value(P75_Q)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_95th_percentile
|
42
|
+
value(P95_Q)
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_98th_percentile
|
46
|
+
value(P98_Q)
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_99th_percentile
|
50
|
+
value(P99_Q)
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_999th_percentile
|
54
|
+
value(P999_Q)
|
55
|
+
end
|
56
|
+
end
|
data/lib/metriks/timer.rb
CHANGED
@@ -18,9 +18,9 @@ module Metriks
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize
|
21
|
+
def initialize(histogram = Metriks::Histogram.new_exponentially_decaying)
|
22
22
|
@meter = Metriks::Meter.new
|
23
|
-
@histogram =
|
23
|
+
@histogram = histogram
|
24
24
|
end
|
25
25
|
|
26
26
|
def clear
|
@@ -50,6 +50,10 @@ module Metriks
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
def snapshot
|
54
|
+
@histogram.snapshot
|
55
|
+
end
|
56
|
+
|
53
57
|
def count
|
54
58
|
@histogram.count
|
55
59
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'atomic'
|
2
|
+
require 'metriks/snapshot'
|
2
3
|
|
3
4
|
module Metriks
|
4
5
|
class UniformSample
|
@@ -19,6 +20,10 @@ module Metriks
|
|
19
20
|
count > @values.length ? @values.length : count
|
20
21
|
end
|
21
22
|
|
23
|
+
def snapshot
|
24
|
+
Snapshot.new(@values.slice(0, size))
|
25
|
+
end
|
26
|
+
|
22
27
|
def update(value)
|
23
28
|
new_count = @count.update { |v| v + 1 }
|
24
29
|
|
data/metriks.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
## If your rubyforge_project name is different, then edit it and comment out
|
14
14
|
## the sub! line in the Rakefile
|
15
15
|
s.name = 'metriks'
|
16
|
-
s.version = '0.8.
|
16
|
+
s.version = '0.8.2'
|
17
17
|
s.date = '2012-02-27'
|
18
18
|
|
19
19
|
## Make sure your summary is short. The description may be as long
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
## that are needed for an end user to actually USE your code.
|
45
45
|
s.add_dependency('atomic', ["~> 1.0"])
|
46
46
|
s.add_dependency('hitimes', [ "~> 1.1"])
|
47
|
+
s.add_dependency('rbtree', [ "~> 0.3" ])
|
47
48
|
|
48
49
|
## List your development dependencies here. Development dependencies are
|
49
50
|
## those that are only needed during development
|
@@ -58,15 +59,18 @@ Gem::Specification.new do |s|
|
|
58
59
|
LICENSE
|
59
60
|
README.md
|
60
61
|
Rakefile
|
62
|
+
benchmark/samplers.rb
|
61
63
|
lib/metriks.rb
|
62
64
|
lib/metriks/counter.rb
|
63
65
|
lib/metriks/ewma.rb
|
66
|
+
lib/metriks/exponentially_decaying_sample.rb
|
64
67
|
lib/metriks/histogram.rb
|
65
68
|
lib/metriks/meter.rb
|
66
69
|
lib/metriks/registry.rb
|
67
70
|
lib/metriks/reporter/logger.rb
|
68
71
|
lib/metriks/reporter/proc_title.rb
|
69
72
|
lib/metriks/simple_moving_average.rb
|
73
|
+
lib/metriks/snapshot.rb
|
70
74
|
lib/metriks/timer.rb
|
71
75
|
lib/metriks/uniform_sample.rb
|
72
76
|
lib/metriks/utilization_timer.rb
|
data/test/histogram_test.rb
CHANGED
@@ -4,35 +4,104 @@ require 'metriks/histogram'
|
|
4
4
|
|
5
5
|
class HistogramTest < Test::Unit::TestCase
|
6
6
|
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_uniform_sample_min
|
10
|
+
@histogram = Metriks::Histogram.new(Metriks::UniformSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE))
|
11
|
+
|
12
|
+
@histogram.update(5)
|
13
|
+
@histogram.update(10)
|
14
|
+
|
15
|
+
assert_equal 5, @histogram.min
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_uniform_sample_max
|
19
|
+
@histogram = Metriks::Histogram.new(Metriks::UniformSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE))
|
20
|
+
|
21
|
+
@histogram.update(5)
|
22
|
+
@histogram.update(10)
|
23
|
+
|
24
|
+
assert_equal 10, @histogram.max
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_uniform_sample_mean
|
28
|
+
@histogram = Metriks::Histogram.new(Metriks::UniformSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE))
|
29
|
+
|
30
|
+
@histogram.update(5)
|
31
|
+
@histogram.update(10)
|
32
|
+
|
33
|
+
assert_equal 7, @histogram.mean
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_uniform_sample_2000
|
7
37
|
@histogram = Metriks::Histogram.new(Metriks::UniformSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE))
|
38
|
+
|
39
|
+
2000.times do |idx|
|
40
|
+
@histogram.update(idx)
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_equal 1999, @histogram.max
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_uniform_sample_snashot
|
47
|
+
@histogram = Metriks::Histogram.new(Metriks::UniformSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE))
|
48
|
+
|
49
|
+
50.times do |idx|
|
50
|
+
@histogram.update(idx)
|
51
|
+
end
|
52
|
+
|
53
|
+
snapshot = @histogram.snapshot
|
54
|
+
|
55
|
+
assert_equal 25.5, snapshot.median
|
8
56
|
end
|
9
57
|
|
10
|
-
def
|
58
|
+
def test_exponential_sample_min
|
59
|
+
@histogram = Metriks::Histogram.new(Metriks::ExponentiallyDecayingSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE, Metriks::Histogram::DEFAULT_ALPHA))
|
60
|
+
|
11
61
|
@histogram.update(5)
|
12
62
|
@histogram.update(10)
|
13
63
|
|
14
64
|
assert_equal 5, @histogram.min
|
15
65
|
end
|
16
66
|
|
17
|
-
def
|
67
|
+
def test_exponential_sample_max
|
68
|
+
@histogram = Metriks::Histogram.new(Metriks::ExponentiallyDecayingSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE, Metriks::Histogram::DEFAULT_ALPHA))
|
69
|
+
|
18
70
|
@histogram.update(5)
|
19
71
|
@histogram.update(10)
|
20
72
|
|
21
73
|
assert_equal 10, @histogram.max
|
22
74
|
end
|
23
75
|
|
24
|
-
def
|
76
|
+
def test_exponential_sample_mean
|
77
|
+
@histogram = Metriks::Histogram.new(Metriks::ExponentiallyDecayingSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE, Metriks::Histogram::DEFAULT_ALPHA))
|
78
|
+
|
25
79
|
@histogram.update(5)
|
26
80
|
@histogram.update(10)
|
27
81
|
|
28
82
|
assert_equal 7, @histogram.mean
|
29
83
|
end
|
30
84
|
|
31
|
-
def
|
85
|
+
def test_exponential_sample_2000
|
86
|
+
@histogram = Metriks::Histogram.new(Metriks::ExponentiallyDecayingSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE, Metriks::Histogram::DEFAULT_ALPHA))
|
87
|
+
|
32
88
|
2000.times do |idx|
|
33
89
|
@histogram.update(idx)
|
34
90
|
end
|
35
91
|
|
36
92
|
assert_equal 1999, @histogram.max
|
37
93
|
end
|
94
|
+
|
95
|
+
def test_exponential_sample_snashot
|
96
|
+
@histogram = Metriks::Histogram.new(Metriks::ExponentiallyDecayingSample.new(Metriks::Histogram::DEFAULT_SAMPLE_SIZE, Metriks::Histogram::DEFAULT_ALPHA))
|
97
|
+
|
98
|
+
50.times do |idx|
|
99
|
+
@histogram.update(idx)
|
100
|
+
end
|
101
|
+
|
102
|
+
snapshot = @histogram.snapshot
|
103
|
+
|
104
|
+
assert_equal 25.5, snapshot.median
|
105
|
+
end
|
106
|
+
|
38
107
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 8
|
8
|
-
-
|
9
|
-
version: 0.8.
|
8
|
+
- 2
|
9
|
+
version: 0.8.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Eric Lindvall
|
@@ -44,9 +44,22 @@ dependencies:
|
|
44
44
|
type: :runtime
|
45
45
|
version_requirements: *id002
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: rbtree
|
48
48
|
prerelease: false
|
49
49
|
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
- 3
|
56
|
+
version: "0.3"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: tomdoc
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
63
|
requirements:
|
51
64
|
- - ~>
|
52
65
|
- !ruby/object:Gem::Version
|
@@ -55,7 +68,7 @@ dependencies:
|
|
55
68
|
- 2
|
56
69
|
version: "0.2"
|
57
70
|
type: :development
|
58
|
-
version_requirements: *
|
71
|
+
version_requirements: *id004
|
59
72
|
description: An experimental metrics client.
|
60
73
|
email: eric@sevenscale.com
|
61
74
|
executables: []
|
@@ -70,15 +83,18 @@ files:
|
|
70
83
|
- LICENSE
|
71
84
|
- README.md
|
72
85
|
- Rakefile
|
86
|
+
- benchmark/samplers.rb
|
73
87
|
- lib/metriks.rb
|
74
88
|
- lib/metriks/counter.rb
|
75
89
|
- lib/metriks/ewma.rb
|
90
|
+
- lib/metriks/exponentially_decaying_sample.rb
|
76
91
|
- lib/metriks/histogram.rb
|
77
92
|
- lib/metriks/meter.rb
|
78
93
|
- lib/metriks/registry.rb
|
79
94
|
- lib/metriks/reporter/logger.rb
|
80
95
|
- lib/metriks/reporter/proc_title.rb
|
81
96
|
- lib/metriks/simple_moving_average.rb
|
97
|
+
- lib/metriks/snapshot.rb
|
82
98
|
- lib/metriks/timer.rb
|
83
99
|
- lib/metriks/uniform_sample.rb
|
84
100
|
- lib/metriks/utilization_timer.rb
|