forked from evanphx/newrelic-redis
/
instrumentation.rb
94 lines (72 loc) · 2.94 KB
/
instrumentation.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
require 'new_relic/agent/method_tracer'
require 'redis'
# Redis instrumentation.
# Originally contributed by Ashley Martens of ngmoco
# Rewritten, reorganized, and repackaged by Evan Phoenix
DependencyDetection.defer do
@name = :redis
depends_on do
defined?(::Redis) and not NewRelic::Control.instance['disable_redis']
end
executes do
NewRelic::Agent.logger.debug 'Installing Redis Instrumentation'
end
executes do
::Redis::Client.class_eval do
# Support older versions of Redis::Client that used the method
# +raw_call_command+.
call_method = ::Redis::Client.new.respond_to?(:call) ? :call : :raw_call_command
def call_with_newrelic_trace(*args, &blk)
if NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction?
total_metric = 'Database/Redis/allWeb'
else
total_metric = 'Database/Redis/allOther'
end
method_name = args[0].is_a?(Array) ? args[0][0] : args[0]
metrics = ["Database/Redis/#{method_name.to_s.upcase}", total_metric]
self.class.trace_execution_scoped(metrics) do
start = Time.now
begin
call_without_newrelic_trace(*args, &blk)
ensure
s = NewRelic::Agent.instance.transaction_sampler
s.notice_nosql(args.inspect, (Time.now - start).to_f) rescue nil
end
end
end
alias_method :call_without_newrelic_trace, call_method
alias_method call_method, :call_with_newrelic_trace
# Older versions of Redis handle pipelining completely differently.
# Don't bother supporting them for now.
#
if public_method_defined? :call_pipelined
def call_pipelined_with_newrelic_trace(commands, *rest)
if NewRelic::Agent::Instrumentation::MetricFrame.recording_web_transaction?
total_metric = 'Database/Redis/allWeb'
else
total_metric = 'Database/Redis/allOther'
end
# Report each command as a metric under pipelined, so the user
# can at least see what all the commands were. This prevents
# metric namespace explosion.
metrics = ["Database/Redis/Pipelined", total_metric]
commands.each do |c|
name = c.kind_of?(Array) ? c[0] : c
metrics << "Database/Redis/Pipelined/#{name.to_s.upcase}"
end
self.class.trace_execution_scoped(metrics) do
start = Time.now
begin
call_pipelined_without_newrelic_trace commands, *rest
ensure
s = NewRelic::Agent.instance.transaction_sampler
s.notice_nosql(commands.inspect, (Time.now - start).to_f) rescue nil
end
end
end
alias_method :call_pipelined_without_newrelic_trace, :call_pipelined
alias_method :call_pipelined, :call_pipelined_with_newrelic_trace
end
end
end
end