traceview 3.8.1 → 3.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +43 -0
  3. data/.travis.yml +5 -4
  4. data/CHANGELOG.md +114 -114
  5. data/Gemfile +5 -6
  6. data/README.md +3 -3
  7. data/Rakefile +18 -21
  8. data/examples/DNT.md +3 -3
  9. data/examples/carrying_context.rb +26 -31
  10. data/examples/instrumenting_metal_controller.rb +1 -1
  11. data/examples/puma_on_heroku_config.rb +3 -3
  12. data/examples/tracing_async_threads.rb +9 -9
  13. data/examples/tracing_background_jobs.rb +5 -7
  14. data/examples/tracing_forked_processes.rb +13 -14
  15. data/examples/unicorn_on_heroku_config.rb +4 -4
  16. data/gemfiles/rails50.gemfile +1 -1
  17. data/lib/joboe_metal.rb +2 -5
  18. data/lib/oboe/backward_compatibility.rb +3 -5
  19. data/lib/oboe_metal.rb +37 -43
  20. data/lib/traceview/api/logging.rb +1 -2
  21. data/lib/traceview/base.rb +3 -0
  22. data/lib/traceview/config.rb +19 -3
  23. data/lib/traceview/frameworks/rails/inst/action_controller.rb +2 -2
  24. data/lib/traceview/frameworks/rails/inst/{action_controller5_api.rb → action_controller_api.rb} +0 -0
  25. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +2 -2
  26. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils5x.rb +3 -4
  27. data/lib/traceview/inst/httpclient.rb +12 -12
  28. data/lib/traceview/inst/mongo2.rb +7 -8
  29. data/lib/traceview/inst/moped.rb +334 -343
  30. data/lib/traceview/inst/rack.rb +14 -2
  31. data/lib/traceview/inst/redis.rb +104 -110
  32. data/lib/traceview/inst/sequel.rb +43 -37
  33. data/lib/traceview/inst/twitter-cassandra.rb +12 -6
  34. data/lib/traceview/support.rb +34 -32
  35. data/lib/traceview/util.rb +7 -4
  36. data/lib/traceview/version.rb +1 -1
  37. data/test/instrumentation/curb_test.rb +2 -24
  38. data/test/instrumentation/httpclient_test.rb +7 -18
  39. data/test/instrumentation/{cassandra_test.rb → twitter-cassandra_test.rb} +32 -0
  40. data/test/minitest_helper.rb +0 -3
  41. data/test/settings +0 -0
  42. data/test/support/avw_handling_test.rb +13 -23
  43. data/test/support/config_test.rb +1 -1
  44. data/test/support/tracing_mode_test.rb +44 -0
  45. metadata +10 -6
@@ -5,6 +5,19 @@ require 'uri'
5
5
  require 'cgi'
6
6
 
7
7
  module TraceView
8
+ ##
9
+ # TraceView::Rack
10
+ #
11
+ # The TraceView::Rack middleware used to sample a subset of incoming
12
+ # requests for instrumentation and reporting. Tracing context can
13
+ # be received here (via the X-Trace HTTP header) or initiated here
14
+ # based on configured tracing mode.
15
+ #
16
+ # After the rack layer passes on to the following layers (Rails, Sinatra,
17
+ # Padrino, Grape), then the instrumentation downstream will
18
+ # automatically detect whether this is a sampled request or not
19
+ # and act accordingly. (to instrument or not)
20
+ #
8
21
  class Rack
9
22
  attr_reader :app
10
23
 
@@ -82,7 +95,7 @@ module TraceView
82
95
  # if so and don't clear context on log_end (see traceview/api/logging.rb)
83
96
  TraceView.has_incoming_context = TraceView.tracing?
84
97
  TraceView.has_xtrace_header = xtrace_header
85
- TraceView.is_continued_trace = TraceView.has_incoming_context or TraceView.has_xtrace_header
98
+ TraceView.is_continued_trace = TraceView.has_incoming_context || TraceView.has_xtrace_header
86
99
 
87
100
  TraceView::API.log_start(:rack, xtrace_header, report_kvs)
