-
Notifications
You must be signed in to change notification settings - Fork 94
/
instrument.rb
131 lines (110 loc) · 3.6 KB
/
instrument.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
require 'socket'
module StatsD
class << self
attr_accessor :host, :port, :mode, :logger, :enabled
end
self.enabled = true
# StatsD.server = 'localhost:1234'
def self.server=(conn)
self.host, port = conn.split(':')
self.port = port.to_i
end
module Instrument
def statsd_measure(method, name)
add_to_method(method, name, :measure) do |old_method, new_method, metric_name, *args|
define_method(new_method) do |*args|
StatsD.measure(metric_name) { send(old_method, *args) }
end
end
end
def statsd_count_success(method, name)
add_to_method(method, name, :count_success) do |old_method, new_method, metric_name|
define_method(new_method) do |*args|
begin
truthiness = result = send(old_method, *args)
rescue
truthiness = false
raise
else
truthiness = (yield(result) rescue false) if block_given?
result
ensure
StatsD.increment("#{metric_name}." + (truthiness == false ? 'failure' : 'success'))
end
end
end
end
def statsd_count_if(method, name)
add_to_method(method, name, :count_if) do |old_method, new_method, metric_name|
define_method(new_method) do |*args|
begin
truthiness = result = send(old_method, *args)
rescue
truthiness = false
raise
else
truthiness = (yield(result) rescue false) if block_given?
result
ensure
StatsD.increment(metric_name) if truthiness
end
end
end
end
def statsd_count(method, name)
add_to_method(method, name, :count) do |old_method, new_method, metric_name|
define_method(new_method) do |*args|
StatsD.increment(metric_name)
send(old_method, *args)
end
end
end
private
def add_to_method(method, name, action, &block)
metric_name = name
method_name_without_statsd = :"#{method}_for_#{action}_on_#{self.name}_without_#{name}"
# raw_ssl_request_for_measure_on_FedEx_without_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
method_name_with_statsd = :"#{method}_for_#{action}_on_#{self.name}_with_#{name}"
# raw_ssl_request_for_measure_on_FedEx_with_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
raise ArgumentError, "already instrumented #{method} for #{self.name}" if method_defined? method_name_without_statsd
raise ArgumentError, "could not find method #{method} for #{self.name}" unless method_defined?(method) || private_method_defined?(method)
alias_method method_name_without_statsd, method
yield method_name_without_statsd, method_name_with_statsd, metric_name
alias_method method, method_name_with_statsd
end
end
# glork:320|ms
def self.measure(key, milli = nil)
result = nil
ms = Benchmark.ms do
result = yield
end if milli.nil?
write(key, ms, :ms)
result
end
# gorets:1|c
def self.increment(key, delta = 1, sample_rate = 1)
write(key, delta, :incr, sample_rate)
end
private
def self.socket
@socket ||= UDPSocket.new
end
def self.write(k,v,op, sample_rate = 1)
return unless enabled
return if sample_rate < 1 && rand > sample_rate
command = "#{k}:#{v}"
case op
when :incr
command << '|c'
when :ms
command << '|ms'
end
command << "|@#{sample_rate}" if sample_rate < 1
if mode == :production
socket.send(command, 0, host, port)
else
logger.info "[StatsD] #{command}"
end
end
end