oboe 2.4.0.1 → 2.5.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33bba2d752d8947638ef9b22ad51e4b5c947e8a8
4
- data.tar.gz: b4f96bd122d67e99bf6647203b51097c49181e8c
3
+ metadata.gz: 812e394b380905601c8d1fbae241aaedce6231b4
4
+ data.tar.gz: 317bb57275d9eb6b23054d9d2e51dd0c8fbd64d6
5
5
  SHA512:
6
- metadata.gz: 78319d63f067e929ac9e293be2770b9c820bf853ee713f301169a5d905a69a1d0edb8218288d6fa65cf9de749f9487642ad826974faae49fc06af8c5ca118bb1
7
- data.tar.gz: a985bb58d63612bc8c93304ae3c3a5ea25e48a27c4a1856a945d3d919a4a3e556f68959d6fd2d0e8062246abe2d2ac51ba7cf3aa409442e0401e75122ab66cea
6
+ metadata.gz: af3e85508ec28a8a56e05ebed1f1ee6a90c8475ca258c9b9127ee81c8d33226331f4604f856426cb1aca24b90592f7d0ec22e2c6da0df4d47e3e30a0e96f4294
7
+ data.tar.gz: a8744c90e5d216672d774b094deadf1d1ccf031a25de3f262984c10d83593fb5908fdb05527671ee7a53f99b5719c9238f65cea6965c197861815cf482970d86
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.0
3
4
  - 2.0.0
4
5
  - 1.9.3
5
6
  - 1.9.2
@@ -29,4 +30,5 @@ services:
29
30
  - mongodb
30
31
  - memcached
31
32
  - cassandra
33
+ - redis
32
34
 
@@ -1,3 +1,12 @@
1
+ # oboe 2.5.0.7 (02/13/14)
2
+
3
+ * Added new Redis redis-rb gem (>= 3.0.0) instrumentation
4
+ * Fix a SampleSource bitmask high bit issue
5
+ * Expanded __Init reports
6
+ * Fix Ruby standalone returning nil X-Trace headers (1B000000...)
7
+ * Test against Ruby 2.1.0 on TravisCI
8
+ * Fix errant Oboe::Config warning
9
+
1
10
  # oboe 2.4.0.1 (01/12/13)
2
11
 
3
12
  * Report SampleRate & SampleSource per updated SWIG API
data/Gemfile CHANGED
@@ -15,7 +15,7 @@ end
15
15
  group :development do
16
16
  gem 'ruby-debug', :platform => :mri_18
17
17
  gem 'ruby-debug19', :platform => :mri_19, :require => 'ruby-debug'
18
- gem 'debugger', :platform => :mri_20
18
+ gem 'byebug', :platform => :mri_20
19
19
  gem 'perftools.rb', :platform => :mri, :require => 'perftools'
20
20
  gem 'pry'
21
21
  end
@@ -29,4 +29,5 @@ gem 'mongo'
29
29
  gem 'bson_ext' # For Mongo, Yours Truly
30
30
  gem 'moped' unless (RUBY_VERSION =~ /^1.8/) == 0
31
31
  gem 'resque'
32
+ gem 'redis'
32
33
 
data/README.md CHANGED
@@ -76,9 +76,16 @@ The oboe gem has the ability to instrument any arbitrary Ruby application or scr
76
76
  Bundler.require
77
77
 
78
78
  require 'oboe'
79
+
80
+ # Tracing mode can be 'never', 'through' (to follow upstream) or 'always'
81
+ Oboe::Config[:tracing_mode] = 'always'
82
+
83
+ # Number of requests to trace out of each million
84
+ Oboe::Config[:sample_rate] = 1000000
85
+
79
86
  Oboe::Ruby.initialize
80
87
 