88
101
 
@@ -120,4 +133,3 @@ module TraceView
120
133
  end
121
134
  end
122
135
  end
123
-
@@ -8,7 +8,7 @@ module TraceView
8
8
  # The operations listed in this constant skip collecting KVKey
9
9
  NO_KEY_OPS = [:keys, :randomkey, :scan, :sdiff, :sdiffstore, :sinter,
10
10
  :sinterstore, :smove, :sunion, :sunionstore, :zinterstore,
11
- :zunionstore, :publish, :select, :eval, :evalsha, :script]
11
+ :zunionstore, :publish, :select, :eval, :evalsha, :script].freeze
12
12
 
13
13
  # Instead of a giant switch statement, we use a hash constant to map out what
14
14
  # KVs need to be collected for each of the many many Redis operations
@@ -39,7 +39,7 @@ module TraceView
39
39
  :bitop => { :operation => 1, :destkey => 2 },
40
40
  :hincrbyfloat => { :field => 2, :increment => 3 },
41
41
  :zremrangebyrank => { :start => 2, :stop => 3 }
42
- }
42
+ }.freeze
43
43
 
44
44
  # The following operations don't require any special handling. For these,
45
45
  # we only collect KVKey and KVOp
@@ -74,108 +74,105 @@ module TraceView
74
74
  kvs = {}
75
75
  op = command.first
76
76
 
77
- begin
78
- kvs[:KVOp] = command[0]
79
- kvs[:RemoteHost] = @options[:host]
77
+ kvs[:KVOp] = command[0]
78
+ kvs[:RemoteHost] = @options[:host]
80
79
 
81
- unless NO_KEY_OPS.include?(op) || (command[1].is_a?(Array) && 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
80
+ unless NO_KEY_OPS.include?(op) || (command[1].is_a?(Array) && command[1].count > 1)
81
+ if command[1].is_a?(Array)
82
+ kvs[:KVKey] = command[1].first
83
+ else
84
+ kvs[:KVKey] = command[1]
87
85
  end
86
+ end
88
87
 
89
- if KV_COLLECT_MAP[op]
90
- # Extract KVs from command for this op
91
- KV_COLLECT_MAP[op].each { |k, v| kvs[k] = command[v] }
92
- else
93
- # This case statement handle special cases not handled
94
- # by KV_COLLECT_MAP
95
- case op
96
- when :set
97
- if command.count > 3
98
- if command[3].is_a?(Hash)
99
- options = command[3]
100
- kvs[:ex] = options[:ex] if options.key?(:ex)
101
- kvs[:px] = options[:px] if options.key?(:px)
102
- kvs[:nx] = options[:nx] if options.key?(:nx)
103
- kvs[:xx] = options[:xx] if options.key?(:xx)
104
- else
105
- options = command[3..-1]
106
- until (opts = options.shift(2)).empty?
107
- case opts[0]
108
- when 'EX' then; kvs[:ex] = opts[1]
109
- when 'PX' then; kvs[:px] = opts[1]
110
- when 'NX' then; kvs[:nx] = opts[1]
111
- when 'XX' then; kvs[:xx] = opts[1]
112
- end
88
+ if KV_COLLECT_MAP[op]
89
+ # Extract KVs from command for this op
90
+ KV_COLLECT_MAP[op].each { |k, v| kvs[k] = command[v] }
91
+ else
92
+ # This case statement handle special cases not handled
93
+ # by KV_COLLECT_MAP
94
+ case op
95
+ when :set
96
+ if command.count > 3
97
+ if command[3].is_a?(Hash)
98
+ options = command[3]
99
+ kvs[:ex] = options[:ex] if options.key?(:ex)
100
+ kvs[:px] = options[:px] if options.key?(:px)
101
+ kvs[:nx] = options[:nx] if options.key?(:nx)
102
+ kvs[:xx] = options[:xx] if options.key?(:xx)
103
+ else
104
+ options = command[3..-1]
105
+ until (opts = options.shift(2)).empty?
106
+ case opts[0]
107
+ when 'EX' then; kvs[:ex] = opts[1]
108
+ when 'PX' then; kvs[:px] = opts[1]
109
+ when 'NX' then; kvs[:nx] = opts[1]
110
+ when 'XX' then; kvs[:xx] = opts[1]
113
111
  end
114
112
  end
115
113
  end
114
+ end
115
+
116
+ when :get
117
+ kvs[:KVHit] = r.nil? ? 0 : 1
116
118
 
117
- when :get
119
+ when :hdel, :hexists, :hget, :hset, :hsetnx
120
+ kvs[:field] = command[2] unless command[2].is_a?(Array)
121
+ if op == :hget
118
122
  kvs[:KVHit] = r.nil? ? 0 : 1
123
+ end
119
124
 
120
- when :hdel, :hexists, :hget, :hset, :hsetnx
121
- kvs[:field] = command[2] unless command[2].is_a?(Array)
122
- if op == :hget
123
- kvs[:KVHit] = r.nil? ? 0 : 1
124
- end
125
+ when :eval
126
+ if command[1].length > 1024
127
+ kvs[:Script] = command[1][0..1023] + '(...snip...)'
128
+ else
129
+ kvs[:Script] = command[1]
130
+ end
125
131
 
126
- when :eval
132
+ when :script
133
+ kvs[:subcommand] = command[1]
134
+ kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:redis][:collect_backtraces]
135
+ if command[1] == 'load'
127
136
  if command[1].length > 1024
