traceview 3.0.0
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.rb +7 -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_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.rb +62 -0
- data/lib/traceview/api.rb +18 -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/base.rb +225 -0
- data/lib/traceview/config.rb +238 -0
- data/lib/traceview/frameworks/grape.rb +97 -0
- data/lib/traceview/frameworks/padrino.rb +64 -0
- data/lib/traceview/frameworks/padrino/templates.rb +58 -0
- data/lib/traceview/frameworks/rails.rb +145 -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/sinatra.rb +95 -0
- data/lib/traceview/frameworks/sinatra/templates.rb +56 -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/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 +250 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module API
|
|
6
|
+
##
|
|
7
|
+
# Utility methods for the Memcache instrumentation
|
|
8
|
+
module Memcache
|
|
9
|
+
MEMCACHE_OPS = %w(add append cas decr decrement delete fetch get incr increment prepend replace set)
|
|
10
|
+
|
|
11
|
+
def memcache_hit?(result)
|
|
12
|
+
result.nil? ? 0 : 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def remote_host(key)
|
|
16
|
+
return unless defined?(Lib.memcached_server_by_key) \
|
|
17
|
+
&& defined?(@struct) && defined?(is_unix_socket?)
|
|
18
|
+
|
|
19
|
+
server_as_array = Lib.memcached_server_by_key(@struct, key.to_s)
|
|
20
|
+
if server_as_array.is_a?(Array)
|
|
21
|
+
server = server_as_array.first
|
|
22
|
+
if is_unix_socket?(server)
|
|
23
|
+
return 'localhost'
|
|
24
|
+
elsif defined?(server.hostname)
|
|
25
|
+
return server.hostname
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module API
|
|
6
|
+
##
|
|
7
|
+
# Module that provides profiling of arbitrary blocks of code
|
|
8
|
+
module Profiling
|
|
9
|
+
##
|
|
10
|
+
# Public: Profile a given block of code. Detect any exceptions thrown by
|
|
11
|
+
# the block and report errors.
|
|
12
|
+
#
|
|
13
|
+
# profile_name - A name used to identify the block being profiled.
|
|
14
|
+
# report_kvs - A hash containing key/value pairs that will be reported along
|
|
15
|
+
# with the event of this profile (optional).
|
|
16
|
+
# with_backtrace - Boolean to indicate whether a backtrace should
|
|
17
|
+
# be collected with this trace event.
|
|
18
|
+
#
|
|
19
|
+
# Example
|
|
20
|
+
#
|
|
21
|
+
# def computation(n)
|
|
22
|
+
# TraceView::API.profile('fib', { :n => n }) do
|
|
23
|
+
# fib(n)
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# Returns the result of the block.
|
|
28
|
+
def profile(profile_name, report_kvs = {}, with_backtrace = false)
|
|
29
|
+
report_kvs[:Language] ||= :ruby
|
|
30
|
+
report_kvs[:ProfileName] ||= profile_name
|
|
31
|
+
report_kvs[:Backtrace] = TraceView::API.backtrace if with_backtrace
|
|
32
|
+
|
|
33
|
+
TraceView::API.log(nil, 'profile_entry', report_kvs)
|
|
34
|
+
|
|
35
|
+
begin
|
|
36
|
+
yield
|
|
37
|
+
rescue => e
|
|
38
|
+
log_exception(nil, e)
|
|
39
|
+
raise
|
|
40
|
+
ensure
|
|
41
|
+
exit_kvs = {}
|
|
42
|
+
exit_kvs[:Language] = :ruby
|
|
43
|
+
exit_kvs[:ProfileName] = report_kvs[:ProfileName]
|
|
44
|
+
|
|
45
|
+
TraceView::API.log(nil, 'profile_exit', exit_kvs)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module API
|
|
6
|
+
##
|
|
7
|
+
# Provides the higher-level tracing interface for the API.
|
|
8
|
+
module Tracing
|
|
9
|
+
# Public: Trace a given block of code. Detect any exceptions thrown by
|
|
10
|
+
# the block and report errors.
|
|
11
|
+
#
|
|
12
|
+
# layer - The layer the block of code belongs to.
|
|
13
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
14
|
+
# with the first event of this layer (optional).
|
|
15
|
+
# protect_op - specify the operation being traced. Used to avoid
|
|
16
|
+
# double tracing between operations that call each other
|
|
17
|
+
#
|
|
18
|
+
# Example
|
|
19
|
+
#
|
|
20
|
+
# def computation(n)
|
|
21
|
+
# fib(n)
|
|
22
|
+
# raise Exception.new
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# def computation_with_oboe(n)
|
|
26
|
+
# trace('fib', { :number => n }) do
|
|
27
|
+
# computation(n)
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# result = computation_with_oboe(1000)
|
|
32
|
+
#
|
|
33
|
+
# Returns the result of the block.
|
|
34
|
+
def trace(layer, opts = {}, protect_op = nil)
|
|
35
|
+
log_entry(layer, opts, protect_op)
|
|
36
|
+
begin
|
|
37
|
+
yield
|
|
38
|
+
rescue Exception => e
|
|
39
|
+
log_exception(layer, e)
|
|
40
|
+
raise
|
|
41
|
+
ensure
|
|
42
|
+
log_exit(layer, {}, protect_op)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Public: Trace a given block of code which can start a trace depending
|
|
47
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
|
48
|
+
# block and report errors.
|
|
49
|
+
#
|
|
50
|
+
# When start_trace returns control to the calling context, the oboe
|
|
51
|
+
# context will be cleared.
|
|
52
|
+
#
|
|
53
|
+
# layer - The layer the block of code belongs to.
|
|
54
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
55
|
+
# with the first event of this layer (optional).
|
|
56
|
+
#
|
|
57
|
+
# Example
|
|
58
|
+
#
|
|
59
|
+
# def handle_request(request, response)
|
|
60
|
+
# # ... code that modifies request and response ...
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# def handle_request_with_oboe(request, response)
|
|
64
|
+
# result, xtrace = start_trace('rails', request['X-Trace']) do
|
|
65
|
+
# handle_request(request, response)
|
|
66
|
+
# end
|
|
67
|
+
# result
|
|
68
|
+
# rescue Exception => e
|
|
69
|
+
# xtrace = e.xtrace
|
|
70
|
+
# ensure
|
|
71
|
+
# response['X-trace'] = xtrace
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# Returns a list of length two, the first element of which is the result
|
|
75
|
+
# of the block, and the second element of which is the oboe context that
|
|
76
|
+
# was set when the block completed execution.
|
|
77
|
+
def start_trace(layer, xtrace = nil, opts = {})
|
|
78
|
+
log_start(layer, xtrace, opts)
|
|
79
|
+
begin
|
|
80
|
+
result = yield
|
|
81
|
+
rescue Exception => e
|
|
82
|
+
log_exception(layer, e)
|
|
83
|
+
e.instance_variable_set(:@xtrace, log_end(layer))
|
|
84
|
+
raise
|
|
85
|
+
end
|
|
86
|
+
xtrace = log_end(layer)
|
|
87
|
+
|
|
88
|
+
[result, xtrace]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Public: Trace a given block of code which can start a trace depending
|
|
92
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
|
93
|
+
# block and report errors. Insert the oboe metadata into the provided for
|
|
94
|
+
# later user.
|
|
95
|
+
#
|
|
96
|
+
# The motivating use case for this is HTTP streaming in rails3. We need
|
|
97
|
+
# access to the exit event's trace id so we can set the header before any
|
|
98
|
+
# work is done, and before any headers are sent back to the client.
|
|
99
|
+
#
|
|
100
|
+
# layer - The layer the block of code belongs to.
|
|
101
|
+
# target - The target object in which to place the oboe metadata.
|
|
102
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
103
|
+
# with the first event of this layer (optional).
|
|
104
|
+
#
|
|
105
|
+
# Example:
|
|
106
|
+
#
|
|
107
|
+
# def handle_request(request, response)
|
|
108
|
+
# # ... code that does something with request and response ...
|
|
109
|
+
# end
|
|
110
|
+
#
|
|
111
|
+
# def handle_request_with_oboe(request, response)
|
|
112
|
+
# start_trace_with_target('rails', request['X-Trace'], response) do
|
|
113
|
+
# handle_request(request, response)
|
|
114
|
+
# end
|
|
115
|
+
# end
|
|
116
|
+
#
|
|
117
|
+
# Returns the result of the block.
|
|
118
|
+
def start_trace_with_target(layer, xtrace, target, opts = {})
|
|
119
|
+
log_start(layer, xtrace, opts)
|
|
120
|
+
exit_evt = TraceView::Context.createEvent
|
|
121
|
+
begin
|
|
122
|
+
target['X-Trace'] = TraceView::Event.metadataString(exit_evt) if TraceView.tracing?
|
|
123
|
+
yield
|
|
124
|
+
rescue Exception => e
|
|
125
|
+
log_exception(layer, e)
|
|
126
|
+
raise
|
|
127
|
+
ensure
|
|
128
|
+
exit_evt.addEdge(TraceView::Context.get)
|
|
129
|
+
log_event(layer, 'exit', exit_evt)
|
|
130
|
+
TraceView::Context.clear
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'pp'
|
|
5
|
+
|
|
6
|
+
module TraceView
|
|
7
|
+
module API
|
|
8
|
+
##
|
|
9
|
+
# General utility methods for the gem
|
|
10
|
+
module Util
|
|
11
|
+
BACKTRACE_CUTOFF = 200
|
|
12
|
+
|
|
13
|
+
# Internal: Check whether the provided key is reserved or not. Reserved
|
|
14
|
+
# keys are either keys that are handled by liboboe calls or the traceview gem.
|
|
15
|
+
#
|
|
16
|
+
# key - the key to check.
|
|
17
|
+
#
|
|
18
|
+
# Return a boolean indicating whether or not key is reserved.
|
|
19
|
+
def valid_key?(key)
|
|
20
|
+
!%w(Label Layer Edge Timestamp Timestamp_u).include? key.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Internal: Get the current backtrace.
|
|
24
|
+
#
|
|
25
|
+
# ignore - Number of frames to ignore at the end of the backtrace. Use
|
|
26
|
+
# when you know how many layers deep in oboe the call is being
|
|
27
|
+
# made.
|
|
28
|
+
#
|
|
29
|
+
# Returns a string with each frame of the backtrace separated by '\r\n'.
|
|
30
|
+
#
|
|
31
|
+
# FIXME: ignore is not currently used (see BACKTRACE_CUTOFF)
|
|
32
|
+
def backtrace(_ignore = 1)
|
|
33
|
+
trim_backtrace(Kernel.caller).join("\r\n")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Internal: Trim a backtrace to a manageable size
|
|
37
|
+
#
|
|
38
|
+
# backtrace - the backtrace (an array of stack frames/from Kernel.caller)
|
|
39
|
+
#
|
|
40
|
+
# Returns a trimmed backtrace
|
|
41
|
+
def trim_backtrace(backtrace)
|
|
42
|
+
return backtrace unless backtrace.is_a?(Array)
|
|
43
|
+
|
|
44
|
+
length = backtrace.size
|
|
45
|
+
if length > BACKTRACE_CUTOFF
|
|
46
|
+
# Trim backtraces by getting the first 180 and last 20 lines
|
|
47
|
+
trimmed = backtrace[0, 180] + ['...[snip]...'] + backtrace[length - 20, 20]
|
|
48
|
+
else
|
|
49
|
+
trimmed = backtrace
|
|
50
|
+
end
|
|
51
|
+
trimmed
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Internal: Check if a host is blacklisted from tracing
|
|
55
|
+
#
|
|
56
|
+
# addr_port - the addr_port from Net::HTTP although this method
|
|
57
|
+
# can be used from any component in reality
|
|
58
|
+
#
|
|
59
|
+
# Returns a boolean on blacklisted state
|
|
60
|
+
def blacklisted?(addr_port)
|
|
61
|
+
return false unless TraceView::Config.blacklist
|
|
62
|
+
|
|
63
|
+
# Ensure that the blacklist is an array
|
|
64
|
+
unless TraceView::Config.blacklist.is_a?(Array)
|
|
65
|
+
val = TraceView::Config[:blacklist]
|
|
66
|
+
TraceView::Config[:blacklist] = [val.to_s]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
TraceView::Config.blacklist.each do |h|
|
|
70
|
+
return true if addr_port.to_s.match(h.to_s)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Internal: Pretty print a list of arguments for reporting
|
|
77
|
+
#
|
|
78
|
+
# args - the list of arguments to work on
|
|
79
|
+
#
|
|
80
|
+
# Returns a pretty string representation of arguments
|
|
81
|
+
def pps(*args)
|
|
82
|
+
old_out = $stdout
|
|
83
|
+
begin
|
|
84
|
+
s = StringIO.new
|
|
85
|
+
$stdout = s
|
|
86
|
+
pp(*args)
|
|
87
|
+
ensure
|
|
88
|
+
$stdout = old_out
|
|
89
|
+
end
|
|
90
|
+
s.string
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Internal: Determine a string to report representing klass
|
|
94
|
+
#
|
|
95
|
+
# args - an instance of a Class, a Class or a Module
|
|
96
|
+
#
|
|
97
|
+
# Returns a string representation of klass
|
|
98
|
+
def get_class_name(klass)
|
|
99
|
+
kv = {}
|
|
100
|
+
|
|
101
|
+
if klass.to_s =~ /::/
|
|
102
|
+
klass.class.to_s.rpartition('::').last
|
|
103
|
+
else
|
|
104
|
+
if klass.is_a?(Class) && klass.is_a?(Module)
|
|
105
|
+
# Class
|
|
106
|
+
kv['Class'] = klass.to_s
|
|
107
|
+
|
|
108
|
+
elsif (!klass.is_a?(Class) && !klass.is_a?(Module))
|
|
109
|
+
# Class instance
|
|
110
|
+
kv['Class'] = klass.class.to_s
|
|
111
|
+
|
|
112
|
+
else
|
|
113
|
+
# Module
|
|
114
|
+
kv['Module'] = klass.to_s
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
kv
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
# Constants from liboboe
|
|
5
|
+
OBOE_TRACE_NEVER = 0
|
|
6
|
+
OBOE_TRACE_ALWAYS = 1
|
|
7
|
+
OBOE_TRACE_THROUGH = 2
|
|
8
|
+
|
|
9
|
+
OBOE_SAMPLE_RATE_SOURCE_FILE = 1
|
|
10
|
+
OBOE_SAMPLE_RATE_SOURCE_DEFAULT = 2
|
|
11
|
+
OBOE_SAMPLE_RATE_SOURCE_OBOE = 3
|
|
12
|
+
OBOE_SAMPLE_RATE_SOURCE_LAST_OBOE = 4
|
|
13
|
+
OBOE_SAMPLE_RATE_SOURCE_DEFAULT_MISCONFIGURED = 5
|
|
14
|
+
OBOE_SAMPLE_RATE_SOURCE_OBOE_DEFAULT = 6
|
|
15
|
+
|
|
16
|
+
# Masks for bitwise ops
|
|
17
|
+
ZERO_MASK = 0b0000000000000000000000000000
|
|
18
|
+
|
|
19
|
+
SAMPLE_RATE_MASK = 0b0000111111111111111111111111
|
|
20
|
+
SAMPLE_SOURCE_MASK = 0b1111000000000000000000000000
|
|
21
|
+
|
|
22
|
+
ZERO_SAMPLE_RATE_MASK = 0b1111000000000000000000000000
|
|
23
|
+
ZERO_SAMPLE_SOURCE_MASK = 0b0000111111111111111111111111
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# This module is the base module for the various implementations of TraceView reporting.
|
|
27
|
+
# Current variations as of 2014-09-10 are a c-extension, JRuby (using TraceView Java
|
|
28
|
+
# instrumentation) and a Heroku c-extension (with embedded tracelyzer)
|
|
29
|
+
module TraceViewBase
|
|
30
|
+
extend ::TraceView::ThreadLocal
|
|
31
|
+
|
|
32
|
+
attr_accessor :reporter
|
|
33
|
+
attr_accessor :loaded
|
|
34
|
+
thread_local :sample_source
|
|
35
|
+
thread_local :sample_rate
|
|
36
|
+
thread_local :layer
|
|
37
|
+
thread_local :layer_op
|
|
38
|
+
|
|
39
|
+
# The following accessors indicate the incoming tracing state received
|
|
40
|
+
# by the rack layer. These are primarily used to identify state
|
|
41
|
+
# between the Ruby and JTraceView instrumentation under JRuby.
|
|
42
|
+
#
|
|
43
|
+
# This is because that even though there may be an incoming
|
|
44
|
+
# X-Trace request header, tracing may have already been started
|
|
45
|
+
# by Joboe. Such a scenario occurs when the application is being
|
|
46
|
+
# hosted by a Java container (such as Tomcat or Glassfish) and
|
|
47
|
+
# JTraceView has already initiated tracing. In this case, we shouldn't
|
|
48
|
+
# pickup the X-Trace context in the X-Trace header and we shouldn't
|
|
49
|
+
# set the outgoing response X-Trace header or clear context.
|
|
50
|
+
# Yeah I know. Yuck.
|
|
51
|
+
|
|
52
|
+
# Occurs only on Jruby. Indicates that Joboe (the java instrumentation)
|
|
53
|
+
# has already started tracing before it hit the JRuby instrumentation.
|
|
54
|
+
thread_local :has_incoming_context
|
|
55
|
+
|
|
56
|
+
# Indicates the existence of a valid X-Trace request header
|
|
57
|
+
thread_local :has_xtrace_header
|
|
58
|
+
|
|
59
|
+
# This indicates that this trace was continued from
|
|
60
|
+
# an incoming X-Trace request header or in the case
|
|
61
|
+
# of JRuby, a trace already started by JTraceView.
|
|
62
|
+
thread_local :is_continued_trace
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# extended
|
|
66
|
+
#
|
|
67
|
+
# Invoked when this module is extended.
|
|
68
|
+
# e.g. extend TraceViewBase
|
|
69
|
+
#
|
|
70
|
+
def self.extended(cls)
|
|
71
|
+
cls.loaded = true
|
|
72
|
+
|
|
73
|
+
# This gives us pretty accessors with questions marks at the end
|
|
74
|
+
# e.g. is_continued_trace --> is_continued_trace?
|
|
75
|
+
TraceView.methods.select{ |m| m =~ /^is_|^has_/ }.each do |c|
|
|
76
|
+
unless c =~ /\?$|=$/
|
|
77
|
+
# TraceView.logger.debug "aliasing #{c}? to #{c}"
|
|
78
|
+
alias_method "#{c}?", c
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# pickup_context
|
|
85
|
+
#
|
|
86
|
+
# Determines whether we should pickup context
|
|
87
|
+
# from an incoming X-Trace request header. The answer
|
|
88
|
+
# is generally yes but there are cases in JRuby under
|
|
89
|
+
# Tomcat (or Glassfish etc.) where tracing may have
|
|
90
|
+
# been already started by the Java instrumentation (Joboe)
|
|
91
|
+
# in which case we don't want to do this.
|
|
92
|
+
#
|
|
93
|
+
def pickup_context?(xtrace)
|
|
94
|
+
return false unless TraceView::XTrace.valid?(xtrace)
|
|
95
|
+
|
|
96
|
+
if defined?(JRUBY_VERSION) && TraceView.tracing?
|
|
97
|
+
return false
|
|
98
|
+
else
|
|
99
|
+
return true
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# tracing_layer?
|
|
105
|
+
#
|
|
106
|
+
# Queries the thread local variable about the current
|
|
107
|
+
# layer being traced. This is used in cases of recursive
|
|
108
|
+
# operation tracing or one instrumented operation calling another.
|
|
109
|
+
#
|
|
110
|
+
def tracing_layer?(layer)
|
|
111
|
+
return TraceView.layer == layer
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
##
|
|
115
|
+
# tracing_layer_op?
|
|
116
|
+
#
|
|
117
|
+
# Queries the thread local variable about the current
|
|
118
|
+
# operation being traced. This is used in cases of recursive
|
|
119
|
+
# operation tracing or one instrumented operation calling another.
|
|
120
|
+
#
|
|
121
|
+
# In such cases, we only want to trace the outermost operation.
|
|
122
|
+
#
|
|
123
|
+
def tracing_layer_op?(operation)
|
|
124
|
+
if operation.is_a?(Array)
|
|
125
|
+
return operation.include?(TraceView.layer_op)
|
|
126
|
+
else
|
|
127
|
+
return TraceView.layer_op == operation
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Returns true if the tracing_mode is set to always.
|
|
133
|
+
# False otherwise
|
|
134
|
+
#
|
|
135
|
+
def always?
|
|
136
|
+
TraceView::Config[:tracing_mode].to_s == 'always'
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
##
|
|
140
|
+
# Returns true if the tracing_mode is set to never.
|
|
141
|
+
# False otherwise
|
|
142
|
+
#
|
|
143
|
+
def never?
|
|
144
|
+
TraceView::Config[:tracing_mode].to_s == 'never'
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Returns true if the tracing_mode is set to always or through.
|
|
149
|
+
# False otherwise
|
|
150
|
+
#
|
|
151
|
+
def passthrough?
|
|
152
|
+
%w(always through).include?(TraceView::Config[:tracing_mode])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
##
|
|
156
|
+
# Returns true if the tracing_mode is set to through.
|
|
157
|
+
# False otherwise
|
|
158
|
+
#
|
|
159
|
+
def through?
|
|
160
|
+
TraceView::Config[:tracing_mode] == 'through'
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
##
|
|
164
|
+
# Returns true if we are currently tracing a request
|
|
165
|
+
# False otherwise
|
|
166
|
+
#
|
|
167
|
+
def tracing?
|
|
168
|
+
return false unless TraceView.loaded
|
|
169
|
+
|
|
170
|
+
TraceView::Context.isValid && !TraceView.never?
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def log(layer, label, options = {})
|
|
174
|
+
# WARN: TraceView.log will be deprecated in a future release. Please use TraceView::API.log instead.
|
|
175
|
+
TraceView::API.log(layer, label, options)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def heroku?
|
|
179
|
+
ENV.key?('TRACEVIEW_URL')
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
##
|
|
183
|
+
# Determines if we are running under a forking webserver
|
|
184
|
+
#
|
|
185
|
+
def forking_webserver?
|
|
186
|
+
if (defined?(::Unicorn) && ($PROGRAM_NAME =~ /unicorn/i)) ||
|
|
187
|
+
(defined?(::Puma) && ($PROGRAM_NAME =~ /puma/i))
|
|
188
|
+
true
|
|
189
|
+
else
|
|
190
|
+
false
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
##
|
|
195
|
+
# Indicates whether a supported framework is in use
|
|
196
|
+
# or not
|
|
197
|
+
#
|
|
198
|
+
def framework?
|
|
199
|
+
defined?(::Rails) or defined?(::Sinatra) or defined?(::Padrino) or defined?(::Grape)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
##
|
|
203
|
+
# These methods should be implemented by the descendants
|
|
204
|
+
# (Oboe_metal, JOboe_metal (JRuby), Heroku_metal)
|
|
205
|
+
#
|
|
206
|
+
def sample?(_opts = {})
|
|
207
|
+
fail 'sample? should be implemented by metal layer.'
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def log(_layer, _label, _options = {})
|
|
211
|
+
fail 'log should be implemented by metal layer.'
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def set_tracing_mode(_mode)
|
|
215
|
+
fail 'set_tracing_mode should be implemented by metal layer.'
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def set_sample_rate(_rate)
|
|
219
|
+
fail 'set_sample_rate should be implemented by metal layer.'
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
module TraceView
|
|
224
|
+
extend TraceViewBase
|
|
225
|
+
end
|