oboe 2.7.16.1 → 2.7.17.1

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: 6c0f88a5d2d28655a722be6a2ba69099591ad8bf
4
- data.tar.gz: 1888338f8cb2117b4d8dfed90ecbd8c95fcab1f0
3
+ metadata.gz: 529cd6cc37ff59074153804ee8b1bf7a127adf1a
4
+ data.tar.gz: 59762f6323ed39ff1ae52085eea67711f100bff4
5
5
  SHA512:
6
- metadata.gz: 1e2c76ace3fcd637732dbeeade679c87d29686b5a3196a5b57c5ea6237a2b66f1b3c2cd9e15c234063d1486a07ef5e2b68a5997a13eb1ae1dfe85027144867c2
7
- data.tar.gz: 01ad1eb9dacb3a0917d4052e10218cb7b0673f423784bf9878e2e945c81e774cc8737127d87bc7297c19a02a5bc50db3134e123519b04a176c65246bdd9a8b3a
6
+ metadata.gz: c37e42ca48f51b286f7466b59da01c68ca349e5c735a13be276f3327ccaba6f09c7149ea84e37d196d42be48513ac9af33bb04c192249d70846f57ede6bd9a86
7
+ data.tar.gz: aee307bcbf113c6b223b6c575b410b610448fc66bbaed9a9f6467f6e74d1f8873b990125edf8b58ea25c70c05609654fd9ca71249eabf9118cdbc75bd8f15d06
@@ -4,6 +4,18 @@ https://github.com/appneta/oboe-ruby/releases
4
4
 
5
5
  Dates in this file are in the format MM/DD/YYYY.
6
6
 
7
+ # oboe 2.7.17.1
8
+
9
+ This patch release includes:
10
+
11
+ * New config option to optionally not report URL query parameters: #116
12
+ * New HTTPClient instrumentation: #115
13
+
14
+ Pushed to Rubygems:
15
+
16
+ https://rubygems.org/gems/oboe/versions/2.7.17.1
17
+ https://rubygems.org/gems/oboe/versions/2.7.17.1-java
18
+
7
19
  # oboe 2.7.16.1
8
20
 
9
21
  This patch release includes:
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source 'https://rubygems.org'
3
3
  group :development, :test do
4
4
  gem 'minitest', "5.5.1"
5
5
  gem 'minitest-reporters'
6
+ gem 'minitest-debugger', :require => false
6
7
  gem 'rack-test'
7
8
  gem 'puma'
8
9
  if RUBY_VERSION < '1.9.3'
@@ -38,6 +39,7 @@ gem 'mongo'
38
39
  gem 'resque'
39
40
  gem 'redis'
40
41
  gem 'faraday'
42
+ gem 'httpclient'
41
43
  gem 'excon'
42
44
  gem 'typhoeus'
43
45
  gem 'sequel'
@@ -13,9 +13,13 @@ module Oboe
13
13
 
14
14
  @@instrumentation = [:action_controller, :action_view, :active_record,
15
15
  :cassandra, :dalli, :em_http_request, :excon, :faraday,
16
- :grape, :nethttp, :memcached, :memcache, :mongo,
16
+ :grape, :httpclient, :nethttp, :memcached, :memcache, :mongo,
17
17
  :moped, :rack, :redis, :resque, :rest_client, :sequel,
18
18
  :typhoeus]