128
- kvs[:Script] = command[1][0..1023] + '(...snip...)'
137
+ kvs[:Script] = command[2][0..1023] + '(...snip...)'
129
138
  else
130
- kvs[:Script] = command[1]
139
+ kvs[:Script] = command[2]
131
140
  end
132
-
133
- when :script
134
- kvs[:subcommand] = command[1]
135
- kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:redis][:collect_backtraces]
136
- if command[1] == 'load'
137
- if command[1].length > 1024
138
- kvs[:Script] = command[2][0..1023] + '(...snip...)'
139
- else
140
- kvs[:Script] = command[2]
141
- end
142
- elsif command[1] == :exists
143
- if command[2].is_a?(Array)
144
- kvs[:KVKey] = command[2].inspect
145
- else
146
- kvs[:KVKey] = command[2]
147
- end
148
- end
149
-
150
- when :mget
151
- if command[1].is_a?(Array)
152
- kvs[:KVKeyCount] = command[1].count
141
+ elsif command[1] == :exists
142
+ if command[2].is_a?(Array)
143
+ kvs[:KVKey] = command[2].inspect
153
144
  else
154
- kvs[:KVKeyCount] = command.count - 1
145
+ kvs[:KVKey] = command[2]
155
146
  end
156
- values = r.select { |i| i }
157
- kvs[:KVHitCount] = values.count
158
-
159
- when :hmget
160
- kvs[:KVKeyCount] = command.count - 2
161
- values = r.select { |i| i }
162
- kvs[:KVHitCount] = values.count
147
+ end
163
148
 
164
- when :mset, :msetnx
165
- if command[1].is_a?(Array)
166
- kvs[:KVKeyCount] = command[1].count / 2
167
- else
168
- kvs[:KVKeyCount] = (command.count - 1) / 2
169
- end
170
- end # case op
171
- end # if KV_COLLECT_MAP[op]
149
+ when :mget
150
+ if command[1].is_a?(Array)
151
+ kvs[:KVKeyCount] = command[1].count
152
+ else
153
+ kvs[:KVKeyCount] = command.count - 1
154
+ end
155
+ values = r.select { |i| i }
156
+ kvs[:KVHitCount] = values.count
172
157
 
173
- rescue StandardError => e
174
- TraceView.logger.debug "Error collecting redis KVs: #{e.message}"
175
- TraceView.logger.debug e.backtrace.join('\n')
176
- end
158
+ when :hmget
159
+ kvs[:KVKeyCount] = command.count - 2
160
+ values = r.select { |i| i }
161
+ kvs[:KVHitCount] = values.count
177
162
 