81
- From here, you can use the Tracing API to instrument areas of code (see below).
88
+ From here, you can use the Tracing API to instrument areas of code using `Oboe::API.start_trace` (see below). If you prefer to instead dive directly into code, take a look at [this example](https://gist.github.com/pglombardo/8550713) of an instrumented Ruby script.
82
89
 
83
90
  ## Other
84
91
 
@@ -88,13 +95,15 @@ You can send deploy notifications to TraceView and have the events show up on yo
88
95
 
89
96
  ## The Tracing API
90
97
 
91
- You can instrument any arbitrary block of code using the following pattern:
98
+ You can instrument any arbitrary block of code using `Oboe::API.trace`:
92
99
 
93
100
  # layer_name will show up in the TraceView app dashboard
94
101
  layer_name = 'subsystemX'
95
102
 
96
- # report_kvs are a set of information Key/Value pairs that are sent to TraceView along with the performance metrics.
97
- # These KV pairs can report on request, environment or client specific information.
103
+ # report_kvs are a set of information Key/Value pairs that are sent to
104
+ # TraceView dashboard along with the performance metrics. These KV
105
+ # pairs are used to report request, environment and/or client specific
106
+ # information.
98
107
 
99
108
  report_kvs = {}
100
109
  report_kvs[:mykey] = @client.id
@@ -103,7 +112,13 @@ You can instrument any arbitrary block of code using the following pattern:
103
112
  # the block of code to be traced
104
113
  end
105
114
 
106
- Find more details in the TraceView [documentation portal](https://support.tv.appneta.com/support/solutions/articles/86395-ruby-instrumentation-public-api).
115
+ `Oboe::API.trace` is used within the context of a request. It will follow the upstream state of the request being traced. i.e. the block of code will only be traced when the parent request is being traced.
116
+
117
+ This tracing state of a request can also be queried by using `Oboe.tracing?`.
118
+
119
+ If you need to instrument code outside the context of a request (such as a cron job, background job or an arbitrary ruby script), use `Oboe::API.start_trace` instead which will initiate new traces based on configuration and probability (based on the sample rate).
120
+
121
+ Find more details in the [RubyDoc page](http://rdoc.info/gems/oboe/Oboe/API/Tracing) or in [this example](https://gist.github.com/pglombardo/8550713) on how to use the Tracing API in an independent Ruby script.
107
122
 
108
123
  ## Tracing Methods
109
124
 
@@ -14,13 +14,13 @@ OBOE_SAMPLE_RATE_SOURCE_DEFAULT_MISCONFIGURED = 5
14
14
  OBOE_SAMPLE_RATE_SOURCE_OBOE_DEFAULT = 6
15
15
 
16
16
  # Masks for bitwise ops
17
- ZERO_MASK = 0b00000000000000000000000000
17
+ ZERO_MASK = 0b0000000000000000000000000000
18
18
 
19
- SAMPLE_RATE_MASK = 0b00111111111111111111111111
20
- SAMPLE_SOURCE_MASK = 0b11000000000000000000000000
19
+ SAMPLE_RATE_MASK = 0b0000111111111111111111111111
20
+ SAMPLE_SOURCE_MASK = 0b1111000000000000000000000000
21
21
 
22
- ZERO_SAMPLE_RATE_MASK = 0b11000000000000000000000000
23
- ZERO_SAMPLE_SOURCE_MASK = 0b00111111111111111111111111
22
+ ZERO_SAMPLE_RATE_MASK = 0b1111000000000000000000000000
23
+ ZERO_SAMPLE_SOURCE_MASK = 0b0000111111111111111111111111
24
24
 
25
25
  module OboeBase
26
26
  attr_accessor :reporter
@@ -81,7 +81,11 @@ module Oboe_metal < MetalBase
81
81
  Oboe.reporter = Oboe::UdpReporter.new(Oboe::Config[:reporter_host])
82
82
  end
83
83
 
84
- Oboe::API.report_init('rack') unless ["development", "test"].include? ENV['RACK_ENV']
84
+ # Only report __Init from here if we are not instrumenting a framework.
85
+ # Otherwise, frameworks will handle reporting __Init after full initialization
86
+ unless defined?(::Rails) or defined?(::Sinatra) or defined?(::Padrino)
87
+ Oboe::API.report_init('rack') unless ["development", "test"].include? ENV['RACK_ENV']
88
+ end
85
89
 
86
90
  rescue Exception => e
87
91
  $stderr.puts e.message
@@ -21,10 +21,13 @@ begin
21
21
  end
22
22
  rescue LoadError
23
23
  Oboe.loaded = false
24
- $stderr.puts "=============================================================="
25
- $stderr.puts "Missing TraceView libraries. Tracing disabled."
26
- $stderr.puts "See: https://support.tv.appneta.com/solution/articles/137973"
27
- $stderr.puts "=============================================================="
24
+
25
+ unless $ENV['RAILS_GROUP'] == 'assets'
26
+ $stderr.puts "=============================================================="
27
+ $stderr.puts "Missing TraceView libraries. Tracing disabled."
28
+ $stderr.puts "See: https://support.tv.appneta.com/solution/articles/137973"
29
+ $stderr.puts "=============================================================="
30
+ end
28
31
  end
29
32
  end
30
33
 
@@ -28,6 +28,19 @@ module Oboe
28
28
  elsif defined?(::Sinatra)
29
29
  platform_info['Ruby.Sinatra.Version'] = "Sinatra-#{::Sinatra::VERSION}"
30
30
  end
31
+
32
+ # Report the instrumented libraries
33
+ platform_info['Ruby.Cassandra.Version'] = "Cassandra-#{::Cassandra.VERSION}" if defined?(::Cassandra)
34
+ platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli)
35
+ platform_info['Ruby.MemCache.Version'] = "MemCache-#{::MemCache::VERSION}" if defined?(::MemCache)
36
+ platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped)
37
+ platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis)
38
+ platform_info['Ruby.Resque.Version'] = "Resque-#{::Resque::VERSION}" if defined?(::Resque)
39
+
40
+ # Special case since the Mongo 1.x driver doesn't embed the version number in the gem directly
41
+ if ::Gem.loaded_specs.has_key?('mongo')
42
+ platform_info['Ruby.Mongo.Version'] = "Mongo-#{::Gem.loaded_specs['mongo'].version.to_s}"
43
+ end
31
44
 
