traceview 3.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +58 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +490 -0
- data/CONFIG.md +16 -0
- data/Gemfile +95 -0
- data/LICENSE +199 -0
- data/README.md +380 -0
- data/Rakefile +109 -0
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +225 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +125 -0
- data/examples/tracing_background_jobs.rb +52 -0
- data/examples/tracing_forked_processes.rb +100 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/extconf.rb +61 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/bson/bson.h +221 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/oboe.h +275 -0
- data/ext/oboe_metal/src/oboe.hpp +352 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
- data/ext/oboe_metal/tests/test.rb +11 -0
- data/gemfiles/mongo.gemfile +33 -0
- data/gemfiles/moped.gemfile +33 -0
- data/get_version.rb +5 -0
- data/init.rb +4 -0
- data/lib/joboe_metal.rb +206 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +59 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +151 -0
- data/lib/rails/generators/traceview/install_generator.rb +76 -0
- data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
- data/lib/traceview/api/layerinit.rb +51 -0
- data/lib/traceview/api/logging.rb +209 -0
- data/lib/traceview/api/memcache.rb +31 -0
- data/lib/traceview/api/profiling.rb +50 -0
- data/lib/traceview/api/tracing.rb +135 -0
- data/lib/traceview/api/util.rb +121 -0
- data/lib/traceview/api.rb +18 -0
- data/lib/traceview/base.rb +225 -0
- data/lib/traceview/config.rb +238 -0
- data/lib/traceview/frameworks/grape.rb +97 -0
- data/lib/traceview/frameworks/padrino/templates.rb +58 -0
- data/lib/traceview/frameworks/padrino.rb +64 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
- data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
- data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
- data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
- data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
- data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
- data/lib/traceview/frameworks/rails.rb +145 -0
- data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
- data/lib/traceview/frameworks/sinatra.rb +95 -0
- data/lib/traceview/inst/cassandra.rb +279 -0
- data/lib/traceview/inst/dalli.rb +86 -0
- data/lib/traceview/inst/em-http-request.rb +99 -0
- data/lib/traceview/inst/excon.rb +111 -0
- data/lib/traceview/inst/faraday.rb +73 -0
- data/lib/traceview/inst/http.rb +87 -0
- data/lib/traceview/inst/httpclient.rb +173 -0
- data/lib/traceview/inst/memcache.rb +102 -0
- data/lib/traceview/inst/memcached.rb +94 -0
- data/lib/traceview/inst/mongo.rb +238 -0
- data/lib/traceview/inst/moped.rb +474 -0
- data/lib/traceview/inst/rack.rb +122 -0
- data/lib/traceview/inst/redis.rb +271 -0
- data/lib/traceview/inst/resque.rb +192 -0
- data/lib/traceview/inst/rest-client.rb +38 -0
- data/lib/traceview/inst/sequel.rb +162 -0
- data/lib/traceview/inst/typhoeus.rb +102 -0
- data/lib/traceview/instrumentation.rb +21 -0
- data/lib/traceview/loading.rb +94 -0
- data/lib/traceview/logger.rb +41 -0
- data/lib/traceview/method_profiling.rb +84 -0
- data/lib/traceview/ruby.rb +36 -0
- data/lib/traceview/support.rb +113 -0
- data/lib/traceview/thread_local.rb +26 -0
- data/lib/traceview/util.rb +250 -0
- data/lib/traceview/version.rb +16 -0
- data/lib/traceview/xtrace.rb +90 -0
- data/lib/traceview.rb +62 -0
- data/test/frameworks/apps/grape_nested.rb +30 -0
- data/test/frameworks/apps/grape_simple.rb +24 -0
- data/test/frameworks/apps/padrino_simple.rb +45 -0
- data/test/frameworks/apps/sinatra_simple.rb +24 -0
- data/test/frameworks/grape_test.rb +142 -0
- data/test/frameworks/padrino_test.rb +30 -0
- data/test/frameworks/sinatra_test.rb +30 -0
- data/test/instrumentation/cassandra_test.rb +380 -0
- data/test/instrumentation/dalli_test.rb +171 -0
- data/test/instrumentation/em_http_request_test.rb +86 -0
- data/test/instrumentation/excon_test.rb +207 -0
- data/test/instrumentation/faraday_test.rb +235 -0
- data/test/instrumentation/http_test.rb +140 -0
- data/test/instrumentation/httpclient_test.rb +296 -0
- data/test/instrumentation/memcache_test.rb +251 -0
- data/test/instrumentation/memcached_test.rb +226 -0
- data/test/instrumentation/mongo_test.rb +462 -0
- data/test/instrumentation/moped_test.rb +496 -0
- data/test/instrumentation/rack_test.rb +116 -0
- data/test/instrumentation/redis_hashes_test.rb +265 -0
- data/test/instrumentation/redis_keys_test.rb +318 -0
- data/test/instrumentation/redis_lists_test.rb +310 -0
- data/test/instrumentation/redis_misc_test.rb +160 -0
- data/test/instrumentation/redis_sets_test.rb +293 -0
- data/test/instrumentation/redis_sortedsets_test.rb +325 -0
- data/test/instrumentation/redis_strings_test.rb +333 -0
- data/test/instrumentation/resque_test.rb +62 -0
- data/test/instrumentation/rest-client_test.rb +294 -0
- data/test/instrumentation/sequel_mysql2_test.rb +326 -0
- data/test/instrumentation/sequel_mysql_test.rb +326 -0
- data/test/instrumentation/sequel_pg_test.rb +330 -0
- data/test/instrumentation/typhoeus_test.rb +285 -0
- data/test/minitest_helper.rb +187 -0
- data/test/profiling/method_test.rb +198 -0
- data/test/servers/rackapp_8101.rb +22 -0
- data/test/support/backcompat_test.rb +269 -0
- data/test/support/config_test.rb +128 -0
- data/test/support/dnt_test.rb +73 -0
- data/test/support/liboboe_settings_test.rb +104 -0
- data/test/support/xtrace_test.rb +35 -0
- data/traceview.gemspec +29 -0
- metadata +248 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module Dalli
|
|
7
|
+
include TraceView::API::Memcache
|
|
8
|
+
|
|
9
|
+
def self.included(cls)
|
|
10
|
+
cls.class_eval do
|
|
11
|
+
TraceView.logger.info '[traceview/loading] Instrumenting memcache (dalli)' if TraceView::Config[:verbose]
|
|
12
|
+
if ::Dalli::Client.private_method_defined? :perform
|
|
13
|
+
alias perform_without_traceview perform
|
|
14
|
+
alias perform perform_with_traceview
|
|
15
|
+
else TraceView.logger.warn '[traceview/loading] Couldn\'t properly instrument Memcache (Dalli). Partial traces may occur.'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if ::Dalli::Client.method_defined? :get_multi
|
|
19
|
+
alias get_multi_without_traceview get_multi
|
|
20
|
+
alias get_multi get_multi_with_traceview
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def perform_with_traceview(*all_args, &blk)
|
|
26
|
+
op, key, *args = *all_args
|
|
27
|
+
|
|
28
|
+
report_kvs = {}
|
|
29
|
+
report_kvs[:KVOp] = op
|
|
30
|
+
report_kvs[:KVKey] = key
|
|
31
|
+
if @servers.is_a?(Array) && !@servers.empty?
|
|
32
|
+
report_kvs[:RemoteHost] = @servers.join(", ")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if TraceView.tracing? && !TraceView.tracing_layer_op?(:get_multi)
|
|
36
|
+
TraceView::API.trace('memcache', report_kvs) do
|
|
37
|
+
result = perform_without_traceview(*all_args, &blk)
|
|
38
|
+
|
|
39
|
+
# Clear the hash for a potential info event
|
|
40
|
+
report_kvs.clear
|
|
41
|
+
report_kvs[:KVHit] = memcache_hit?(result) if op == :get && key.class == String
|
|
42
|
+
report_kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:dalli][:collect_backtraces]
|
|
43
|
+
|
|
44
|
+
TraceView::API.log('memcache', 'info', report_kvs) unless report_kvs.empty?
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
perform_without_traceview(*all_args, &blk)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def get_multi_with_traceview(*keys)
|
|
53
|
+
return get_multi_without_traceview(keys) unless TraceView.tracing?
|
|
54
|
+
|
|
55
|
+
info_kvs = {}
|
|
56
|
+
|
|
57
|
+
begin
|
|
58
|
+
info_kvs[:KVKeyCount] = keys.flatten.length
|
|
59
|
+
info_kvs[:KVKeyCount] = (info_kvs[:KVKeyCount] - 1) if keys.last.is_a?(Hash) || keys.last.nil?
|
|
60
|
+
if @servers.is_a?(Array) && !@servers.empty?
|
|
61
|
+
info_kvs[:RemoteHost] = @servers.join(", ")
|
|
62
|
+
end
|
|
63
|
+
rescue
|
|
64
|
+
TraceView.logger.debug "[traceview/debug] Error collecting info keys: #{e.message}"
|
|
65
|
+
TraceView.logger.debug e.backtrace
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
TraceView::API.trace('memcache', { :KVOp => :get_multi }, :get_multi) do
|
|
69
|
+
values = get_multi_without_traceview(keys)
|
|
70
|
+
|
|
71
|
+
info_kvs[:KVHitCount] = values.length
|
|
72
|
+
info_kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:dalli][:collect_backtraces]
|
|
73
|
+
TraceView::API.log('memcache', 'info', info_kvs)
|
|
74
|
+
|
|
75
|
+
values
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if defined?(Dalli) && TraceView::Config[:dalli][:enabled]
|
|
83
|
+
::Dalli::Client.module_eval do
|
|
84
|
+
include TraceView::Inst::Dalli
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module TraceView
|
|
2
|
+
module Inst
|
|
3
|
+
module EventMachine
|
|
4
|
+
module HttpConnection
|
|
5
|
+
def setup_request_with_traceview(*args, &block)
|
|
6
|
+
report_kvs = {}
|
|
7
|
+
context = TraceView::Context.toString
|
|
8
|
+
blacklisted = TraceView::API.blacklisted?(@uri)
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
report_kvs['IsService'] = 1
|
|
12
|
+
report_kvs['RemoteURL'] = @uri
|
|
13
|
+
report_kvs['HTTPMethod'] = args[0]
|
|
14
|
+
report_kvs['Blacklisted'] = true if blacklisted
|
|
15
|
+
|
|
16
|
+
if TraceView::Config[:em_http_request][:collect_backtraces]
|
|
17
|
+
report_kvs[:Backtrace] = TraceView::API.backtrace
|
|
18
|
+
end
|
|
19
|
+
rescue => e
|
|
20
|
+
TraceView.logger.debug "[traceview/debug] em-http-request KV error: #{e.inspect}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
::TraceView::API.log_entry('em-http-request', report_kvs)
|
|
24
|
+
client = setup_request_without_traceview(*args, &block)
|
|
25
|
+
client.req.headers['X-Trace'] = context unless blacklisted
|
|
26
|
+
client
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module HttpClient
|
|
31
|
+
def parse_response_header_with_traceview(*args, &block)
|
|
32
|
+
report_kvs = {}
|
|
33
|
+
xtrace = nil
|
|
34
|
+
blacklisted = TraceView::API.blacklisted?(@uri)
|
|
35
|
+
|
|
36
|
+
begin
|
|
37
|
+
report_kvs[:HTTPStatus] = args[2]
|
|
38
|
+
report_kvs[:Async] = 1
|
|
39
|
+
rescue => e
|
|
40
|
+
TraceView.logger.debug "[traceview/debug] em-http-request KV error: #{e.inspect}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
parse_response_header_without_traceview(*args, &block)
|
|
44
|
+
|
|
45
|
+
unless blacklisted
|
|
46
|
+
headers = args[0]
|
|
47
|
+
context = TraceView::Context.toString
|
|
48
|
+
task_id = TraceView::XTrace.task_id(context)
|
|
49
|
+
|
|
50
|
+
if headers.is_a?(Hash) && headers.key?('X-Trace')
|
|
51
|
+
xtrace = headers['X-Trace']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if TraceView::XTrace.valid?(xtrace) && TraceView.tracing?
|
|
55
|
+
|
|
56
|
+
# Assure that we received back a valid X-Trace with the same task_id
|
|
57
|
+
if task_id == TraceView::XTrace.task_id(xtrace)
|
|
58
|
+
TraceView::Context.fromString(xtrace)
|
|
59
|
+
else
|
|
60
|
+
TraceView.logger.debug "Mismatched returned X-Trace ID : #{xtrace}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
::TraceView::API.log_exit('em-http-request', report_kvs)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if RUBY_VERSION >= '1.9'
|
|
74
|
+
if defined?(::EventMachine::HttpConnection) && defined?(::EventMachine::HttpClient) && TraceView::Config[:em_http_request][:enabled]
|
|
75
|
+
TraceView.logger.info '[traceview/loading] Instrumenting em-http-request' if TraceView::Config[:verbose]
|
|
76
|
+
|
|
77
|
+
class ::EventMachine::HttpConnection
|
|
78
|
+
include TraceView::Inst::EventMachine::HttpConnection
|
|
79
|
+
|
|
80
|
+
if method_defined?(:setup_request)
|
|
81
|
+
class_eval 'alias :setup_request_without_traceview :setup_request'
|
|
82
|
+
class_eval 'alias :setup_request :setup_request_with_traceview'
|
|
83
|
+
else
|
|
84
|
+
TraceView.logger.warn '[traceview/loading] Couldn\'t properly instrument em-http-request (:setup_request). Partial traces may occur.'
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class ::EventMachine::HttpClient
|
|
89
|
+
include TraceView::Inst::EventMachine::HttpClient
|
|
90
|
+
|
|
91
|
+
if method_defined?(:parse_response_header)
|
|
92
|
+
class_eval 'alias :parse_response_header_without_traceview :parse_response_header'
|
|
93
|
+
class_eval 'alias :parse_response_header :parse_response_header_with_traceview'
|
|
94
|
+
else
|
|
95
|
+
TraceView.logger.warn '[traceview/loading] Couldn\'t properly instrument em-http-request (:parse_response_header). Partial traces may occur.'
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Copyright (c) 2015 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module ExconConnection
|
|
7
|
+
def self.included(klass)
|
|
8
|
+
::TraceView::Util.method_alias(klass, :request, ::Excon::Connection)
|
|
9
|
+
::TraceView::Util.method_alias(klass, :requests, ::Excon::Connection)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def traceview_collect(params)
|
|
13
|
+
kvs = {}
|
|
14
|
+
kvs['IsService'] = 1
|
|
15
|
+
kvs['RemoteProtocol'] = ::TraceView::Util.upcase(@data[:scheme])
|
|
16
|
+
kvs['RemoteHost'] = @data[:host]
|
|
17
|
+
|
|
18
|
+
# Conditionally log query args
|
|
19
|
+
if TraceView::Config[:excon][:log_args] && (@data[:query] && @data[:query].length)
|
|
20
|
+
kvs['ServiceArg'] = @data[:path] + '?' + @data[:query]
|
|
21
|
+
else
|
|
22
|
+
kvs['ServiceArg'] = @data[:path]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# In the case of HTTP pipelining, params could be an array of
|
|
26
|
+
# request hashes.
|
|
27
|
+
if params.is_a?(Array)
|
|
28
|
+
methods = []
|
|
29
|
+
params.each do |p|
|
|
30
|
+
methods << ::TraceView::Util.upcase(p[:method])
|
|
31
|
+
end
|
|
32
|
+
kvs['HTTPMethods'] = methods.join(', ')[0..1024]
|
|
33
|
+
kvs['Pipeline'] = true
|
|
34
|
+
else
|
|
35
|
+
kvs['HTTPMethod'] = ::TraceView::Util.upcase(params[:method])
|
|
36
|
+
end
|
|
37
|
+
kvs['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:excon][:collect_backtraces]
|
|
38
|
+
kvs
|
|
39
|
+
rescue => e
|
|
40
|
+
TraceView.logger.debug "[traceview/debug] Error capturing excon KVs: #{e.message}"
|
|
41
|
+
TraceView.logger.debug e.backtrace.join('\n') if ::TraceView::Config[:verbose]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def requests_with_traceview(pipeline_params)
|
|
45
|
+
responses = nil
|
|
46
|
+
TraceView::API.trace('excon', traceview_collect(pipeline_params)) do
|
|
47
|
+
responses = requests_without_traceview(pipeline_params)
|
|
48
|
+
end
|
|
49
|
+
responses
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def request_with_traceview(params={}, &block)
|
|
53
|
+
# If we're not tracing, just do a fast return.
|
|
54
|
+
# If making HTTP pipeline requests (ordered batched)
|
|
55
|
+
# then just return as we're tracing from parent
|
|
56
|
+
# <tt>requests</tt>
|
|
57
|
+
if !TraceView.tracing? || params[:pipeline]
|
|
58
|
+
return request_without_traceview(params, &block)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
begin
|
|
62
|
+
response_context = nil
|
|
63
|
+
|
|
64
|
+
# Avoid cross host tracing for blacklisted domains
|
|
65
|
+
blacklisted = TraceView::API.blacklisted?(@data[:hostname])
|
|
66
|
+
|
|
67
|
+
req_context = TraceView::Context.toString()
|
|
68
|
+
@data[:headers]['X-Trace'] = req_context unless blacklisted
|
|
69
|
+
|
|
70
|
+
kvs = traceview_collect(params)
|
|
71
|
+
kvs['Blacklisted'] = true if blacklisted
|
|
72
|
+
|
|
73
|
+
TraceView::API.log_entry('excon', kvs)
|
|
74
|
+
kvs.clear
|
|
75
|
+
|
|
76
|
+
# The core excon call
|
|
77
|
+
response = request_without_traceview(params, &block)
|
|
78
|
+
|
|
79
|
+
# excon only passes back a hash (datum) for HTTP pipelining...
|
|
80
|
+
# In that case, we should never arrive here but for the OCD, double check
|
|
81
|
+
# the datatype before trying to extract pertinent info
|
|
82
|
+
if response.is_a?(Excon::Response)
|
|
83
|
+
response_context = response.headers['X-Trace']
|
|
84
|
+
kvs['HTTPStatus'] = response.status
|
|
85
|
+
|
|
86
|
+
# If we get a redirect, report the location header
|
|
87
|
+
if ((300..308).to_a.include? response.status.to_i) && response.headers.key?("Location")
|
|
88
|
+
kvs["Location"] = response.headers["Location"]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if response_context && !blacklisted
|
|
92
|
+
TraceView::XTrace.continue_service_context(req_context, response_context)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
response
|
|
97
|
+
rescue => e
|
|
98
|
+
TraceView::API.log_exception('excon', e)
|
|
99
|
+
raise e
|
|
100
|
+
ensure
|
|
101
|
+
TraceView::API.log_exit('excon', kvs) unless params[:pipeline]
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if TraceView::Config[:excon][:enabled] && defined?(::Excon)
|
|
109
|
+
::TraceView.logger.info '[traceview/loading] Instrumenting excon' if TraceView::Config[:verbose]
|
|
110
|
+
::TraceView::Util.send_include(::Excon::Connection, ::TraceView::Inst::ExconConnection)
|
|
111
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module TraceView
|
|
2
|
+
module Inst
|
|
3
|
+
module FaradayConnection
|
|
4
|
+
def self.included(klass)
|
|
5
|
+
::TraceView::Util.method_alias(klass, :run_request, ::Faraday::Connection)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def run_request_with_traceview(method, url, body, headers, &block)
|
|
9
|
+
# Only send service KVs if we're not using the Net::HTTP adapter
|
|
10
|
+
# Otherwise, the Net::HTTP instrumentation will send the service KVs
|
|
11
|
+
handle_service = !@builder.handlers.include?(Faraday::Adapter::NetHttp) &&
|
|
12
|
+
!@builder.handlers.include?(Faraday::Adapter::Excon)
|
|
13
|
+
TraceView::API.log_entry('faraday')
|
|
14
|
+
|
|
15
|
+
result = run_request_without_traceview(method, url, body, headers, &block)
|
|
16
|
+
|
|
17
|
+
kvs = {}
|
|
18
|
+
kvs['Middleware'] = @builder.handlers
|
|
19
|
+
kvs['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:faraday][:collect_backtraces]
|
|
20
|
+
|
|
21
|
+
if handle_service
|
|
22
|
+
blacklisted = TraceView::API.blacklisted?(@url_prefix.to_s)
|
|
23
|
+
context = TraceView::Context.toString
|
|
24
|
+
task_id = TraceView::XTrace.task_id(context)
|
|
25
|
+
|
|
26
|
+
# Avoid cross host tracing for blacklisted domains
|
|
27
|
+
# Conditionally add the X-Trace header to the outgoing request
|
|
28
|
+
@headers['X-Trace'] = context unless blacklisted
|
|
29
|
+
|
|
30
|
+
kvs['IsService'] = 1
|
|
31
|
+
kvs['RemoteProtocol'] = (@url_prefix.scheme == 'https') ? 'HTTPS' : 'HTTP'
|
|
32
|
+
kvs['RemoteHost'] = @url_prefix.host
|
|
33
|
+
kvs['RemotePort'] = @url_prefix.port
|
|
34
|
+
kvs['ServiceArg'] = url
|
|
35
|
+
kvs['HTTPMethod'] = method
|
|
36
|
+
kvs[:HTTPStatus] = result.status
|
|
37
|
+
kvs['Blacklisted'] = true if blacklisted
|
|
38
|
+
|
|
39
|
+
# Re-attach net::http edge unless it's blacklisted or if we don't have a
|
|
40
|
+
# valid X-Trace header
|
|
41
|
+
unless blacklisted
|
|
42
|
+
xtrace = result.headers['X-Trace']
|
|
43
|
+
|
|
44
|
+
if TraceView::XTrace.valid?(xtrace) && TraceView.tracing?
|
|
45
|
+
|
|
46
|
+
# Assure that we received back a valid X-Trace with the same task_id
|
|
47
|
+
if task_id == TraceView::XTrace.task_id(xtrace)
|
|
48
|
+
TraceView::Context.fromString(xtrace)
|
|
49
|
+
else
|
|
50
|
+
TraceView.logger.debug "Mismatched returned X-Trace ID: #{xtrace}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
TraceView::API.log('faraday', 'info', kvs)
|
|
57
|
+
result
|
|
58
|
+
rescue => e
|
|
59
|
+
TraceView::API.log_exception('faraday', e)
|
|
60
|
+
raise e
|
|
61
|
+
ensure
|
|
62
|
+
TraceView::API.log_exit('faraday')
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if TraceView::Config[:faraday][:enabled]
|
|
69
|
+
if defined?(::Faraday)
|
|
70
|
+
TraceView.logger.info '[traceview/loading] Instrumenting faraday' if TraceView::Config[:verbose]
|
|
71
|
+
::TraceView::Util.send_include(::Faraday::Connection, ::TraceView::Inst::FaradayConnection)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'net/http'
|
|
5
|
+
|
|
6
|
+
if TraceView::Config[:nethttp][:enabled]
|
|
7
|
+
|
|
8
|
+
Net::HTTP.class_eval do
|
|
9
|
+
def request_with_traceview(*args, &block)
|
|
10
|
+
# If we're not tracing, just do a fast return. Since
|
|
11
|
+
# net/http.request calls itself, only trace
|
|
12
|
+
# once the http session has been started.
|
|
13
|
+
if !TraceView.tracing? || !started?
|
|
14
|
+
return request_without_traceview(*args, &block)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Avoid cross host tracing for blacklisted domains
|
|
18
|
+
blacklisted = TraceView::API.blacklisted?(addr_port)
|
|
19
|
+
|
|
20
|
+
TraceView::API.trace('net-http') do
|
|
21
|
+
opts = {}
|
|
22
|
+
context = TraceView::Context.toString()
|
|
23
|
+
task_id = TraceView::XTrace.task_id(context)
|
|
24
|
+
|
|
25
|
+
# Collect KVs to report in the info event
|
|
26
|
+
if args.length && args[0]
|
|
27
|
+
req = args[0]
|
|
28
|
+
|
|
29
|
+
opts['IsService'] = 1
|
|
30
|
+
opts['RemoteProtocol'] = use_ssl? ? 'HTTPS' : 'HTTP'
|
|
31
|
+
opts['RemoteHost'] = addr_port
|
|
32
|
+
|
|
33
|
+
# Conditionally log query params
|
|
34
|
+
if TraceView::Config[:nethttp][:log_args]
|
|
35
|
+
opts['ServiceArg'] = req.path
|
|
36
|
+
else
|
|
37
|
+
opts['ServiceArg'] = req.path.split('?').first
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
opts['HTTPMethod'] = req.method
|
|
41
|
+
opts['Blacklisted'] = true if blacklisted
|
|
42
|
+
opts['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:nethttp][:collect_backtraces]
|
|
43
|
+
|
|
44
|
+
req['X-Trace'] = context unless blacklisted
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
begin
|
|
48
|
+
# The actual net::http call
|
|
49
|
+
resp = request_without_traceview(*args, &block)
|
|
50
|
+
|
|
51
|
+
# Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
|
|
52
|
+
unless blacklisted
|
|
53
|
+
xtrace = resp.get_fields('X-Trace')
|
|
54
|
+
xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
|
|
55
|
+
|
|
56
|
+
if TraceView::XTrace.valid?(xtrace)
|
|
57
|
+
|
|
58
|
+
# Assure that we received back a valid X-Trace with the same task_id
|
|
59
|
+
if task_id == TraceView::XTrace.task_id(xtrace)
|
|
60
|
+
TraceView::Context.fromString(xtrace)
|
|
61
|
+
else
|
|
62
|
+
TraceView.logger.debug "Mismatched returned X-Trace ID : #{xtrace}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
opts['HTTPStatus'] = resp.code
|
|
68
|
+
|
|
69
|
+
# If we get a redirect, report the location header
|
|
70
|
+
if ((300..308).to_a.include? resp.code.to_i) && resp.header["Location"]
|
|
71
|
+
opts["Location"] = resp.header["Location"]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
next resp
|
|
75
|
+
ensure
|
|
76
|
+
# Log the info event with the KVs in opts
|
|
77
|
+
TraceView::API.log('net-http', 'info', opts)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
alias request_without_traceview request
|
|
83
|
+
alias request request_with_traceview
|
|
84
|
+
|
|
85
|
+
TraceView.logger.info '[traceview/loading] Instrumenting net/http' if TraceView::Config[:verbose]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Copyright (c) 2015 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module HTTPClient
|
|
7
|
+
def self.included(klass)
|
|
8
|
+
::TraceView::Util.method_alias(klass, :do_request, ::HTTPClient)
|
|
9
|
+
::TraceView::Util.method_alias(klass, :do_request_async, ::HTTPClient)
|
|
10
|
+
::TraceView::Util.method_alias(klass, :do_get_stream, ::HTTPClient)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def traceview_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 TraceView::Config[:httpclient][:log_args]
|
|
21
|
+
if query
|
|
22
|
+
kvs['RemoteURL'] = uri.to_s + '?' + TraceView::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'] = ::TraceView::Util.upcase(method)
|
|
31
|
+
kvs['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:httpclient][:collect_backtraces]
|
|
32
|
+
kvs
|
|
33
|
+
rescue => e
|
|
34
|
+
TraceView.logger.debug "[traceview/debug] Error capturing httpclient KVs: #{e.message}"
|
|
35
|
+
TraceView.logger.debug e.backtrace.join('\n') if ::TraceView::Config[:verbose]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def do_request_with_traceview(method, uri, query, body, header, &block)
|
|
39
|
+
# If we're not tracing, just do a fast return.
|
|
40
|
+
if !TraceView.tracing?
|
|
41
|
+
return request_without_traceview(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 = TraceView::API.blacklisted?(uri.hostname)
|
|
49
|
+
|
|
50
|
+
kvs = traceview_collect(method, uri, query)
|
|
51
|
+
kvs['Blacklisted'] = true if blacklisted
|
|
52
|
+
|
|
53
|
+
TraceView::API.log_entry('httpclient', kvs)
|
|
54
|
+
kvs.clear
|
|
55
|
+
|
|
56
|
+
req_context = TraceView::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_traceview(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
|
+
TraceView::XTrace.continue_service_context(req_context, response_context)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
response
|
|
81
|
+
rescue => e
|
|
82
|
+
TraceView::API.log_exception('httpclient', e)
|
|
83
|
+
raise e
|
|
84
|
+
ensure
|
|
85
|
+
TraceView::API.log_exit('httpclient', kvs)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def do_request_async_with_traceview(method, uri, query, body, header)
|
|
90
|
+
if TraceView.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 ["traceview.context", TraceView::Context.toString]
|
|
97
|
+
elsif header.is_a?(Hash)
|
|
98
|
+
header['traceview.context'] = TraceView::Context.toString
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
do_request_async_without_traceview(method, uri, query, body, header)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def do_get_stream_with_traceview(req, proxy, conn)
|
|
106
|
+
unless req.headers.key?("traceview.context")
|
|
107
|
+
return do_get_stream_without_traceview(req, proxy, conn)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Pickup context and delete the headers stowaway
|
|
111
|
+
TraceView::Context.fromString req.headers["traceview.context"]
|
|
112
|
+
req.header.delete "traceview.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 = TraceView::API.blacklisted?(uri.hostname)
|
|
122
|
+
|
|
123
|
+
kvs = traceview_collect(method, uri)
|
|
124
|
+
kvs['Blacklisted'] = true if blacklisted
|
|
125
|
+
kvs['Async'] = 1
|
|
126
|
+
|
|
127
|
+
TraceView::API.log_entry('httpclient', kvs)
|
|
128
|
+
kvs.clear
|
|
129
|
+
|
|
130
|
+
req_context = TraceView::Context.toString()
|
|
131
|
+
req.header.add('X-Trace', req_context)
|
|
132
|
+
|
|
133
|
+
# The core httpclient call
|
|
134
|
+
result = do_get_stream_without_traceview(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
|
+
TraceView::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
|
+
TraceView::API.log_exception('httpclient', e)
|
|
160
|
+
raise e
|
|
161
|
+
ensure
|
|
162
|
+
# TraceView::API.log_exit('httpclient', kvs.merge('Async' => 1))
|
|
163
|
+
TraceView::API.log_exit('httpclient', kvs)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if TraceView::Config[:httpclient][:enabled] && defined?(::HTTPClient)
|
|
171
|
+
::TraceView.logger.info '[traceview/loading] Instrumenting httpclient' if TraceView::Config[:verbose]
|
|
172
|
+
::TraceView::Util.send_include(::HTTPClient, ::TraceView::Inst::HTTPClient)
|
|
173
|
+
end
|