19
+
20
+ # Subgrouping of instrumentation
21
+ @@http_clients = [:excon, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
22
+
19
23
  ##
20
24
  # Return the raw nested hash.
21
25
  #
@@ -41,10 +45,11 @@ module Oboe
41
45
  Oboe::Config[:action_view][:collect_backtraces] = true
42
46
  Oboe::Config[:cassandra][:collect_backtraces] = true
43
47
  Oboe::Config[:dalli][:collect_backtraces] = false
44
- Oboe::Config[:faraday][:collect_backtraces] = false
45
- Oboe::Config[:grape][:collect_backtraces] = true
46
48
  Oboe::Config[:em_http_request][:collect_backtraces] = false
47
49
  Oboe::Config[:excon][:collect_backtraces] = true
50
+ Oboe::Config[:faraday][:collect_backtraces] = false
51
+ Oboe::Config[:grape][:collect_backtraces] = true
52
+ Oboe::Config[:httpclient][:collect_backtraces] = true
48
53
  Oboe::Config[:memcache][:collect_backtraces] = false
49
54
  Oboe::Config[:memcached][:collect_backtraces] = false
50
55
  Oboe::Config[:mongo][:collect_backtraces] = true
@@ -71,6 +76,33 @@ module Oboe
71
76
  # Access Key is empty until loaded from config file or env var
72
77
  @@config[:access_key] = ''
73
78
 
79
+ # Logging of outgoing HTTP query args
80
+ #
81
+ # This optionally disables the logging of query args of outgoing
82
+ # HTTP clients such as Net::HTTP, excon, typhoeus and others.
83
+ #
84
+ # This flag is global to all HTTP client instrumentation.
85
+ #
86
+ # To configure this on a per instrumentation basis, set this
87
+ # option to true and instead disable the instrumenstation specific
88
+ # option <tt>log_args</tt>:
89
+ #
90
+ # Oboe::Config[:nethttp][:log_args] = false
91
+ # Oboe::Config[:excon][:log_args] = false
92
+ # Oboe::Config[:typhoeus][:log_args] = true
93
+ #
94
+ @@config[:include_url_query_params] = true
95
+
96
+ # Logging of incoming HTTP query args
97
+ #
98
+ # This optionally disables the logging of incoming URL request
99
+ # query args.
100
+ #
101
+ # This flag is global and currently only affects the Rack
102
+ # instrumentation which reports incoming request URLs and
103
+ # query args by default.
104
+ @@config[:include_remote_url_params] = true
105
+
74
106
  # The oboe Ruby client has the ability to sanitize query literals
75
107
  # from SQL statements. By default this is disabled. Enable to
76
108
  # avoid collecting and reporting query literals to TraceView.
@@ -110,6 +142,7 @@ module Oboe
110
142
  # report all raised exception regardless.
111
143
  @@config[:report_rescued_errors] = false
112
144
 
145
+ # Environment support for OpenShift.
113
146
  if ENV.key?('OPENSHIFT_TRACEVIEW_TLYZER_IP')
114
147
  # We're running on OpenShift
115
148
  @@config[:tracing_mode] = 'always'
@@ -145,9 +178,8 @@ module Oboe
145
178
  if key == :sampling_rate
146
179
  Oboe.logger.warn 'sampling_rate is not a supported setting for Oboe::Config. ' \
147
180
  'Please use :sample_rate.'
148
- end
149
181
 
150
- if key == :sample_rate
182
+ elsif key == :sample_rate
151
183
  unless value.is_a?(Integer) || value.is_a?(Float)
152
184
  fail 'oboe :sample_rate must be a number between 1 and 1000000 (1m)'
153
185
  end
@@ -159,8 +191,19 @@ module Oboe
159
191
 
160
192
  # Assure value is an integer
161
193
  @@config[key.to_sym] = value.to_i
162
-
163
194
  Oboe.set_sample_rate(value) if Oboe.loaded
195
+
196
+ elsif key == :include_url_query_params
197
+ # Obey the global flag and update all of the per instrumentation
198
+ # <tt>:log_args</tt> values.
199
+ @@http_clients.each do |i|
200
+ @@config[i][:log_args] = value
201
+ end
202
+
203
+ elsif key == :include_remote_url_params
204
+ # Obey the global flag and update all of the per instrumentation
205
+ # <tt>:log_args</tt> values.
206
+ @@config[:rack][:log_args] = value
164
207
  end
165
208
 
166
209
  # Update liboboe if updating :tracing_mode
@@ -169,18 +212,24 @@ module Oboe
169
212
  end
170
213
  end
171
214
 
172
- def self.instrumentation_list
173
- @@instrumentation
174
- end
175
-
176
215
  def self.method_missing(sym, *args)
216
+ class_var_name = "@@#{sym}"
217
+
177
218
  if sym.to_s =~ /(.+)=$/
178
219
  self[$1] = args.first
179
220
  else
180
- unless @@config.key?(sym)
181
- Oboe.logger.warn "[oboe/warn] Unknown method call on Oboe::Config: #{sym}"
221
+ # Try part of the @@config hash first
222
+ if @@config.key?(sym)
223
+ self[sym]
224
+
225
+ # Then try as a class variable
226
+ elsif self.class_variable_defined?(class_var_name.to_sym)
227
+ self.class_eval(class_var_name)
228
+
229
+ # Congrats - You've won a brand new nil...
230
+ else
231
+ nil
182
232
  end
183
- self[sym]
184
233
  end
185
234
  end
186
235
  end
@@ -15,7 +15,8 @@ module Oboe
15
15
  kvs['RemoteProtocol'] = ::Oboe::Util.upcase(@data[:scheme])
16
16
  kvs['RemoteHost'] = @data[:host]
17
17
 
18
- if @data[:query] && @data[:query].length
18
+ # Conditionally log query args
19
+ if Oboe::Config[:excon][:log_args] && (@data[:query] && @data[:query].length)
19
20
  kvs['ServiceArg'] = @data[:path] + '?' + @data[:query]
20
21
  else
21
22
  kvs['ServiceArg'] = @data[:path]
@@ -29,7 +29,14 @@ if Oboe::Config[:nethttp][:enabled]
29
29
  opts['IsService'] = 1
30
30
  opts['RemoteProtocol'] = use_ssl? ? 'HTTPS' : 'HTTP'
31
31
  opts['RemoteHost'] = addr_port
32
- opts['ServiceArg'] = req.path
32
+
33
+ # Conditionally log query params
34
+ if Oboe::Config[:nethttp][:log_args]
35
+ opts['ServiceArg'] = req.path
36
+ else
37
+ opts['ServiceArg'] = req.path.split('?').first
38
+ end
39
+
33
40
  opts['HTTPMethod'] = req.method
34
41
  opts['Blacklisted'] = true if blacklisted
35
42
  opts['Backtrace'] = Oboe::API.backtrace if Oboe::Config[:nethttp][:collect_backtraces]
@@ -0,0 +1,173 @@
1
+ # Copyright (c) 2015 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module Inst
6
+ module HTTPClient
7
+ def self.included(klass)
8
+ ::Oboe::Util.method_alias(klass, :do_request, ::HTTPClient)
9
+ ::Oboe::Util.method_alias(klass, :do_request_async, ::HTTPClient)
10
+ ::Oboe::Util.method_alias(klass, :do_get_stream, ::HTTPClient)
11
+ end
12
+
13
+ def oboe_collect(method, uri, query = nil)
14
+ kvs = {}
15
+ kvs['IsService'] = 1
16
+
17
+ # Conditionally log URL query params
18
+ # Because of the hook points, the query arg can come in under <tt>query</tt>
19
+ # or as a part of <tt>uri</tt> (not both). Here we handle both cases.
20
+ if Oboe::Config[:httpclient][:log_args]
21
+ if query
22
+ kvs['RemoteURL'] = uri.to_s + '?' + Oboe::Util.to_query(query)
23
+ else
24
+ kvs['RemoteURL'] = uri.to_s
25
+ end
26
+ else
27
+ kvs['RemoteURL'] = uri.to_s.split('?').first
28
+ end
29
+
30
+ kvs['HTTPMethod'] = ::Oboe::Util.upcase(method)
31
+ kvs['Backtrace'] = Oboe::API.backtrace if Oboe::Config[:httpclient][:collect_backtraces]
32
+ kvs
33
+ rescue => e
34
+ Oboe.logger.debug "[oboe/debug] Error capturing httpclient KVs: #{e.message}"
35
+ Oboe.logger.debug e.backtrace.join('\n') if ::Oboe::Config[:verbose]
36
+ end
37
+
38
+ def do_request_with_oboe(method, uri, query, body, header, &block)
39
+ # If we're not tracing, just do a fast return.
40
+ if !Oboe.tracing?
41
+ return request_without_oboe(method, uri, query, body, header, &block)
42
+ end
43
+
44
+ begin
45
+ response_context = nil
46
+
47
+ # Avoid cross host tracing for blacklisted domains
48
+ blacklisted = Oboe::API.blacklisted?(uri.hostname)
49
+
50
+ kvs = oboe_collect(method, uri, query)
51
+ kvs['Blacklisted'] = true if blacklisted
52
+
53
+ Oboe::API.log_entry('httpclient', kvs)
54
+ kvs.clear
55
+
56
+ req_context = Oboe::Context.toString()
57
+
58
+ # Be aware of various ways to call/use httpclient
59
+ if header.is_a?(Array)
60
+ header.push ["X-Trace", req_context]
61
+ elsif header.is_a?(Hash)
62
+ header['X-Trace'] = req_context unless blacklisted
63
+ end
64
+
65
+ # The core httpclient call
66
+ response = do_request_without_oboe(method, uri, query, body, header, &block)
67
+
68
+ response_context = response.headers['X-Trace']
69
+ kvs['HTTPStatus'] = response.status_code
70
+
71
+ # If we get a redirect, report the location header
72
+ if ((300..308).to_a.include? response.status.to_i) && response.headers.key?("Location")
73
+ kvs["Location"] = response.headers["Location"]
74
+ end
75
+
76
+ if response_context && !blacklisted
77
+ Oboe::XTrace.continue_service_context(req_context, response_context)
78
+ end
79
+
80
+ response
81
+ rescue => e
82
+ Oboe::API.log_exception('httpclient', e)
83
+ raise e
84
+ ensure
85
+ Oboe::API.log_exit('httpclient', kvs)
86
+ end
87
+ end
88
+
89
+ def do_request_async_with_oboe(method, uri, query, body, header)
90
+ if Oboe.tracing?
91
+ # Since async is done by calling Thread.new { .. }, we somehow
92
+ # have to pass the tracing context into that new thread. Here
93
+ # we stowaway the context in the request headers to be picked up
94
+ # (and removed from req headers) in do_get_stream.
95
+ if header.is_a?(Array)
96
+ header.push ["oboe.context", Oboe::Context.toString]
97
+ elsif header.is_a?(Hash)
98
+ header['oboe.context'] = Oboe::Context.toString
99
+ end
100
+ end
101
+
102
+ do_request_async_without_oboe(method, uri, query, body, header)
103
+ end
104
+
105
+ def do_get_stream_with_oboe(req, proxy, conn)
106
+ unless req.headers.key?("oboe.context")
107
+ return do_get_stream_without_oboe(req, proxy, conn)
108
+ end
109
+
110
+ # Pickup context and delete the headers stowaway
111
+ Oboe::Context.fromString req.headers["oboe.context"]
112
+ req.header.delete "oboe.context"
113
+
114
+ begin
115
+ response = nil
116
+ response_context = nil
117
+ uri = req.http_header.request_uri
118
+ method = req.http_header.request_method
119
+
120
+ # Avoid cross host tracing for blacklisted domains
121
+ blacklisted = Oboe::API.blacklisted?(uri.hostname)
122
+
123
+ kvs = oboe_collect(method, uri)
124
+ kvs['Blacklisted'] = true if blacklisted
125
+ kvs['Async'] = 1
126
+
127
+ Oboe::API.log_entry('httpclient', kvs)
128
+ kvs.clear
129
+
130
+ req_context = Oboe::Context.toString()
131
+ req.header.add('X-Trace', req_context)
132
+
133
+ # The core httpclient call
134
+ result = do_get_stream_without_oboe(req, proxy, conn)
135
+
136
+ # Older HTTPClient < 2.6.0 returns HTTPClient::Connection
137
+ if result.is_a?(::HTTP::Message)
138
+ response = result
139
+ else
140
+ response = conn.pop
141
+ end
142
+
143
+ response_context = response.headers['X-Trace']
144
+ kvs['HTTPStatus'] = response.status_code
145
+
146
+ # If we get a redirect, report the location header
147
+ if ((300..308).to_a.include? response.status.to_i) && response.headers.key?("Location")
148
+ kvs["Location"] = response.headers["Location"]
149
+ end
150
+
151
+ if response_context && !blacklisted
152
+ Oboe::XTrace.continue_service_context(req_context, response_context)
153
+ end
154
+
155
+ # Older HTTPClient < 2.6.0 returns HTTPClient::Connection
156
+ conn.push response if result.is_a?(::HTTPClient::Connection)
157
+ result
158
+ rescue => e
159
+ Oboe::API.log_exception('httpclient', e)
160
+ raise e
161
+ ensure
162
+ # Oboe::API.log_exit('httpclient', kvs.merge('Async' => 1))
163
+ Oboe::API.log_exit('httpclient', kvs)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ if Oboe::Config[:httpclient][:enabled] && defined?(::HTTPClient)
171
+ ::Oboe.logger.info '[oboe/loading] Instrumenting httpclient' if Oboe::Config[:verbose]
172
+ ::Oboe::Util.send_include(::HTTPClient, ::Oboe::Inst::HTTPClient)
173
+ end
@@ -19,7 +19,6 @@ module Oboe
19
19
  report_kvs['Port'] = req.port
20
20
  report_kvs['Proto'] = req.scheme
21
21
  report_kvs['Query-String'] = URI.unescape(req.query_string) unless req.query_string.empty?
22
- report_kvs[:URL] = URI.unescape(req.path)
23
22
  report_kvs[:Method] = req.request_method
24
23
  report_kvs['AJAX'] = true if req.xhr?
25
24
  report_kvs['ClientIP'] = req.ip
@@ -62,9 +61,13 @@ module Oboe
62
61
  end
63
62
 
64
63
  req = ::Rack::Request.new(env)
65
-
66
64
  report_kvs = {}
67
- report_kvs[:URL] = URI.unescape(req.path)
65
+
66
+ if Oboe::Config[:rack][:log_args]
67
+ report_kvs[:URL] = URI.unescape(req.fullpath)
68
+ else
69
+ report_kvs[:URL] = URI.unescape(req.path)
70
+ end
68
71
 
69
72
  # Check for and validate X-Trace request header to pick up tracing context
70
73
  xtrace = env.is_a?(Hash) ? env['HTTP_X_TRACE'] : nil
@@ -28,15 +28,19 @@ module Oboe
28
28
  end
29
29
 
30
30
  kvs = {}
31
+ kvs['IsService'] = 1
31
32
  kvs[:HTTPStatus] = response.code
32
33
  kvs['Backtrace'] = Oboe::API.backtrace if Oboe::Config[:typhoeus][:collect_backtraces]
33
34
 
34
35
  uri = URI(response.effective_url)
35
- kvs['IsService'] = 1
36
- kvs['RemoteProtocol'] = ::Oboe::Util.upcase(uri.scheme)
37
- kvs['RemoteHost'] = uri.host
38
- kvs['RemotePort'] = uri.port ? uri.port : 80
39
- kvs['ServiceArg'] = uri.path
36
+
37
+ # Conditionally log query params
38
+ if Oboe::Config[:typhoeus][:log_args]
39
+ kvs['RemoteURL'] = uri.to_s
40
+ else
41
+ kvs['RemoteURL'] = uri.to_s.split('?').first
42
+ end
43
+
40
44
  kvs['HTTPMethod'] = ::Oboe::Util.upcase(options[:method])
41
45
  kvs['Blacklisted'] = true if blacklisted
42
46
 
@@ -138,6 +138,25 @@ module Oboe
138
138
  end
139
139
  end
140
140
 
141
+
142
+ ##
143
+ # to_query
144
+ #
145
+ # Used under Ruby 1.8.7 to convert a hash into a URL
146
+ # query. A backport of Hash#to_query.
147
+ #
148
+ def to_query(h)
149
+ return "" unless h.is_a?(Hash)
150
+
151
+ # If called from a newer Ruby, use the builtin.
152
+ return h.to_query if RUBY_VERSION >= '1.9.3'
153
+
154
+ result = []
155
+
156
+ h.each { |k, v| result.push (k.to_s + '=' + v.to_s) }
157
+ return result.sort.join('&')
158
+ end
159
+
141
160
  ##
142
161
  # build_report
143
162
  #
@@ -174,6 +193,7 @@ module Oboe
174
193
  platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli)
175
194
  platform_info['Ruby.Excon.Version'] = "Excon-#{::Excon::VERSION}" if defined?(::Excon::VERSION)
176
195
  platform_info['Ruby.Faraday.Version'] = "Faraday-#{::Faraday::VERSION}" if defined?(::Faraday)
196
+ platform_info['Ruby.HTTPClient.Version'] = "HTTPClient-#{::HTTPClient::VERSION}" if defined?(::HTTPClient::VERSION)
177
197
  platform_info['Ruby.MemCache.Version'] = "MemCache-#{::MemCache::VERSION}" if defined?(::MemCache)
178
198
  platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped)
179
199
  platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis)