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,159 @@
|
|
|
1
|
+
# AppNeta TraceView Initializer (the oboe gem)
|
|
2
|
+
# http://www.appneta.com/products/traceview/
|
|
3
|
+
#
|
|
4
|
+
# More information on instrumenting Ruby applications can be found here:
|
|
5
|
+
# https://support.appneta.com/cloud/installing-ruby-instrumentation
|
|
6
|
+
|
|
7
|
+
if defined?(TraceView::Config)
|
|
8
|
+
# Tracing Mode determines when traces should be initiated for incoming requests. Valid
|
|
9
|
+
# options are always, through (when using an instrumented Apache or Nginx) and never.
|
|
10
|
+
#
|
|
11
|
+
# If you're not using an instrumented Apache or Nginx, set this directive to always in
|
|
12
|
+
# order to initiate tracing from Ruby.
|
|
13
|
+
TraceView::Config[:tracing_mode] = '<%= @tracing_mode %>'
|
|
14
|
+
|
|
15
|
+
# Verbose output of instrumentation initialization
|
|
16
|
+
# TraceView::Config[:verbose] = <%= @verbose %>
|
|
17
|
+
|
|
18
|
+
# Logging of outgoing HTTP query args
|
|
19
|
+
#
|
|
20
|
+
# This optionally disables the logging of query args of outgoing
|
|
21
|
+
# HTTP clients such as Net::HTTP, excon, typhoeus and others.
|
|
22
|
+
#
|
|
23
|
+
# This flag is global to all HTTP client instrumentation.
|
|
24
|
+
#
|
|
25
|
+
# To configure this on a per instrumentation basis, set this
|
|
26
|
+
# option to true and instead disable the instrumenstation specific
|
|
27
|
+
# option <tt>log_args</tt>:
|
|
28
|
+
#
|
|
29
|
+
# TraceView::Config[:nethttp][:log_args] = false
|
|
30
|
+
# TraceView::Config[:excon][:log_args] = false
|
|
31
|
+
# TraceView::Config[:typhoeus][:log_args] = true
|
|
32
|
+
#
|
|
33
|
+
TraceView::Config[:include_url_query_params] = true
|
|
34
|
+
|
|
35
|
+
# Logging of incoming HTTP query args
|
|
36
|
+
#
|
|
37
|
+
# This optionally disables the logging of incoming URL request
|
|
38
|
+
# query args.
|
|
39
|
+
#
|
|
40
|
+
# This flag is global and currently only affects the Rack
|
|
41
|
+
# instrumentation which reports incoming request URLs and
|
|
42
|
+
# query args by default.
|
|
43
|
+
TraceView::Config[:include_remote_url_params] = true
|
|
44
|
+
|
|
45
|
+
# The oboe Ruby client has the ability to sanitize query literals
|
|
46
|
+
# from SQL statements. By default this is disabled. Enable to
|
|
47
|
+
# avoid collecting and reporting query literals to TraceView.
|
|
48
|
+
# TraceView::Config[:sanitize_sql] = false
|
|
49
|
+
|
|
50
|
+
# Do Not Trace
|
|
51
|
+
# These two values allow you to configure specific URL patterns to
|
|
52
|
+
# never be traced. By default, this is set to common static file
|
|
53
|
+
# extensions but you may want to customize this list for your needs.
|
|
54
|
+
#
|
|
55
|
+
# dnt_regexp and dnt_opts is passed to Regexp.new to create
|
|
56
|
+
# a regular expression object. That is then used to match against
|
|
57
|
+
# the incoming request path.
|
|
58
|
+
#
|
|
59
|
+
# The path string originates from the rack layer and is retrieved
|
|
60
|
+
# as follows:
|
|
61
|
+
#
|
|
62
|
+
# req = ::Rack::Request.new(env)
|
|
63
|
+
# path = URI.unescape(req.path)
|
|
64
|
+
#
|
|
65
|
+
# Usage:
|
|
66
|
+
# TraceView::Config[:dnt_regexp] = "lobster$"
|
|
67
|
+
# TraceView::Config[:dnt_opts] = Regexp::IGNORECASE
|
|
68
|
+
#
|
|
69
|
+
# This will ignore all requests that end with the string lobster
|
|
70
|
+
# regardless of case
|
|
71
|
+
#
|
|
72
|
+
# Requests with positive matches (non nil) will not be traced.
|
|
73
|
+
# See lib/oboe/util.rb: TraceView::Util.static_asset?
|
|
74
|
+
#
|
|
75
|
+
# TraceView::Config[:dnt_regexp] = "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|ttf|woff|svg|less)$"
|
|
76
|
+
# TraceView::Config[:dnt_opts] = Regexp::IGNORECASE
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Rails Exception Logging
|
|
80
|
+
#
|
|
81
|
+
# In Rails, raised exceptions with rescue handlers via
|
|
82
|
+
# <tt>rescue_from</tt> are not reported to the TraceView
|
|
83
|
+
# dashboard by default. Setting this value to true will
|
|
84
|
+
# report all raised exception regardless.
|
|
85
|
+
#
|
|
86
|
+
# TraceView::Config[:report_rescued_errors] = false
|
|
87
|
+
#
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Enabling/Disabling Instrumentation
|
|
91
|
+
#
|
|
92
|
+
# If you're having trouble with one of the instrumentation libraries, they
|
|
93
|
+
# can be individually disabled here by setting the :enabled
|
|
94
|
+
# value to false:
|
|
95
|
+
#
|
|
96
|
+
# TraceView::Config[:action_controller][:enabled] = true
|
|
97
|
+
# TraceView::Config[:active_record][:enabled] = true
|
|
98
|
+
# TraceView::Config[:action_view][:enabled] = true
|
|
99
|
+
# TraceView::Config[:cassandra][:enabled] = true
|
|
100
|
+
# TraceView::Config[:dalli][:enabled] = true
|
|
101
|
+
# TraceView::Config[:excon][:enabled] = true
|
|
102
|
+
# TraceView::Config[:em_http_request][:enabled] = true
|
|
103
|
+
# TraceView::Config[:faraday][:enabled] = true
|
|
104
|
+
# TraceView::Config[:httpclient][:enabled] = true
|
|
105
|
+
# TraceView::Config[:memcache][:enabled] = true
|
|
106
|
+
# TraceView::Config[:memcached][:enabled] = true
|
|
107
|
+
# TraceView::Config[:mongo][:enabled] = true
|
|
108
|
+
# TraceView::Config[:moped][:enabled] = true
|
|
109
|
+
# TraceView::Config[:nethttp][:enabled] = true
|
|
110
|
+
# TraceView::Config[:redis][:enabled] = true
|
|
111
|
+
# TraceView::Config[:resque][:enabled] = true
|
|
112
|
+
# TraceView::Config[:rest_client][:enabled] = true
|
|
113
|
+
# TraceView::Config[:sequel][:enabled] = true
|
|
114
|
+
# TraceView::Config[:typhoeus][:enabled] = true
|
|
115
|
+
#
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Enabling/Disabling Backtrace Collection
|
|
119
|
+
#
|
|
120
|
+
# Instrumentation can optionally collect backtraces as they collect
|
|
121
|
+
# performance metrics. Note that this has a negative impact on
|
|
122
|
+
# performance but can be useful when trying to locate the source of
|
|
123
|
+
# a certain call or operation.
|
|
124
|
+
#
|
|
125
|
+
# TraceView::Config[:action_controller][:collect_backtraces] = true
|
|
126
|
+
# TraceView::Config[:active_record][:collect_backtraces] = true
|
|
127
|
+
# TraceView::Config[:action_view][:collect_backtraces] = true
|
|
128
|
+
# TraceView::Config[:cassandra][:collect_backtraces] = true
|
|
129
|
+
# TraceView::Config[:dalli][:collect_backtraces] = false
|
|
130
|
+
# TraceView::Config[:excon][:collect_backtraces] = false
|
|
131
|
+
# TraceView::Config[:em_http_request][:collect_backtraces] = true
|
|
132
|
+
# TraceView::Config[:faraday][:collect_backtraces] = false
|
|
133
|
+
# TraceView::Config[:httpclient][:collect_backtraces] = false
|
|
134
|
+
# TraceView::Config[:memcache][:collect_backtraces] = false
|
|
135
|
+
# TraceView::Config[:memcached][:collect_backtraces] = false
|
|
136
|
+
# TraceView::Config[:mongo][:collect_backtraces] = true
|
|
137
|
+
# TraceView::Config[:moped][:collect_backtraces] = true
|
|
138
|
+
# TraceView::Config[:nethttp][:collect_backtraces] = true
|
|
139
|
+
# TraceView::Config[:redis][:collect_backtraces] = false
|
|
140
|
+
# TraceView::Config[:resque][:collect_backtraces] = true
|
|
141
|
+
# TraceView::Config[:rest_client][:collect_backtraces] = true
|
|
142
|
+
# TraceView::Config[:sequel][:collect_backtraces] = true
|
|
143
|
+
# TraceView::Config[:typhoeus][:collect_backtraces] = false
|
|
144
|
+
#
|
|
145
|
+
|
|
146
|
+
#
|
|
147
|
+
# Resque Options
|
|
148
|
+
#
|
|
149
|
+
# :link_workers - associates Resque enqueue operations with the jobs they queue by piggybacking
|
|
150
|
+
# an additional argument on the Redis queue that is stripped prior to job
|
|
151
|
+
# processing
|
|
152
|
+
# !!! Note: Make sure both the enqueue side and the Resque workers are instrumented
|
|
153
|
+
# before enabling this or jobs will fail !!!
|
|
154
|
+
# (Default: false)
|
|
155
|
+
# TraceView::Config[:resque][:link_workers] = false
|
|
156
|
+
#
|
|
157
|
+
# Set to true to disable Resque argument logging (Default: false)
|
|
158
|
+
# TraceView::Config[:resque][:log_args] = false
|
|
159
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module API
|
|
6
|
+
##
|
|
7
|
+
# Provides methods related to layer initialization and reporting
|
|
8
|
+
module LayerInit
|
|
9
|
+
# Internal: Report that instrumentation for the given layer has been
|
|
10
|
+
# installed, as well as the version of instrumentation and version of
|
|
11
|
+
# layer.
|
|
12
|
+
#
|
|
13
|
+
def report_init(layer = 'rack')
|
|
14
|
+
# Don't send __Init in development or test
|
|
15
|
+
return if %w(development test).include? ENV['RACK_ENV']
|
|
16
|
+
|
|
17
|
+
# Don't send __Init if the c-extension hasn't loaded
|
|
18
|
+
return unless TraceView.loaded
|
|
19
|
+
|
|
20
|
+
platform_info = TraceView::Util.build_init_report
|
|
21
|
+
|
|
22
|
+
# If already tracing, save and clear the context. Restore it after
|
|
23
|
+
# the __Init is sent
|
|
24
|
+
context = nil
|
|
25
|
+
|
|
26
|
+
if TraceView.tracing?
|
|
27
|
+
context = TraceView::Context.toString
|
|
28
|
+
TraceView::Context.clear
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
start_trace(layer, nil, platform_info.merge('Force' => true)) {}
|
|
32
|
+
|
|
33
|
+
TraceView::Context.fromString(context) if context
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# force_trace has been deprecated and will be removed in a subsequent version.
|
|
38
|
+
#
|
|
39
|
+
def force_trace
|
|
40
|
+
TraceView.logger.warn 'TraceView::API::LayerInit.force_trace has been deprecated and will be ' \
|
|
41
|
+
'removed in a subsequent version.'
|
|
42
|
+
|
|
43
|
+
saved_mode = TraceView::Config[:tracing_mode]
|
|
44
|
+
TraceView::Config[:tracing_mode] = 'always'
|
|
45
|
+
yield
|
|
46
|
+
ensure
|
|
47
|
+
TraceView::Config[:tracing_mode] = saved_mode
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module API
|
|
6
|
+
##
|
|
7
|
+
# This modules provides the X-Trace logging facilities.
|
|
8
|
+
module Logging
|
|
9
|
+
# Public: Report an event in an active trace.
|
|
10
|
+
#
|
|
11
|
+
# layer - The layer the reported event belongs to
|
|
12
|
+
# label - The label for the reported event. See API documentation for
|
|
13
|
+
# reserved labels and usage.
|
|
14
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
15
|
+
# with this event (optional).
|
|
16
|
+
#
|
|
17
|
+
# Example
|
|
18
|
+
#
|
|
19
|
+
# log('logical_layer', 'entry')
|
|
20
|
+
# log('logical_layer', 'info', { :list_length => 20 })
|
|
21
|
+
# log('logical_layer', 'exit')
|
|
22
|
+
#
|
|
23
|
+
# Returns nothing.
|
|
24
|
+
def log(layer, label, opts = {})
|
|
25
|
+
if TraceView.loaded
|
|
26
|
+
log_event(layer, label, TraceView::Context.createEvent, opts)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Public: Report an exception.
|
|
31
|
+
#
|
|
32
|
+
# layer - The layer the reported event belongs to
|
|
33
|
+
# exn - The exception to report
|
|
34
|
+
#
|
|
35
|
+
# Example
|
|
36
|
+
#
|
|
37
|
+
# begin
|
|
38
|
+
# function_without_traceview()
|
|
39
|
+
# rescue Exception => e
|
|
40
|
+
# log_exception('rails', e)
|
|
41
|
+
# raise
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# Returns nothing.
|
|
45
|
+
def log_exception(layer, exn)
|
|
46
|
+
return if !TraceView.loaded || exn.instance_variable_get(:@oboe_logged)
|
|
47
|
+
|
|
48
|
+
kvs = { :ErrorClass => exn.class.name,
|
|
49
|
+
:ErrorMsg => exn.message,
|
|
50
|
+
:Backtrace => exn.backtrace.join("\r\n") }
|
|
51
|
+
|
|
52
|
+
exn.instance_variable_set(:@oboe_logged, true)
|
|
53
|
+
log(layer, 'error', kvs)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Public: Decide whether or not to start a trace, and report an event
|
|
57
|
+
# appropriately.
|
|
58
|
+
#
|
|
59
|
+
# layer - The layer the reported event belongs to
|
|
60
|
+
# xtrace - An xtrace metadata string, or nil.
|
|
61
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
62
|
+
# with this event (optional).
|
|
63
|
+
#
|
|
64
|
+
# Returns nothing.
|
|
65
|
+
def log_start(layer, xtrace = nil, opts = {})
|
|
66
|
+
return if !TraceView.loaded || TraceView.never? ||
|
|
67
|
+
(opts.key?(:URL) && ::TraceView::Util.static_asset?(opts[:URL]))
|
|
68
|
+
|
|
69
|
+
TraceView::Context.fromString(xtrace) if TraceView.pickup_context?(xtrace)
|
|
70
|
+
|
|
71
|
+
if TraceView.tracing?
|
|
72
|
+
# Pre-existing context. Either we inherited context from an
|
|
73
|
+
# incoming X-Trace request header or under JRuby, Joboe started
|
|
74
|
+
# tracing before the JRuby code was called (e.g. Tomcat)
|
|
75
|
+
TraceView.is_continued_trace = true
|
|
76
|
+
|
|
77
|
+
if TraceView.has_xtrace_header
|
|
78
|
+
opts[:TraceOrigin] = :continued_header
|
|
79
|
+
elsif TraceView.has_incoming_context
|
|
80
|
+
opts[:TraceOrigin] = :continued_context
|
|
81
|
+
else
|
|
82
|
+
opts[:TraceOrigin] = :continued
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
log_entry(layer, opts)
|
|
86
|
+
|
|
87
|
+
elsif opts.key?('Force')
|
|
88
|
+
# Forced tracing: used by __Init reporting
|
|
89
|
+
opts[:TraceOrigin] = :forced
|
|
90
|
+
log_event(layer, 'entry', TraceView::Context.startTrace, opts)
|
|
91
|
+
|
|
92
|
+
elsif TraceView.sample?(opts.merge(:layer => layer, :xtrace => xtrace))
|
|
93
|
+
# Probablistic tracing of a subset of requests based off of
|
|
94
|
+
# sample rate and sample source
|
|
95
|
+
opts[:SampleRate] = TraceView.sample_rate
|
|
96
|
+
opts[:SampleSource] = TraceView.sample_source
|
|
97
|
+
opts[:TraceOrigin] = :always_sampled
|
|
98
|
+
|
|
99
|
+
log_event(layer, 'entry', TraceView::Context.startTrace, opts)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Public: Report an exit event.
|
|
104
|
+
#
|
|
105
|
+
# layer - The layer the reported event belongs to
|
|
106
|
+
#
|
|
107
|
+
# Returns an xtrace metadata string
|
|
108
|
+
def log_end(layer, opts = {})
|
|
109
|
+
if TraceView.loaded
|
|
110
|
+
log_event(layer, 'exit', TraceView::Context.createEvent, opts)
|
|
111
|
+
xtrace = TraceView::Context.toString
|
|
112
|
+
TraceView::Context.clear unless TraceView.has_incoming_context?
|
|
113
|
+
xtrace
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# Public: Log an entry event
|
|
119
|
+
#
|
|
120
|
+
# A helper method to create and log an
|
|
121
|
+
# entry event
|
|
122
|
+
#
|
|
123
|
+
# Returns an xtrace metadata string
|
|
124
|
+
def log_entry(layer, kvs = {}, op = nil)
|
|
125
|
+
if TraceView.loaded
|
|
126
|
+
TraceView.layer_op = op if op
|
|
127
|
+
log_event(layer, 'entry', TraceView::Context.createEvent, kvs)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Public: Log an info event
|
|
133
|
+
#
|
|
134
|
+
# A helper method to create and log an
|
|
135
|
+
# info event
|
|
136
|
+
#
|
|
137
|
+
# Returns an xtrace metadata string
|
|
138
|
+
def log_info(layer, kvs = {})
|
|
139
|
+
if TraceView.loaded
|
|
140
|
+
log_event(layer, 'info', TraceView::Context.createEvent, kvs)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
##
|
|
145
|
+
# Public: Log an exit event
|
|
146
|
+
#
|
|
147
|
+
# A helper method to create and log an
|
|
148
|
+
# exit event
|
|
149
|
+
#
|
|
150
|
+
# Returns an xtrace metadata string
|
|
151
|
+
def log_exit(layer, kvs = {}, op = nil)
|
|
152
|
+
if TraceView.loaded
|
|
153
|
+
TraceView.layer_op = nil if op
|
|
154
|
+
log_event(layer, 'exit', TraceView::Context.createEvent, kvs)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Internal: Report an event.
|
|
159
|
+
#
|
|
160
|
+
# layer - The layer the reported event belongs to
|
|
161
|
+
# label - The label for the reported event. See API documentation for
|
|
162
|
+
# reserved labels and usage.
|
|
163
|
+
# opts - A hash containing key/value pairs that will be reported along
|
|
164
|
+
# with this event (optional).
|
|
165
|
+
#
|
|
166
|
+
# Examples
|
|
167
|
+
#
|
|
168
|
+
# entry = TraceView::Context.createEvent
|
|
169
|
+
# log_event('rails', 'entry', exit, { :controller => 'user', :action => 'index' })
|
|
170
|
+
# exit = TraceView::Context.createEvent
|
|
171
|
+
# exit.addEdge(entry.getMetadata)
|
|
172
|
+
# log_event('rails', 'exit', exit)
|
|
173
|
+
#
|
|
174
|
+
# Returns nothing.
|
|
175
|
+
def log_event(layer, label, event, opts = {})
|
|
176
|
+
if TraceView.loaded
|
|
177
|
+
event.addInfo('Layer', layer.to_s) if layer
|
|
178
|
+
event.addInfo('Label', label.to_s)
|
|
179
|
+
|
|
180
|
+
TraceView.layer = layer if label == 'entry'
|
|
181
|
+
TraceView.layer = nil if label == 'exit'
|
|
182
|
+
|
|
183
|
+
opts.each do |k, v|
|
|
184
|
+
value = nil
|
|
185
|
+
|
|
186
|
+
if valid_key? k
|
|
187
|
+
if [Integer, Float, Fixnum, NilClass, String].include?(v.class)
|
|
188
|
+
value = v
|
|
189
|
+
elsif v.class == Set
|
|
190
|
+
value = v.to_a.to_s
|
|
191
|
+
else
|
|
192
|
+
value = v.to_s if v.respond_to?(:to_s)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
begin
|
|
196
|
+
event.addInfo(k.to_s, value)
|
|
197
|
+
rescue ArgumentError => e
|
|
198
|
+
TraceView.logger.debug "[TraceView/debug] Couldn't add event KV: #{k.to_s} => #{v.class}"
|
|
199
|
+
TraceView.logger.debug "[TraceView/debug] #{e.message}"
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end if !opts.nil? && opts.any?
|
|
203
|
+
|
|
204
|
+
TraceView::Reporter.sendReport(event)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -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
|