178
- kvs
163
+ when :mset, :msetnx
164
+ if command[1].is_a?(Array)
165
+ kvs[:KVKeyCount] = command[1].count / 2
166
+ else
167
+ kvs[:KVKeyCount] = (command.count - 1) / 2
168
+ end
169
+ end # case op
170
+ end # if KV_COLLECT_MAP[op]
171
+ rescue StandardError => e
172
+ TraceView.logger.debug "Error collecting redis KVs: #{e.message}"
173
+ TraceView.logger.debug e.backtrace.join('\n')
174
+ ensure
175
+ return kvs
179
176
  end
180
177
 
181
178
  # Extracts the Key/Values to report from a pipelined
@@ -186,33 +183,32 @@ module TraceView
186
183
  def extract_pipeline_details(pipeline)
187
184
  kvs = {}
188
185
 
189
- begin
190
- kvs[:RemoteHost] = @options[:host]
191
- kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:redis][:collect_backtraces]
186
+ kvs[:RemoteHost] = @options[:host]
187
+ kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:redis][:collect_backtraces]
192
188
 
193
- command_count = pipeline.commands.count
194
- kvs[:KVOpCount] = command_count
189
+ command_count = pipeline.commands.count
190
+ kvs[:KVOpCount] = command_count
195
191
 
196
- if pipeline.commands.first == :multi
197
- kvs[:KVOp] = :multi
198
- else
199
- kvs[:KVOp] = :pipeline
200
- end
192
+ kvs[:KVOp] = if pipeline.commands.first == :multi
193
+ :multi
194
+ else
195
+ :pipeline
196
+ end
201
197
 
202
- # Report pipelined operations if the number
203
- # of ops is reasonable
204
- if command_count < 12
205
- ops = []
206
- pipeline.commands.each do |c|
207
- ops << c.first
208
- end
209
- kvs[:KVOps] = ops.join(', ')
198
+ # Report pipelined operations if the number
199
+ # of ops is reasonable
200
+ if command_count < 12
201
+ ops = []
202
+ pipeline.commands.each do |c|
203
+ ops << c.first
210
204
  end
211
- rescue StandardError => e
212
- TraceView.logger.debug "[traceview/debug] Error extracting pipelined commands: #{e.message}"
213
- TraceView.logger.debug e.backtrace
205
+ kvs[:KVOps] = ops.join(', ')
214
206
  end
215
- kvs
207
+ rescue StandardError => e
208
+ TraceView.logger.debug "[traceview/debug] Error extracting pipelined commands: #{e.message}"
209
+ TraceView.logger.debug e.backtrace
210
+ ensure
211
+ return kvs
216
212
  end
217
213
 
218
214
  #
@@ -266,7 +262,6 @@ module TraceView
266
262
  call_pipeline_without_traceview(pipeline)
267
263
  end
268
264
  end
269
-
270
265
  end
271
266
  end
272
267
  end
@@ -278,4 +273,3 @@ if TraceView::Config[:redis][:enabled]
278
273
  ::TraceView::Util.send_include(::Redis::Client, ::TraceView::Inst::Redis::Client)
279
274
  end
280
275
  end
281
-
@@ -3,7 +3,19 @@
3
3
 
4
4
  module TraceView
5
5
  module Inst
6
+ ##
7
+ # TraceView::Inst::Sequel
8
+ #
9
+ # The common (shared) methods used by the TraceView Sequel instrumentation
10
+ # across multiple modules/classes.
11
+ #
6
12
  module Sequel
13
+ ##
14
+ # extract_trace_details
15
+ #
16
+ # Given SQL and the options hash, this method extracts the interesting
17
+ # bits for reporting to the TraceView dashboard.
18
+ #
7
19
  def extract_trace_details(sql, opts)
8
20
  kvs = {}
9
21
 
@@ -17,7 +29,7 @@ module TraceView
17
29
  else
18
30
  # Report raw SQL and any binds if they exist
19
31
  kvs[:Query] = sql.to_s
20
- kvs[:QueryArgs] = opts[:arguments] if opts.is_a?(Hash) and opts.key?(:arguments)
32
+ kvs[:QueryArgs] = opts[:arguments] if opts.is_a?(Hash) && opts.key?(:arguments)
21
33
  end
