rubycut-metriks 0.9.9.4
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 +14 -0
- data/LICENSE +21 -0
- data/README.md +405 -0
- data/Rakefile +150 -0
- data/benchmark/samplers.rb +92 -0
- data/lib/metriks/counter.rb +44 -0
- data/lib/metriks/ewma.rb +63 -0
- data/lib/metriks/exponentially_decaying_sample.rb +102 -0
- data/lib/metriks/histogram.rb +112 -0
- data/lib/metriks/meter.rb +85 -0
- data/lib/metriks/registry.rb +207 -0
- data/lib/metriks/reporter/graphite.rb +119 -0
- data/lib/metriks/reporter/librato_metrics.rb +185 -0
- data/lib/metriks/reporter/logger.rb +129 -0
- data/lib/metriks/reporter/proc_title.rb +65 -0
- data/lib/metriks/reporter/riemann.rb +119 -0
- data/lib/metriks/simple_moving_average.rb +60 -0
- data/lib/metriks/snapshot.rb +59 -0
- data/lib/metriks/time_tracker.rb +26 -0
- data/lib/metriks/timer.rb +101 -0
- data/lib/metriks/uniform_sample.rb +40 -0
- data/lib/metriks/utilization_timer.rb +43 -0
- data/lib/metriks.rb +35 -0
- data/metriks.gemspec +100 -0
- data/test/counter_test.rb +39 -0
- data/test/graphite_reporter_test.rb +41 -0
- data/test/histogram_test.rb +199 -0
- data/test/librato_metrics_reporter_test.rb +35 -0
- data/test/logger_reporter_test.rb +49 -0
- data/test/meter_test.rb +38 -0
- data/test/metriks_test.rb +31 -0
- data/test/proc_title_reporter_test.rb +25 -0
- data/test/registry_test.rb +49 -0
- data/test/riemann_reporter_test.rb +88 -0
- data/test/test_helper.rb +33 -0
- data/test/thread_error_handling_tests.rb +20 -0
- data/test/timer_test.rb +32 -0
- data/test/utilization_timer_test.rb +25 -0
- metadata +161 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Metriks::Reporter
|
4
|
+
class Graphite
|
5
|
+
attr_reader :host, :port
|
6
|
+
|
7
|
+
def initialize(host, port, options = {})
|
8
|
+
@host = host
|
9
|
+
@port = port
|
10
|
+
|
11
|
+
@prefix = options[:prefix]
|
12
|
+
|
13
|
+
@registry = options[:registry] || Metriks::Registry.default
|
14
|
+
@interval = options[:interval] || 60
|
15
|
+
@on_error = options[:on_error] || proc { |ex| }
|
16
|
+
end
|
17
|
+
|
18
|
+
def socket
|
19
|
+
@socket = nil if @socket && @socket.closed?
|
20
|
+
@socket ||= TCPSocket.new(@host, @port)
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
@thread ||= Thread.new do
|
25
|
+
loop do
|
26
|
+
sleep @interval
|
27
|
+
|
28
|
+
Thread.new do
|
29
|
+
begin
|
30
|
+
write
|
31
|
+
rescue Exception => ex
|
32
|
+
@on_error[ex] rescue nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def stop
|
40
|
+
@thread.kill if @thread
|
41
|
+
@thread = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def restart
|
45
|
+
stop
|
46
|
+
start
|
47
|
+
end
|
48
|
+
|
49
|
+
def write
|
50
|
+
@registry.each do |name, metric|
|
51
|
+
case metric
|
52
|
+
when Metriks::Meter
|
53
|
+
write_metric name, metric, [
|
54
|
+
:count, :one_minute_rate, :five_minute_rate,
|
55
|
+
:fifteen_minute_rate, :mean_rate
|
56
|
+
]
|
57
|
+
when Metriks::Counter
|
58
|
+
write_metric name, metric, [
|
59
|
+
:count
|
60
|
+
]
|
61
|
+
when Metriks::Gauge
|
62
|
+
write_metric name, metric, [
|
63
|
+
:value
|
64
|
+
]
|
65
|
+
when Metriks::UtilizationTimer
|
66
|
+
write_metric name, metric, [
|
67
|
+
:count, :one_minute_rate, :five_minute_rate,
|
68
|
+
:fifteen_minute_rate, :mean_rate,
|
69
|
+
:min, :max, :mean, :stddev,
|
70
|
+
:one_minute_utilization, :five_minute_utilization,
|
71
|
+
:fifteen_minute_utilization, :mean_utilization,
|
72
|
+
], [
|
73
|
+
:median, :get_95th_percentile
|
74
|
+
]
|
75
|
+
when Metriks::Timer
|
76
|
+
write_metric name, metric, [
|
77
|
+
:count, :one_minute_rate, :five_minute_rate,
|
78
|
+
:fifteen_minute_rate, :mean_rate,
|
79
|
+
:min, :max, :mean, :stddev
|
80
|
+
], [
|
81
|
+
:median, :get_95th_percentile
|
82
|
+
]
|
83
|
+
when Metriks::Histogram
|
84
|
+
write_metric name, metric, [
|
85
|
+
:count, :min, :max, :mean, :stddev
|
86
|
+
], [
|
87
|
+
:median, :get_95th_percentile
|
88
|
+
]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def write_metric(base_name, metric, keys, snapshot_keys = [])
|
94
|
+
time = Time.now.to_i
|
95
|
+
|
96
|
+
base_name = base_name.to_s.gsub(/ +/, '_')
|
97
|
+
if @prefix
|
98
|
+
base_name = "#{@prefix}.#{base_name}"
|
99
|
+
end
|
100
|
+
|
101
|
+
keys.flatten.each do |key|
|
102
|
+
name = key.to_s.gsub(/^get_/, '')
|
103
|
+
value = metric.send(key)
|
104
|
+
socket.write("#{base_name}.#{name} #{value} #{time}\n")
|
105
|
+
end
|
106
|
+
|
107
|
+
unless snapshot_keys.empty?
|
108
|
+
snapshot = metric.snapshot
|
109
|
+
snapshot_keys.flatten.each do |key|
|
110
|
+
name = key.to_s.gsub(/^get_/, '')
|
111
|
+
value = snapshot.send(key)
|
112
|
+
socket.write("#{base_name}.#{name} #{value} #{time}\n")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
rescue Errno::EPIPE
|
116
|
+
socket.close
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'metriks/time_tracker'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module Metriks::Reporter
|
5
|
+
class LibratoMetrics
|
6
|
+
attr_accessor :prefix, :source
|
7
|
+
|
8
|
+
def initialize(email, token, options = {})
|
9
|
+
@email = email
|
10
|
+
@token = token
|
11
|
+
|
12
|
+
@prefix = options[:prefix]
|
13
|
+
@source = options[:source]
|
14
|
+
|
15
|
+
@registry = options[:registry] || Metriks::Registry.default
|
16
|
+
@time_tracker = Metriks::TimeTracker.new(options[:interval] || 60)
|
17
|
+
@on_error = options[:on_error] || proc { |ex| }
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
@thread ||= Thread.new do
|
22
|
+
loop do
|
23
|
+
@time_tracker.sleep
|
24
|
+
|
25
|
+
Thread.new do
|
26
|
+
begin
|
27
|
+
write
|
28
|
+
rescue Exception => ex
|
29
|
+
@on_error[ex] rescue nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def stop
|
37
|
+
@thread.kill if @thread
|
38
|
+
@thread = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def restart
|
42
|
+
stop
|
43
|
+
start
|
44
|
+
end
|
45
|
+
|
46
|
+
def write
|
47
|
+
gauges = []
|
48
|
+
@registry.each do |name, metric|
|
49
|
+
gauges << case metric
|
50
|
+
when Metriks::Meter
|
51
|
+
prepare_metric name, metric, [
|
52
|
+
:count, :one_minute_rate, :five_minute_rate,
|
53
|
+
:fifteen_minute_rate, :mean_rate
|
54
|
+
]
|
55
|
+
when Metriks::Counter
|
56
|
+
prepare_metric name, metric, [
|
57
|
+
:count
|
58
|
+
]
|
59
|
+
when Metriks::Gauge
|
60
|
+
prepare_metric name, metric, [
|
61
|
+
:value
|
62
|
+
]
|
63
|
+
when Metriks::UtilizationTimer
|
64
|
+
prepare_metric name, metric, [
|
65
|
+
:count, :one_minute_rate, :five_minute_rate,
|
66
|
+
:fifteen_minute_rate, :mean_rate,
|
67
|
+
:min, :max, :mean, :stddev,
|
68
|
+
:one_minute_utilization, :five_minute_utilization,
|
69
|
+
:fifteen_minute_utilization, :mean_utilization,
|
70
|
+
], [
|
71
|
+
:median, :get_95th_percentile
|
72
|
+
]
|
73
|
+
when Metriks::Timer
|
74
|
+
prepare_metric name, metric, [
|
75
|
+
:count, :one_minute_rate, :five_minute_rate,
|
76
|
+
:fifteen_minute_rate, :mean_rate,
|
77
|
+
:min, :max, :mean, :stddev
|
78
|
+
], [
|
79
|
+
:median, :get_95th_percentile
|
80
|
+
]
|
81
|
+
when Metriks::Histogram
|
82
|
+
prepare_metric name, metric, [
|
83
|
+
:count, :min, :max, :mean, :stddev
|
84
|
+
], [
|
85
|
+
:median, :get_95th_percentile
|
86
|
+
]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
gauges.flatten!
|
91
|
+
|
92
|
+
unless gauges.empty?
|
93
|
+
submit(form_data(gauges.flatten))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def submit(data)
|
98
|
+
url = URI.parse('https://metrics-api.librato.com/v1/metrics')
|
99
|
+
req = Net::HTTP::Post.new(url.path)
|
100
|
+
req.basic_auth(@email, @token)
|
101
|
+
req.set_form_data(data)
|
102
|
+
|
103
|
+
http = Net::HTTP.new(url.host, url.port)
|
104
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
105
|
+
http.use_ssl = true
|
106
|
+
store = OpenSSL::X509::Store.new
|
107
|
+
store.set_default_paths
|
108
|
+
http.cert_store = store
|
109
|
+
|
110
|
+
case res = http.start { |http| http.request(req) }
|
111
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
112
|
+
# OK
|
113
|
+
else
|
114
|
+
res.error!
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def form_data(metrics)
|
119
|
+
data = {}
|
120
|
+
|
121
|
+
gauges = metrics.select { |m| m[:type] == "gauge" }
|
122
|
+
|
123
|
+
gauges.each_with_index do |gauge, idx|
|
124
|
+
gauge.each do |key, value|
|
125
|
+
if value
|
126
|
+
data["gauges[#{idx}][#{key}]"] = value.to_s
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
counters = metrics.select { |m| m[:type] == "counter" }
|
132
|
+
|
133
|
+
counters.each_with_index do |counter, idx|
|
134
|
+
counter.each do |key, value|
|
135
|
+
if value
|
136
|
+
data["counters[#{idx}][#{key}]"] = value.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
data
|
142
|
+
end
|
143
|
+
|
144
|
+
def prepare_metric(base_name, metric, keys, snapshot_keys = [])
|
145
|
+
results = []
|
146
|
+
time = @time_tracker.now_floored
|
147
|
+
|
148
|
+
base_name = base_name.to_s.gsub(/ +/, '_')
|
149
|
+
if @prefix
|
150
|
+
base_name = "#{@prefix}.#{base_name}"
|
151
|
+
end
|
152
|
+
|
153
|
+
keys.flatten.each do |key|
|
154
|
+
name = key.to_s.gsub(/^get_/, '')
|
155
|
+
value = metric.send(key)
|
156
|
+
|
157
|
+
results << {
|
158
|
+
:type => name.to_s == "count" ? "counter" : "gauge",
|
159
|
+
:name => "#{base_name}.#{name}",
|
160
|
+
:source => @source,
|
161
|
+
:measure_time => time,
|
162
|
+
:value => value
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
unless snapshot_keys.empty?
|
167
|
+
snapshot = metric.snapshot
|
168
|
+
snapshot_keys.flatten.each do |key|
|
169
|
+
name = key.to_s.gsub(/^get_/, '')
|
170
|
+
value = snapshot.send(key)
|
171
|
+
|
172
|
+
results << {
|
173
|
+
:type => name.to_s == "count" ? "counter" : "gauge",
|
174
|
+
:name => "#{base_name}.#{name}",
|
175
|
+
:source => @source,
|
176
|
+
:measure_time => time,
|
177
|
+
:value => value
|
178
|
+
}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
results
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'metriks/time_tracker'
|
3
|
+
|
4
|
+
module Metriks::Reporter
|
5
|
+
class Logger
|
6
|
+
attr_accessor :prefix, :log_level, :logger
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@logger = options[:logger] || ::Logger.new(STDOUT)
|
10
|
+
@log_level = options[:log_level] || ::Logger::INFO
|
11
|
+
@prefix = options[:prefix] || 'metriks:'
|
12
|
+
|
13
|
+
@registry = options[:registry] || Metriks::Registry.default
|
14
|
+
@time_tracker = Metriks::TimeTracker.new(options[:interval] || 60)
|
15
|
+
@on_error = options[:on_error] || proc { |ex| }
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
@thread ||= Thread.new do
|
20
|
+
loop do
|
21
|
+
@time_tracker.sleep
|
22
|
+
|
23
|
+
begin
|
24
|
+
write
|
25
|
+
rescue Exception => ex
|
26
|
+
@on_error[ex] rescue nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
@thread.kill if @thread
|
34
|
+
@thread = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def restart
|
38
|
+
stop
|
39
|
+
start
|
40
|
+
end
|
41
|
+
|
42
|
+
def flush
|
43
|
+
if !@last_write || @last_write.min != Time.now.min
|
44
|
+
write
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def write
|
49
|
+
@last_write = Time.now
|
50
|
+
|
51
|
+
@registry.each do |name, metric|
|
52
|
+
case metric
|
53
|
+
when Metriks::Meter
|
54
|
+
log_metric name, 'meter', metric, [
|
55
|
+
:count, :one_minute_rate, :five_minute_rate,
|
56
|
+
:fifteen_minute_rate, :mean_rate
|
57
|
+
]
|
58
|
+
when Metriks::Counter
|
59
|
+
log_metric name, 'counter', metric, [
|
60
|
+
:count
|
61
|
+
]
|
62
|
+
when Metriks::Gauge
|
63
|
+
log_metric name, 'gauge', metric, [
|
64
|
+
:value
|
65
|
+
]
|
66
|
+
when Metriks::UtilizationTimer
|
67
|
+
log_metric name, 'utilization_timer', metric, [
|
68
|
+
:count, :one_minute_rate, :five_minute_rate,
|
69
|
+
:fifteen_minute_rate, :mean_rate,
|
70
|
+
:min, :max, :mean, :stddev,
|
71
|
+
:one_minute_utilization, :five_minute_utilization,
|
72
|
+
:fifteen_minute_utilization, :mean_utilization,
|
73
|
+
], [
|
74
|
+
:median, :get_95th_percentile
|
75
|
+
]
|
76
|
+
when Metriks::Timer
|
77
|
+
log_metric name, 'timer', metric, [
|
78
|
+
:count, :one_minute_rate, :five_minute_rate,
|
79
|
+
:fifteen_minute_rate, :mean_rate,
|
80
|
+
:min, :max, :mean, :stddev
|
81
|
+
], [
|
82
|
+
:median, :get_95th_percentile
|
83
|
+
]
|
84
|
+
when Metriks::Histogram
|
85
|
+
log_metric name, 'histogram', metric, [
|
86
|
+
:count, :min, :max, :mean, :stddev
|
87
|
+
], [
|
88
|
+
:median, :get_95th_percentile
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def extract_from_metric(metric, *keys)
|
95
|
+
keys.flatten.collect do |key|
|
96
|
+
name = key.to_s.gsub(/^get_/, '')
|
97
|
+
[ { name => metric.send(key) } ]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def log_metric(name, type, metric, keys, snapshot_keys = [])
|
102
|
+
message = []
|
103
|
+
|
104
|
+
message << @prefix if @prefix
|
105
|
+
message << { :time => Time.now.to_i }
|
106
|
+
|
107
|
+
message << { :name => name }
|
108
|
+
message << { :type => type }
|
109
|
+
message += extract_from_metric(metric, keys)
|
110
|
+
|
111
|
+
unless snapshot_keys.empty?
|
112
|
+
snapshot = metric.snapshot
|
113
|
+
message += extract_from_metric(snapshot, snapshot_keys)
|
114
|
+
end
|
115
|
+
|
116
|
+
@logger.add(@log_level, format_message(message))
|
117
|
+
end
|
118
|
+
|
119
|
+
def format_message(args)
|
120
|
+
args.map do |arg|
|
121
|
+
case arg
|
122
|
+
when Hash then arg.map { |name, value| "#{name}=#{format_message([value])}" }
|
123
|
+
when Array then format_message(arg)
|
124
|
+
else arg
|
125
|
+
end
|
126
|
+
end.join(' ')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Metriks::Reporter
|
2
|
+
class ProcTitle
|
3
|
+
def initialize(options = {})
|
4
|
+
@rounding = options[:rounding] || 1
|
5
|
+
@prefix = options[:prefix] || $0.dup
|
6
|
+
|
7
|
+
@interval = options[:interval] || 5
|
8
|
+
@on_error = options[:on_error] || proc { |ex| }
|
9
|
+
|
10
|
+
@metrics = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(name, suffix = nil, &block)
|
14
|
+
@metrics << [ name, suffix, block ]
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
@metrics.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
@thread ||= Thread.new do
|
23
|
+
loop do
|
24
|
+
begin
|
25
|
+
unless @metrics.empty?
|
26
|
+
title = generate_title
|
27
|
+
if title && !title.empty?
|
28
|
+
$0 = "#{@prefix} #{title}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
rescue Exception => ex
|
32
|
+
@on_error[ex] rescue nil
|
33
|
+
end
|
34
|
+
sleep @interval
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def stop
|
40
|
+
@thread.kill if @thread
|
41
|
+
@thread = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def restart
|
45
|
+
stop
|
46
|
+
start
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
def generate_title
|
51
|
+
@metrics.collect do |name, suffix, block|
|
52
|
+
val = block.call
|
53
|
+
val = "%.#{@rounding}f" % val if val.is_a?(Float)
|
54
|
+
|
55
|
+
if suffix == '%'
|
56
|
+
"#{name}: #{val}#{suffix}"
|
57
|
+
elsif suffix
|
58
|
+
"#{name}: #{val}/#{suffix}"
|
59
|
+
else
|
60
|
+
"#{name}: #{val}"
|
61
|
+
end
|
62
|
+
end.join(' ')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Metriks::Reporter
|
2
|
+
class Riemann
|
3
|
+
require 'riemann/client'
|
4
|
+
|
5
|
+
attr_accessor :client
|
6
|
+
def initialize(options = {})
|
7
|
+
@client = ::Riemann::Client.new(
|
8
|
+
:host => options[:host],
|
9
|
+
:port => options[:port]
|
10
|
+
)
|
11
|
+
@registry = options[:registry] || Metriks::Registry.default
|
12
|
+
@interval = options[:interval] || 60
|
13
|
+
@on_error = options[:on_error] || proc { |ex| }
|
14
|
+
|
15
|
+
@default_event = options[:default_event] || {}
|
16
|
+
@default_event[:ttl] ||= @interval * 1.5
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
@thread ||= Thread.new do
|
21
|
+
loop do
|
22
|
+
sleep @interval
|
23
|
+
|
24
|
+
Thread.new do
|
25
|
+
begin
|
26
|
+
write
|
27
|
+
rescue Exception => ex
|
28
|
+
@on_error[ex] rescue nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def stop
|
36
|
+
@thread.kill if @thread
|
37
|
+
@thread = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def restart
|
41
|
+
stop
|
42
|
+
start
|
43
|
+
end
|
44
|
+
|
45
|
+
def flush
|
46
|
+
# Is this supposed to take interval into account? --aphyr
|
47
|
+
if !@last_write || @last_write.min != Time.now.min
|
48
|
+
write
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def write
|
53
|
+
@last_write = Time.now
|
54
|
+
|
55
|
+
@registry.each do |name, metric|
|
56
|
+
case metric
|
57
|
+
when Metriks::Meter
|
58
|
+
send_metric name, 'meter', metric, [
|
59
|
+
:count, :one_minute_rate, :five_minute_rate,
|
60
|
+
:fifteen_minute_rate, :mean_rate
|
61
|
+
]
|
62
|
+
when Metriks::Counter
|
63
|
+
send_metric name, 'counter', metric, [
|
64
|
+
:count
|
65
|
+
]
|
66
|
+
when Metriks::Gauge
|
67
|
+
send_metric name, 'gauge', metric, [
|
68
|
+
:value
|
69
|
+
]
|
70
|
+
when Metriks::UtilizationTimer
|
71
|
+
send_metric name, 'utilization_timer', metric, [
|
72
|
+
:count, :one_minute_rate, :five_minute_rate,
|
73
|
+
:fifteen_minute_rate, :mean_rate,
|
74
|
+
:min, :max, :mean, :stddev,
|
75
|
+
:one_minute_utilization, :five_minute_utilization,
|
76
|
+
:fifteen_minute_utilization, :mean_utilization,
|
77
|
+
], [
|
78
|
+
:median, :get_95th_percentile
|
79
|
+
]
|
80
|
+
when Metriks::Timer
|
81
|
+
send_metric name, 'timer', metric, [
|
82
|
+
:count, :one_minute_rate, :five_minute_rate,
|
83
|
+
:fifteen_minute_rate, :mean_rate,
|
84
|
+
:min, :max, :mean, :stddev
|
85
|
+
], [
|
86
|
+
:median, :get_95th_percentile
|
87
|
+
]
|
88
|
+
when Metriks::Histogram
|
89
|
+
send_metric name, 'histogram', metric, [
|
90
|
+
:count, :min, :max, :mean, :stddev
|
91
|
+
], [
|
92
|
+
:median, :get_95th_percentile
|
93
|
+
]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def send_metric(name, type, metric, keys, snapshot_keys = [])
|
99
|
+
keys.each do |key|
|
100
|
+
@client << @default_event.merge(
|
101
|
+
:service => "#{name} #{key}",
|
102
|
+
:metric => metric.send(key),
|
103
|
+
:tags => [type]
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
unless snapshot_keys.empty?
|
108
|
+
snapshot = metric.snapshot
|
109
|
+
snapshot_keys.each do |key|
|
110
|
+
@client << @default_event.merge(
|
111
|
+
:service => "#{name} #{key}",
|
112
|
+
:metric => snapshot.send(key),
|
113
|
+
:tags => [type]
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'atomic'
|
2
|
+
|
3
|
+
module Metriks
|
4
|
+
class SimpleMovingAverage
|
5
|
+
INTERVAL = 5.0
|
6
|
+
SECONDS_PER_MINUTE = 60.0
|
7
|
+
|
8
|
+
ONE_MINUTE = 1
|
9
|
+
FIVE_MINUTES = 5
|
10
|
+
FIFTEEN_MINUTES = 15
|
11
|
+
|
12
|
+
def self.new_m1
|
13
|
+
new(ONE_MINUTE * SECONDS_PER_MINUTE, INTERVAL)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.new_m5
|
17
|
+
new(FIVE_MINUTES * SECONDS_PER_MINUTE, INTERVAL)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.new_m15
|
21
|
+
new(FIFTEEN_MINUTES * SECONDS_PER_MINUTE, INTERVAL)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(duration, interval)
|
25
|
+
@interval = interval
|
26
|
+
@duration = duration
|
27
|
+
|
28
|
+
@values = Array.new((duration / interval).to_i) { Atomic.new(nil) }
|
29
|
+
@index = Atomic.new(0)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear
|
33
|
+
@values.each do |value|
|
34
|
+
value.value = nil
|
35
|
+
end
|
36
|
+
@index.value = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def update(value)
|
40
|
+
@values[@index.value].update { |v| v ? v + value : value }
|
41
|
+
end
|
42
|
+
|
43
|
+
def tick
|
44
|
+
@index.update { |v| v < @values.length - 1 ? v + 1 : 0 }
|
45
|
+
end
|
46
|
+
|
47
|
+
def rate
|
48
|
+
num, count = 0.0, 0.0
|
49
|
+
|
50
|
+
@values.each do |value|
|
51
|
+
if v = value.value
|
52
|
+
num += v
|
53
|
+
count += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
num / count / @interval.to_f
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|