32
45
  # Report the server in use (if possible)
33
46
  if defined?(::Unicorn)
@@ -44,10 +57,20 @@ module Oboe
44
57
  platform_info['Ruby.AppContainer.Version'] = "Mongrel2-#{::Mongrel2::VERSION}"
45
58
  elsif defined?(::Trinidad)
46
59
  platform_info['Ruby.AppContainer.Version'] = "Trinidad-#{::Trinidad::VERSION}"
60
+ elsif defined?(::WEBrick)
61
+ platform_info['Ruby.AppContainer.Version'] = "WEBrick-#{::WEBrick::VERSION}"
47
62
  else
48
63
  platform_info['Ruby.AppContainer.Version'] = "Unknown"
49
64
  end
50
- rescue
65
+
66
+ # If we couldn't load the c extension correctly, report the error to the dashboard.
67
+ unless Oboe.loaded
68
+ platform_info['Error'] = "Missing TraceView libraries. Tracing disabled."
69
+ end
70
+
71
+ rescue StandardError => e
72
+ Oboe.logger.debug "Error in layerinit: #{e.message}"
73
+ Oboe.logger.debug e.backtrace
51
74
  end
52
75
 
53
76
  start_trace(layer, nil, platform_info) { }
@@ -12,7 +12,7 @@ module Oboe
12
12
  @@config = {}
13
13
 
14
14
  @@instrumentation = [ :cassandra, :dalli, :nethttp, :memcached, :memcache, :mongo,
15
- :moped, :rack, :resque, :action_controller, :action_view,
15
+ :moped, :rack, :redis, :resque, :action_controller, :action_view,
16
16
  :active_record ]
17
17
 
18
18
  ##
@@ -42,6 +42,7 @@ module Oboe
42
42
  Oboe::Config[:mongo][:collect_backtraces] = true
43
43
  Oboe::Config[:moped][:collect_backtraces] = true
44
44
  Oboe::Config[:nethttp][:collect_backtraces] = true
45
+ Oboe::Config[:redis][:collect_backtraces] = false
45
46
  Oboe::Config[:resque][:collect_backtraces] = true
46
47
 
47
48
  # Special instrument specific flags
@@ -56,6 +57,9 @@ module Oboe
56
57
  # Setup an empty host blacklist (see: Oboe::API::Util.blacklisted?)
57
58
  @@config[:blacklist] = []
58
59
 
60
+ # Access Key is empty until loaded from config file or env var
61
+ @@config[:access_key] = ""
62
+
59
63
  # The oboe Ruby client has the ability to sanitize query literals
60
64
  # from SQL statements. By default this is disabled. Enable to
61
65
  # avoid collecting and reporting query literals to TraceView.
@@ -110,6 +110,7 @@ if defined?(::Rails)
110
110
  Oboe::Loading.load_access_key