22
34
  kvs[:IsPreparedStatement] = true if sql.is_a?(Symbol)
23
35
 
@@ -40,35 +52,43 @@ module TraceView
40
52
  ensure
41
53
  return kvs
42
54
  end
43
- end
44
-
45
- module SequelDatabase
46
- def self.included(klass)
47
- ::TraceView::Util.method_alias(klass, :run, ::Sequel::Database)
48
- ::TraceView::Util.method_alias(klass, :execute_ddl, ::Sequel::Database)
49
- ::TraceView::Util.method_alias(klass, :execute_dui, ::Sequel::Database)
50
- ::TraceView::Util.method_alias(klass, :execute_insert, ::Sequel::Database)
51
- end
52
55
 
53
- def run_with_traceview(sql, opts=::Sequel::OPTS)
56
+ ##
57
+ # exec_with_traceview
58
+ #
59
+ # This method wraps and routes the call to the specified
60
+ # original method call
61
+ #
62
+ def exec_with_traceview(method, sql, opts = ::Sequel::OPTS, &block)
54
63
  kvs = extract_trace_details(sql, opts)
55
64
 
56
65
  TraceView::API.log_entry(:sequel, kvs)
57
66
 
58
- run_without_traceview(sql, opts)
67
+ send(method, sql, opts, &block)
59
68
  rescue => e
60
69
  TraceView::API.log_exception(:sequel, e)
61
70
  raise e
62
71
  ensure
63
72
  TraceView::API.log_exit(:sequel)
64
73
  end
74
+ end
75
+
76
+ module SequelDatabase
77
+ include TraceView::Inst::Sequel
65
78
 
66
- def exec_with_traceview(method, sql, opts=::Sequel::OPTS, &block)
79
+ def self.included(klass)
80
+ ::TraceView::Util.method_alias(klass, :run, ::Sequel::Database)
81
+ ::TraceView::Util.method_alias(klass, :execute_ddl, ::Sequel::Database)
82
+ ::TraceView::Util.method_alias(klass, :execute_dui, ::Sequel::Database)
83
+ ::TraceView::Util.method_alias(klass, :execute_insert, ::Sequel::Database)
84
+ end
85
+
86
+ def run_with_traceview(sql, opts = ::Sequel::OPTS)
67
87
  kvs = extract_trace_details(sql, opts)
68
88
 
69
89
  TraceView::API.log_entry(:sequel, kvs)
70
90
 
71
- send(method, sql, opts, &block)
91
+ run_without_traceview(sql, opts)
72
92
  rescue => e
73
93
  TraceView::API.log_exception(:sequel, e)
74
94
  raise e
@@ -76,7 +96,7 @@ module TraceView
76
96
  TraceView::API.log_exit(:sequel)
77
97
  end
78
98
 
79
- def execute_ddl_with_traceview(sql, opts=::Sequel::OPTS, &block)
99
+ def execute_ddl_with_traceview(sql, opts = ::Sequel::OPTS, &block)
80
100
  # If we're already tracing a sequel operation, then this call likely came
81
101
  # from Sequel::Dataset. In this case, just pass it on.
82
102
  return execute_ddl_without_traceview(sql, opts, &block) if TraceView.tracing_layer?(:sequel)
@@ -84,7 +104,7 @@ module TraceView
84
104
  exec_with_traceview(:execute_ddl_without_traceview, sql, opts, &block)
85
105
  end
86
106
 
87
- def execute_dui_with_traceview(sql, opts=::Sequel::OPTS, &block)
107
+ def execute_dui_with_traceview(sql, opts = ::Sequel::OPTS, &block)
88
108
  # If we're already tracing a sequel operation, then this call likely came
89
109
  # from Sequel::Dataset. In this case, just pass it on.
90
110
  return execute_dui_without_traceview(sql, opts, &block) if TraceView.tracing_layer?(:sequel)
@@ -92,7 +112,7 @@ module TraceView
92
112
  exec_with_traceview(:execute_dui_without_traceview, sql, opts, &block)