111
111
  Oboe::Inst.load_instrumentation
112
112
  Oboe::Rails.load_instrumentation
113
+ Oboe::API.report_init('rack') unless ["development", "test"].include? ENV['RACK_ENV']
113
114
  end
114
115
  end
115
116
  end
@@ -125,6 +126,7 @@ if defined?(::Rails)
125
126
  Oboe::Inst.load_instrumentation
126
127
  Oboe::Rails.load_instrumentation
127
128
  Oboe::Rails.include_helpers
129
+ Oboe::API.report_init('rack') unless ["development", "test"].include? ENV['RACK_ENV']
128
130
  end
129
131
  end
130
132
  end
@@ -71,7 +71,7 @@ module Oboe
71
71
  xtrace = e.instance_variable_get(:@xtrace)
72
72
  raise
73
73
  ensure
74
- result[1]['X-Trace'] = xtrace if xtrace
74
+ result[1]['X-Trace'] = xtrace if Oboe::XTrace.valid?(xtrace)
75
75
  return result
76
76
  end
77
77
  end
@@ -0,0 +1,273 @@
1
+ # Copyright (c) 2014 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module Inst
6
+ module Redis
7
+ module Client
8
+ # The operations listed in this constant skip collecting KVKey
9
+ NO_KEY_OPS = [ :keys, :randomkey, :scan, :sdiff, :sdiffstore, :sinter,
10
+ :sinterstore, :smove, :sunion, :sunionstore, :zinterstore,
11
+ :zunionstore, :publish, :select, :eval, :evalsha, :script ]
12
+
13
+ # Instead of a giant switch statement, we use a hash constant to map out what
14
+ # KVs need to be collected for each of the many many Redis operations
15
+ # Hash formatting by undiagnosed OCD
16
+ KV_COLLECT_MAP = {
17
+ :brpoplpush => { :destination => 2 }, :rpoplpush => { :destination => 2 },
18
+ :sdiffstore => { :destination => 1 }, :sinterstore => { :destination => 1 },
19
+ :sunionstore => { :destination => 1 }, :zinterstore => { :destination => 1 },
20
+ :zunionstore => { :destination => 1 }, :publish => { :channel => 1 },
21
+ :incrby => { :increment => 2 }, :incrbyfloat => { :increment => 2 },
22
+ :pexpire => { :milliseconds => 2 }, :pexpireat => { :milliseconds => 2 },
23
+ :expireat => { :timestamp => 2 }, :decrby => { :decrement => 2 },
24
+ :psetex => { :ttl => 2 }, :restore => { :ttl => 2 },
25
+ :setex => { :ttl => 2 }, :setnx => { :ttl => 2 },
26
+ :move => { :db => 2 }, :select => { :db => 1 },
27
+ :lindex => { :index => 2 }, :getset => { :value => 2 },
28
+ :keys => { :pattern => 1 }, :expire => { :seconds => 2 },
29
+ :rename => { :newkey => 2 }, :renamenx => { :newkey => 2 },
30
+ :getbit => { :offset => 2 }, :setbit => { :offset => 2 },
31
+ :setrange => { :offset => 2 }, :evalsha => { :sha => 1 },
32
+ :getrange => { :start => 2, :end => 3 },
33
+ :zrange => { :start => 2, :end => 3 },
34
+ :bitcount => { :start => 2, :stop => 3 },
35
+ :lrange => { :start => 2, :stop => 3 },
36
+ :zrevrange => { :start => 2, :stop => 3 },
37
+ :hincrby => { :field => 2, :increment => 3 },
38
+ :smove => { :source => 1, :destination => 2 },
39
+ :bitop => { :operation => 1, :destkey => 2 },
40
+ :hincrbyfloat => { :field => 2, :increment => 3 },
41
+ :zremrangebyrank => { :start => 2, :stop => 3 },
42
+ }
43
+
44
+ # The following operations don't require any special handling. For these,
45
+ # we only collect KVKey and KVOp
46
+ #
47
+ # :append, :blpop, :brpop, :decr, :del, :dump, :exists,
48
+ # :hgetall, :hkeys, :hlen, :hvals, :hmset, :incr, :linsert,
49
+ # :llen, :lpop, :lpush, :lpushx, :lrem, :lset, :ltrim,
50
+ # :persist, :pttl, :hscan, :rpop, :rpush, :rpushx, :sadd,
51
+ # :scard, :sismember, :smembers, :strlen, :sort, :spop,
52
+ # :srandmember, :srem, :sscan, :ttl, :type, :zadd, :zcard,
53
+ # :zcount, :zincrby, :zrangebyscore, :zrank, :zrem,
54
+ # :zremrangebyscore, :zrevrank, :zrevrangebyscore, :zscore
55
+ #
56
+ # For the operations in NO_KEY_OPS (above) we only collect
57
+ # KVOp (no KVKey)
58
+
59
+ def self.included(klass)
60
+ # We wrap two of the Redis methods to instrument
61
+ # operations
62
+ ::Oboe::Util.method_alias(klass, :call, ::Redis::Client)
63
+ ::Oboe::Util.method_alias(klass, :call_pipeline, ::Redis::Client)
64
+ end
65
+
66
+ # Given any Redis operation command array, this method
67
+ # extracts the Key/Values to report to the TraceView
68
+ # dashboard.
69
+ #
70
+ # @param command [Array] the Redis operation array
71
+ # @param r [Return] the return value from the operation
72
+ # @return [Hash] the Key/Values to report
73
+ def extract_trace_details(command, r)
74
+ kvs = {}
75
+ op = command.first
76
+
77
+ begin
78
+ kvs[:KVOp] = command[0]
79
+ kvs[:RemoteHost] = @options[:host]
80
+
81
+ unless NO_KEY_OPS.include? op or (command[1].is_a?(Array) and command[1].count > 1)
82
+ if command[1].is_a?(Array)
83
+ kvs[:KVKey] = command[1].first
84
+ else
85
+ kvs[:KVKey] = command[1]
86
+ end
87
+ end
88
+
89
+ if KV_COLLECT_MAP[op]
90
+ # Extract KVs from command for this op
91
+ KV_COLLECT_MAP[op].each { |k, v|
92
+ kvs[k] = command[v]
93
+ }
94
+ else
95
+ # This case statement handle special cases not handled
96
+ # by KV_COLLECT_MAP
97
+ case op
98
+ when :set
99
+ if command.count > 3
100
+ options = command[3]
101
+ kvs[:ex] = options[:ex] if options.has_key?(:ex)
102
+ kvs[:px] = options[:px] if options.has_key?(:px)
103
+ kvs[:nx] = options[:nx] if options.has_key?(:nx)
104
+ kvs[:xx] = options[:xx] if options.has_key?(:xx)
105
+ end
106
+
107
+ when :get
108
+ kvs[:KVHit] = r.nil? ? 0 : 1
109
+
110
+ when :hdel, :hexists, :hget, :hset, :hsetnx
111
+ kvs[:field] = command[2] unless command[2].is_a?(Array)
112
+ if op == :hget
113
+ kvs[:KVHit] = r.nil? ? 0 : 1
114
+ end
115
+
116
+ when :eval
117
+ if command[1].length > 1024
118
+ kvs[:Script] = command[1][0..1023] + "(...snip...)"
119
+ else
120
+ kvs[:Script] = command[1]
121
+ end
122
+
123
+ when :script
124
+ kvs[:subcommand] = command[1]
125
+ kvs[:Backtrace] = Oboe::API.backtrace if Oboe::Config[:redis][:collect_backtraces]
126
+ if command[1] == "load"
127
+ if command[1].length > 1024
128
+ kvs[:Script] = command[2][0..1023] + "(...snip...)"
129
+ else
130
+ kvs[:Script] = command[2]
131
+ end
132
+ elsif command[1] == :exists
133
+ if command[2].is_a?(Array)
134
+ kvs[:KVKey] = command[2].inspect
135
+ else
136
+ kvs[:KVKey] = command[2]
137
+ end
138
+ end
139
+
140
+ when :mget
141
+ if command[1].is_a?(Array)
142
+ kvs[:KVKeyCount] = command[1].count
143
+ else
144
+ kvs[:KVKeyCount] = command.count - 1
145
+ end
146
+ values = r.select{ |i| i }
147
+ kvs[:KVHitCount] = values.count
148
+
149
+ when :hmget
150
+ kvs[:KVKeyCount] = command.count - 2
151
+ values = r.select{ |i| i }
152
+ kvs[:KVHitCount] = values.count
153
+
154
+ when :mset, :msetnx
155
+ if command[1].is_a?(Array)
156
+ kvs[:KVKeyCount] = command[1].count / 2
157
+ else
158
+ kvs[:KVKeyCount] = (command.count - 1) / 2
159
+ end
160
+ end # case op
161
+ end # if KV_COLLECT_MAP[op]
162
+
163
+ rescue StandardError => e
164
+ Oboe.logger.debug "Error collecting redis KVs: #{e.message}"
165
+ Oboe.logger.debug e.backtrace.join("\n")
166
+ end
167
+
168
+ kvs
169
+ end
170
+
171
+ # Extracts the Key/Values to report from a pipelined
172
+ # call to the TraceView dashboard.
173
+ #
174
+ # @param pipeline [Redis::Pipeline] the Redis pipeline instance
175
+ # @return [Hash] the Key/Values to report
176
+ def extract_pipeline_details(pipeline)
177
+ kvs = {}
178
+
179
+ begin
180
+ kvs[:RemoteHost] = @options[:host]
181
+ kvs[:Backtrace] = Oboe::API.backtrace if Oboe::Config[:redis][:collect_backtraces]
182
+
183
+ command_count = pipeline.commands.count
184
+ kvs[:KVOpCount] = command_count
185
+
186
+ if pipeline.commands.first == :multi
187
+ kvs[:KVOp] = :multi
188
+ else
189
+ kvs[:KVOp] = :pipeline
190
+ end
191
+
192
+ # Report pipelined operations if the number
193
+ # of ops is reasonable
194
+ if command_count < 12
195
+ ops = []
196
+ pipeline.commands.each do |c|
197
+ ops << c.first
198
+ end
199
+ kvs[:KVOps] = ops.join(", ")
200
+ end
201
+ rescue StandardError => e
202
+ Oboe.logger.debug "[oboe/debug] Error extracting pipelined commands: #{e.message}"
203
+ Oboe.logger.debug e.backtrace
204
+ end
205
+ kvs
206
+ end
207
+
208
+ #
209
+ # The wrapper method for Redis::Client.call. Here
210
+ # (when tracing) we capture KVs to report and pass
211
+ # the call along
212
+ #
213
+ def call_with_oboe(command, &block)
214
+ if Oboe.tracing?
215
+ ::Oboe::API.log_entry('redis', {})
216
+
217
+ begin
218
+ r = call_without_oboe(command, &block)
219
+ report_kvs = extract_trace_details(command, r)
220
+ r
221
+ rescue StandardError => e
222
+ ::Oboe::API.log_exception('redis', e)
223
+ raise
224
+ ensure
225
+ ::Oboe::API.log_exit('redis', report_kvs)
226
+ end
227
+
228
+ else
229
+ call_without_oboe(command, &block)
230
+ end
231
+ end
232
+
233
+ #
234
+ # The wrapper method for Redis::Client.call_pipeline. Here
235
+ # (when tracing) we capture KVs to report and pass the call along
236
+ #
237
+ def call_pipeline_with_oboe(pipeline)
238
+ if Oboe.tracing?
239
+ report_kvs = {}
240
+
241
+ # Fall back to the raw tracing API so we can pass KVs
242
+ # back on exit (a limitation of the Oboe::API.trace
243
+ # block method) This removes the need for an info
244
+ # event to send additonal KVs
245
+ ::Oboe::API.log_entry('redis', {})
246
+
247
+ report_kvs = extract_pipeline_details(pipeline)
248
+
249
+ begin
250
+ call_pipeline_without_oboe(pipeline)
251
+ rescue StandardError => e
252
+ ::Oboe::API.log_exception('redis', e)
253
+ raise
254
+ ensure
255
+ ::Oboe::API.log_exit('redis', report_kvs)
256
+ end
257
+ else
258
+ call_pipeline_without_oboe(pipeline)
259
+ end
260
+ end
261
+
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ if Oboe::Config[:redis][:enabled]
268
+ if defined?(::Redis) and Gem::Version.new(::Redis::VERSION) >= Gem::Version.new('3.0.0')
269
+ Oboe.logger.info "[oboe/loading] Instrumenting redis" if Oboe::Config[:verbose]
270
+ ::Oboe::Util.send_include(::Redis::Client, ::Oboe::Inst::Redis::Client)
271
+ end
272
+ end
273
+