93
113
  end
94
114
 
95
- def execute_insert_with_traceview(sql, opts=::Sequel::OPTS, &block)
115
+ def execute_insert_with_traceview(sql, opts = ::Sequel::OPTS, &block)
96
116
  # If we're already tracing a sequel operation, then this call likely came
97
117
  # from Sequel::Dataset. In this case, just pass it on.
98
118
  return execute_insert_without_traceview(sql, opts, &block) if TraceView.tracing_layer?(:sequel)
@@ -102,6 +122,7 @@ module TraceView
102
122
  end # module SequelDatabase
103
123
 
104
124
  module SequelDataset
125
+ include TraceView::Inst::Sequel
105
126
 
106
127
  def self.included(klass)
107
128
  ::TraceView::Util.method_alias(klass, :execute, ::Sequel::Dataset)
@@ -110,32 +131,19 @@ module TraceView
110
131
  ::TraceView::Util.method_alias(klass, :execute_insert, ::Sequel::Dataset)
111
132
  end
112
133
 
113
- def exec_with_traceview(method, sql, opts=::Sequel::OPTS, &block)
114
- kvs = extract_trace_details(sql, opts)
115
-
116
- TraceView::API.log_entry(:sequel, kvs)
117
-
118
- send(method, sql, opts, &block)
119
- rescue => e
120
- TraceView::API.log_exception(:sequel, e)
121
- raise e
122
- ensure
123
- TraceView::API.log_exit(:sequel)
124
- end
125
-
126
- def execute_with_traceview(sql, opts=::Sequel::OPTS, &block)
134
+ def execute_with_traceview(sql, opts = ::Sequel::OPTS, &block)
127
135
  exec_with_traceview(:execute_without_traceview, sql, opts, &block)
128
136
  end
129
137
 
130
- def execute_ddl_with_traceview(sql, opts=::Sequel::OPTS, &block)
138
+ def execute_ddl_with_traceview(sql, opts = ::Sequel::OPTS, &block)
131
139
  exec_with_traceview(:execute_ddl_without_traceview, sql, opts, &block)
132
140
  end
133
141
 
134
- def execute_dui_with_traceview(sql, opts=::Sequel::OPTS, &block)
142
+ def execute_dui_with_traceview(sql, opts = ::Sequel::OPTS, &block)
135
143
  exec_with_traceview(:execute_dui_without_traceview, sql, opts, &block)
136
144
  end
137
145
 
138
- def execute_insert_with_traceview(sql, opts=::Sequel::OPTS, &block)
146
+ def execute_insert_with_traceview(sql, opts = ::Sequel::OPTS, &block)
139
147
  exec_with_traceview(:execute_insert_without_traceview, sql, opts, &block)
140
148
  end
141
149
 
@@ -144,7 +152,7 @@ module TraceView
144
152
  end # module TraceView
145
153
 
146
154
  if TraceView::Config[:sequel][:enabled]
147
- if defined?(::Sequel) && ::Sequel::VERSION < "4.0.0"
155
+ if defined?(::Sequel) && ::Sequel::VERSION < '4.0.0'
148
156
  # For versions before 4.0.0, Sequel::OPTS wasn't defined.
149
157
  # Define it as an empty hash for backwards compatibility.
150
158
  module ::Sequel
@@ -154,9 +162,7 @@ if TraceView::Config[:sequel][:enabled]
154
162
 
155
163
  if defined?(::Sequel)
156
164
  TraceView.logger.info '[traceview/loading] Instrumenting sequel' if TraceView::Config[:verbose]
157
- ::TraceView::Util.send_include(::Sequel::Database, ::TraceView::Inst::Sequel)
158
165
  ::TraceView::Util.send_include(::Sequel::Database, ::TraceView::Inst::SequelDatabase)
159
- ::TraceView::Util.send_include(::Sequel::Dataset, ::TraceView::Inst::Sequel)
160
166
  ::TraceView::Util.send_include(::Sequel::Dataset, ::TraceView::Inst::SequelDataset)
161
167
  end
162
168
  end