appoptics_apm 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +43 -0
- data/.dockerignore +5 -0
- data/.gitignore +23 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +82 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Dockerfile +41 -0
- data/Dockerfile_test +66 -0
- data/Gemfile +41 -0
- data/LICENSE +193 -0
- data/README.md +351 -0
- data/Rakefile +202 -0
- data/Vagrantfile +67 -0
- data/appoptics_apm.gemspec +55 -0
- data/build_gems.sh +15 -0
- data/docker-compose.yml +73 -0
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +220 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +124 -0
- data/examples/tracing_background_jobs.rb +53 -0
- data/examples/tracing_forked_processes.rb +99 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/extconf.rb +54 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0.so.0.0.0 +0 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/VERSION +1 -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 +883 -0
- data/ext/oboe_metal/src/oboe.hpp +793 -0
- data/ext/oboe_metal/src/oboe_debug.h +50 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +6088 -0
- data/ext/oboe_metal/tests/test.rb +11 -0
- data/gemfiles/delayed_job.gemfile +36 -0
- data/gemfiles/frameworks.gemfile +44 -0
- data/gemfiles/instrumentation_mocked.gemfile +29 -0
- data/gemfiles/libraries.gemfile +85 -0
- data/gemfiles/rails23.gemfile +39 -0
- data/gemfiles/rails30.gemfile +42 -0
- data/gemfiles/rails31.gemfile +44 -0
- data/gemfiles/rails32.gemfile +54 -0
- data/gemfiles/rails40.gemfile +27 -0
- data/gemfiles/rails41.gemfile +27 -0
- data/gemfiles/rails42.gemfile +35 -0
- data/gemfiles/rails50.gemfile +44 -0
- data/gemfiles/rails51.gemfile +44 -0
- data/get_version.rb +5 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm/api/layerinit.rb +39 -0
- data/lib/appoptics_apm/api/logging.rb +359 -0
- data/lib/appoptics_apm/api/memcache.rb +34 -0
- data/lib/appoptics_apm/api/profiling.rb +201 -0
- data/lib/appoptics_apm/api/tracing.rb +152 -0
- data/lib/appoptics_apm/api/util.rb +128 -0
- data/lib/appoptics_apm/api.rb +18 -0
- data/lib/appoptics_apm/base.rb +252 -0
- data/lib/appoptics_apm/config.rb +281 -0
- data/lib/appoptics_apm/frameworks/grape.rb +93 -0
- data/lib/appoptics_apm/frameworks/padrino/templates.rb +58 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +52 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +106 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller2.rb +61 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_2x.rb +56 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +120 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +101 -0
- data/lib/appoptics_apm/frameworks/rails.rb +116 -0
- data/lib/appoptics_apm/frameworks/sinatra/templates.rb +56 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +71 -0
- data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
- data/lib/appoptics_apm/inst/bunny-consumer.rb +92 -0
- data/lib/appoptics_apm/inst/curb.rb +329 -0
- data/lib/appoptics_apm/inst/dalli.rb +85 -0
- data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
- data/lib/appoptics_apm/inst/em-http-request.rb +105 -0
- data/lib/appoptics_apm/inst/excon.rb +130 -0
- data/lib/appoptics_apm/inst/faraday.rb +77 -0
- data/lib/appoptics_apm/inst/http.rb +83 -0
- data/lib/appoptics_apm/inst/httpclient.rb +176 -0
- data/lib/appoptics_apm/inst/memcache.rb +102 -0
- data/lib/appoptics_apm/inst/memcached.rb +94 -0
- data/lib/appoptics_apm/inst/mongo.rb +242 -0
- data/lib/appoptics_apm/inst/mongo2.rb +225 -0
- data/lib/appoptics_apm/inst/moped.rb +466 -0
- data/lib/appoptics_apm/inst/rack.rb +146 -0
- data/lib/appoptics_apm/inst/redis.rb +275 -0
- data/lib/appoptics_apm/inst/resque.rb +151 -0
- data/lib/appoptics_apm/inst/rest-client.rb +50 -0
- data/lib/appoptics_apm/inst/sequel.rb +178 -0
- data/lib/appoptics_apm/inst/sidekiq-client.rb +53 -0
- data/lib/appoptics_apm/inst/sidekiq-worker.rb +67 -0
- data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
- data/lib/appoptics_apm/inst/typhoeus.rb +113 -0
- data/lib/appoptics_apm/instrumentation.rb +22 -0
- data/lib/appoptics_apm/legacy_method_profiling.rb +97 -0
- data/lib/appoptics_apm/loading.rb +66 -0
- data/lib/appoptics_apm/logger.rb +41 -0
- data/lib/appoptics_apm/method_profiling.rb +33 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/support.rb +135 -0
- data/lib/appoptics_apm/test.rb +94 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +312 -0
- data/lib/appoptics_apm/version.rb +15 -0
- data/lib/appoptics_apm/xtrace.rb +103 -0
- data/lib/appoptics_apm.rb +72 -0
- data/lib/joboe_metal.rb +214 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +80 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +187 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +222 -0
- data/ruby_setup.sh +47 -0
- data/run_docker_build_gem_upload_to_packagecloud.sh +20 -0
- data/run_tests_docker.rb +32 -0
- data/test/benchmark/README.md +65 -0
- data/test/benchmark/logging_bench.rb +54 -0
- data/test/benchmark/with_libraries_gemfile/bunny_bench.rb +69 -0
- data/test/benchmark/with_rails5x_gemfile/action_controller5x_bench.rb +43 -0
- data/test/frameworks/apps/grape_nested.rb +33 -0
- data/test/frameworks/apps/grape_simple.rb +80 -0
- data/test/frameworks/apps/padrino_simple.rb +80 -0
- data/test/frameworks/apps/sinatra_simple.rb +55 -0
- data/test/frameworks/grape_test.rb +286 -0
- data/test/frameworks/padrino_test.rb +222 -0
- data/test/frameworks/rails3x_test.rb +554 -0
- data/test/frameworks/rails4x_test.rb +570 -0
- data/test/frameworks/rails5x_api_test.rb +210 -0
- data/test/frameworks/rails5x_test.rb +376 -0
- data/test/frameworks/rails_shared_tests.rb +172 -0
- data/test/frameworks/sinatra_test.rb +140 -0
- data/test/instrumentation/bunny_client_test.rb +276 -0
- data/test/instrumentation/bunny_consumer_test.rb +204 -0
- data/test/instrumentation/curb_test.rb +398 -0
- data/test/instrumentation/dalli_test.rb +177 -0
- data/test/instrumentation/em_http_request_test.rb +89 -0
- data/test/instrumentation/excon_test.rb +231 -0
- data/test/instrumentation/faraday_test.rb +228 -0
- data/test/instrumentation/http_test.rb +143 -0
- data/test/instrumentation/httpclient_test.rb +320 -0
- data/test/instrumentation/memcache_test.rb +260 -0
- data/test/instrumentation/memcached_test.rb +229 -0
- data/test/instrumentation/mongo_v1_test.rb +479 -0
- data/test/instrumentation/mongo_v2_index_test.rb +124 -0
- data/test/instrumentation/mongo_v2_test.rb +584 -0
- data/test/instrumentation/mongo_v2_view_test.rb +435 -0
- data/test/instrumentation/moped_test.rb +517 -0
- data/test/instrumentation/rack_test.rb +165 -0
- data/test/instrumentation/redis_hashes_test.rb +268 -0
- data/test/instrumentation/redis_keys_test.rb +321 -0
- data/test/instrumentation/redis_lists_test.rb +310 -0
- data/test/instrumentation/redis_misc_test.rb +163 -0
- data/test/instrumentation/redis_sets_test.rb +296 -0
- data/test/instrumentation/redis_sortedsets_test.rb +328 -0
- data/test/instrumentation/redis_strings_test.rb +349 -0
- data/test/instrumentation/resque_test.rb +185 -0
- data/test/instrumentation/rest-client_test.rb +288 -0
- data/test/instrumentation/sequel_mysql2_test.rb +353 -0
- data/test/instrumentation/sequel_mysql_test.rb +334 -0
- data/test/instrumentation/sequel_pg_test.rb +336 -0
- data/test/instrumentation/sidekiq-client_test.rb +159 -0
- data/test/instrumentation/sidekiq-worker_test.rb +180 -0
- data/test/instrumentation/twitter-cassandra_test.rb +424 -0
- data/test/instrumentation/typhoeus_test.rb +284 -0
- data/test/jobs/delayed_job/db_worker_job.rb +29 -0
- data/test/jobs/delayed_job/error_worker_job.rb +10 -0
- data/test/jobs/delayed_job/remote_call_worker_job.rb +20 -0
- data/test/jobs/resque/db_worker_job.rb +29 -0
- data/test/jobs/resque/error_worker_job.rb +10 -0
- data/test/jobs/resque/remote_call_worker_job.rb +20 -0
- data/test/jobs/sidekiq/db_worker_job.rb +29 -0
- data/test/jobs/sidekiq/error_worker_job.rb +10 -0
- data/test/jobs/sidekiq/remote_call_worker_job.rb +20 -0
- data/test/minitest_helper.rb +276 -0
- data/test/mocked/curb_mocked_test.rb +311 -0
- data/test/mocked/excon_mocked_test.rb +166 -0
- data/test/mocked/faraday_mocked_test.rb +93 -0
- data/test/mocked/http_mocked_test.rb +129 -0
- data/test/mocked/httpclient_mocked_test.rb +245 -0
- data/test/mocked/rest_client_mocked_test.rb +103 -0
- data/test/mocked/typhoeus_mocked_test.rb +192 -0
- data/test/models/widget.rb +36 -0
- data/test/profiling/legacy_method_profiling_test.rb +201 -0
- data/test/profiling/method_profiling_test.rb +631 -0
- data/test/queues/delayed_job-client_test.rb +95 -0
- data/test/queues/delayed_job-worker_test.rb +91 -0
- data/test/reporter/reporter_test.rb +14 -0
- data/test/servers/delayed_job.rb +107 -0
- data/test/servers/rackapp_8101.rb +29 -0
- data/test/servers/rails3x_8140.rb +96 -0
- data/test/servers/rails4x_8140.rb +96 -0
- data/test/servers/rails5x_8140.rb +95 -0
- data/test/servers/rails5x_api_8150.rb +78 -0
- data/test/servers/sidekiq.rb +29 -0
- data/test/servers/sidekiq.yml +7 -0
- data/test/servers/sidekiq_initializer.rb +25 -0
- data/test/settings +0 -0
- data/test/support/auto_tracing_test.rb +50 -0
- data/test/support/backcompat_test.rb +276 -0
- data/test/support/config_test.rb +149 -0
- data/test/support/dnt_test.rb +98 -0
- data/test/support/init_report_test.rb +25 -0
- data/test/support/liboboe_settings_test.rb +110 -0
- data/test/support/logging_test.rb +130 -0
- data/test/support/noop_test.rb +88 -0
- data/test/support/sql_sanitize_test.rb +55 -0
- data/test/support/tracing_mode_test.rb +33 -0
- data/test/support/tvalias_test.rb +15 -0
- data/test/support/xtrace_test.rb +41 -0
- metadata +475 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module API
|
8
|
+
##
|
9
|
+
# Provides the higher-level tracing interface for the API.
|
10
|
+
#
|
11
|
+
# Traces are best created with a <tt>AppOpticsAPM:API.start_trace</tt> block and
|
12
|
+
# <tt>AppOpticsAPM:API.trace</tt> blocks around calls to be traced.
|
13
|
+
# These two methods guarantee proper nesting of tracing and handling of the tracing context.
|
14
|
+
#
|
15
|
+
# Some optional keys that can be used in the +opts+ hash:
|
16
|
+
# * +:TransactionName+ - this will show up in the transactions column in the traces dashboard
|
17
|
+
# * +:Controller+ - if present will be combined with +Action+ and show up as transaction in the traces dashboard
|
18
|
+
# * +:Action+ - if present will be combined with +Controller+ and show up as transaction in the traces dashboard
|
19
|
+
# * +:HTTP-Host+ - domain portion of URL
|
20
|
+
# * +:URL+ - request URI
|
21
|
+
# * +:Method+
|
22
|
+
#
|
23
|
+
# Invalid keys: +:Label+, +:Layer+, +:Edge+, +:Timestamp+, +:Timestamp_u+
|
24
|
+
#
|
25
|
+
module Tracing
|
26
|
+
# Public: Trace a given block of code. Detect any exceptions thrown by
|
27
|
+
# the block and report errors.
|
28
|
+
#
|
29
|
+
# * +:layer+ - The layer the block of code belongs to.
|
30
|
+
# * +:opts+ - A hash containing key/value pairs that will be reported along
|
31
|
+
# with the first event of this layer (optional).
|
32
|
+
# * +:protect_op+ - The operation being traced. Used to avoid
|
33
|
+
# double tracing operations that call each other
|
34
|
+
#
|
35
|
+
# Example
|
36
|
+
#
|
37
|
+
# def computation(n)
|
38
|
+
# fib(n)
|
39
|
+
# raise Exception.new
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# def computation_with_oboe(n)
|
43
|
+
# trace('fib', { :number => n }, :fib) do
|
44
|
+
# computation(n)
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# result = computation_with_oboe(1000)
|
49
|
+
#
|
50
|
+
# Returns the result of the block.
|
51
|
+
def trace(layer, opts = {}, protect_op = nil)
|
52
|
+
log_entry(layer, opts, protect_op)
|
53
|
+
begin
|
54
|
+
yield
|
55
|
+
rescue Exception => e
|
56
|
+
log_exception(layer, e)
|
57
|
+
raise
|
58
|
+
ensure
|
59
|
+
log_exit(layer)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Public: Trace a given block of code which can start a trace depending
|
64
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
65
|
+
# block and report errors.
|
66
|
+
#
|
67
|
+
# When start_trace returns control to the calling context, the oboe
|
68
|
+
# context will be cleared.
|
69
|
+
#
|
70
|
+
# layer - The layer the block of code belongs to.
|
71
|
+
# opts - A hash containing key/value pairs that will be reported along
|
72
|
+
# with the first event of this layer (optional).
|
73
|
+
#
|
74
|
+
# Example
|
75
|
+
#
|
76
|
+
# def handle_request(request, response)
|
77
|
+
# # ... code that modifies request and response ...
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# def handle_request_with_oboe(request, response)
|
81
|
+
# result, xtrace = start_trace('rails', request['X-Trace']) do
|
82
|
+
# handle_request(request, response)
|
83
|
+
# end
|
84
|
+
# result
|
85
|
+
# rescue Exception => e
|
86
|
+
# xtrace = e.xtrace
|
87
|
+
# ensure
|
88
|
+
# response['X-trace'] = xtrace
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# Returns a list of length two, the first element of which is the result
|
92
|
+
# of the block, and the second element of which is the oboe context that
|
93
|
+
# was set when the block completed execution.
|
94
|
+
def start_trace(layer, xtrace = nil, opts = {})
|
95
|
+
log_start(layer, xtrace, opts)
|
96
|
+
begin
|
97
|
+
result = yield
|
98
|
+
rescue Exception => e
|
99
|
+
log_exception(layer, e)
|
100
|
+
e.instance_variable_set(:@xtrace, log_end(layer))
|
101
|
+
raise
|
102
|
+
end
|
103
|
+
xtrace = log_end(layer)
|
104
|
+
|
105
|
+
[result, xtrace]
|
106
|
+
end
|
107
|
+
|
108
|
+
# Public: Trace a given block of code which can start a trace depending
|
109
|
+
# on configuration and probability. Detect any exceptions thrown by the
|
110
|
+
# block and report errors. Assign an X-Trace to the target.
|
111
|
+
#
|
112
|
+
# The motivating use case for this is HTTP streaming in rails3. We need
|
113
|
+
# access to the exit event's trace id so we can set the header before any
|
114
|
+
# work is done, and before any headers are sent back to the client.
|
115
|
+
#
|
116
|
+
# layer - The layer the block of code belongs to.
|
117
|
+
# xtrace - string - The X-Trace to continue by the target
|
118
|
+
# target - has to respond to #[]=, The target object in which to place the trace information
|
119
|
+
# opts - A hash containing key/value pairs that will be reported along
|
120
|
+
# with the first event of this layer (optional).
|
121
|
+
#
|
122
|
+
# Example:
|
123
|
+
#
|
124
|
+
# def handle_request(request, response)
|
125
|
+
# # ... code that does something with request and response ...
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
# def handle_request_with_oboe(request, response)
|
129
|
+
# start_trace_with_target('rails', request['X-Trace'], response) do
|
130
|
+
# handle_request(request, response)
|
131
|
+
# end
|
132
|
+
# end
|
133
|
+
#
|
134
|
+
# Returns the result of the block.
|
135
|
+
def start_trace_with_target(layer, xtrace, target, opts = {})
|
136
|
+
log_start(layer, xtrace, opts)
|
137
|
+
exit_evt = AppOpticsAPM::Context.createEvent
|
138
|
+
begin
|
139
|
+
target['X-Trace'] = AppOpticsAPM::EventUtil.metadataString(exit_evt) if AppOpticsAPM.tracing?
|
140
|
+
yield
|
141
|
+
rescue Exception => e
|
142
|
+
log_exception(layer, e)
|
143
|
+
raise
|
144
|
+
ensure
|
145
|
+
exit_evt.addEdge(AppOpticsAPM::Context.get)
|
146
|
+
log(layer, :exit, {}, exit_evt)
|
147
|
+
AppOpticsAPM::Context.clear
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
module AppOpticsAPM
|
9
|
+
module API
|
10
|
+
##
|
11
|
+
# General utility methods for the gem
|
12
|
+
module Util
|
13
|
+
BACKTRACE_CUTOFF = 200
|
14
|
+
|
15
|
+
# Internal: Check whether the provided key is reserved or not. Reserved
|
16
|
+
# keys are either keys that are handled by liboboe calls or the appoptics_apm gem.
|
17
|
+
#
|
18
|
+
# key - the key to check.
|
19
|
+
#
|
20
|
+
# Return a boolean indicating whether or not key is reserved.
|
21
|
+
def valid_key?(key)
|
22
|
+
![:Label, :Layer, :Edge, :Timestamp, :Timestamp_u].include?(key.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Internal: Get the current backtrace.
|
26
|
+
#
|
27
|
+
# ignore - Number of frames to ignore at the top of the backtrace. Use
|
28
|
+
# when you know how many layers deep in the key call is being
|
29
|
+
# made.
|
30
|
+
#
|
31
|
+
# Returns a string with each frame of the backtrace separated by '\r\n'.
|
32
|
+
#
|
33
|
+
def backtrace(ignore = 0)
|
34
|
+
bt = Kernel.caller
|
35
|
+
bt.slice!(0, ignore)
|
36
|
+
trim_backtrace(bt).join("\r\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Internal: Trim a backtrace to a manageable size
|
40
|
+
#
|
41
|
+
# backtrace - the backtrace (an array of stack frames/from Kernel.caller)
|
42
|
+
#
|
43
|
+
# Returns a trimmed backtrace
|
44
|
+
def trim_backtrace(backtrace)
|
45
|
+
return backtrace unless backtrace.is_a?(Array)
|
46
|
+
|
47
|
+
length = backtrace.size
|
48
|
+
if length > BACKTRACE_CUTOFF
|
49
|
+
# Trim backtraces by getting the first 180 and last 20 lines
|
50
|
+
trimmed = backtrace[0, 180] + ['...[snip]...'] + backtrace[length - 20, 20]
|
51
|
+
else
|
52
|
+
trimmed = backtrace
|
53
|
+
end
|
54
|
+
trimmed
|
55
|
+
end
|
56
|
+
|
57
|
+
# Internal: Check if a host is blacklisted from tracing
|
58
|
+
#
|
59
|
+
# addr_port - the addr_port from Net::HTTP although this method
|
60
|
+
# can be used from any component in reality
|
61
|
+
#
|
62
|
+
# Returns a boolean on blacklisted state
|
63
|
+
def blacklisted?(addr_port)
|
64
|
+
return false unless AppOpticsAPM::Config.blacklist
|
65
|
+
|
66
|
+
# Ensure that the blacklist is an array
|
67
|
+
unless AppOpticsAPM::Config.blacklist.is_a?(Array)
|
68
|
+
val = AppOpticsAPM::Config[:blacklist]
|
69
|
+
AppOpticsAPM::Config[:blacklist] = [val.to_s]
|
70
|
+
end
|
71
|
+
|
72
|
+
AppOpticsAPM::Config.blacklist.each do |h|
|
73
|
+
return true if addr_port.to_s.match(h.to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
# Internal: Pretty print a list of arguments for reporting
|
80
|
+
#
|
81
|
+
# args - the list of arguments to work on
|
82
|
+
#
|
83
|
+
# Returns a pretty string representation of arguments
|
84
|
+
def pps(*args)
|
85
|
+
old_out = $stdout
|
86
|
+
begin
|
87
|
+
s = StringIO.new
|
88
|
+
$stdout = s
|
89
|
+
pp(*args)
|
90
|
+
ensure
|
91
|
+
$stdout = old_out
|
92
|
+
end
|
93
|
+
s.string
|
94
|
+
end
|
95
|
+
|
96
|
+
# Internal: Determine a string to report representing klass
|
97
|
+
#
|
98
|
+
# args - an instance of a Class, a Class or a Module
|
99
|
+
#
|
100
|
+
# Returns a string representation of klass
|
101
|
+
def get_class_name(klass)
|
102
|
+
kv = {}
|
103
|
+
|
104
|
+
if klass.to_s =~ /::/
|
105
|
+
klass.class.to_s.rpartition('::').last
|
106
|
+
else
|
107
|
+
if klass.is_a?(Class) && klass.is_a?(Module)
|
108
|
+
# Class
|
109
|
+
kv['Class'] = klass.to_s
|
110
|
+
|
111
|
+
elsif !klass.is_a?(Class) && !klass.is_a?(Module)
|
112
|
+
# Class instance
|
113
|
+
kv['Class'] = klass.class.to_s
|
114
|
+
|
115
|
+
else
|
116
|
+
# Module
|
117
|
+
kv['Module'] = klass.to_s
|
118
|
+
end
|
119
|
+
end
|
120
|
+
kv
|
121
|
+
end
|
122
|
+
|
123
|
+
def xtrace_v2?(xtr)
|
124
|
+
return xtr && xtr.start_with?('2B')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
##
|
6
|
+
# This module implements the AppOpticsAPM tracing API.
|
7
|
+
# See: https://github.com/librato/ruby-appoptics#the-tracing-api
|
8
|
+
# and/or: http://rdoc.info/gems/appoptics_apm/AppOpticsAPM/API/Tracing
|
9
|
+
module API
|
10
|
+
def self.extend_with_tracing
|
11
|
+
extend AppOpticsAPM::API::Logging
|
12
|
+
extend AppOpticsAPM::API::Tracing
|
13
|
+
extend AppOpticsAPM::API::Profiling
|
14
|
+
extend AppOpticsAPM::API::LayerInit
|
15
|
+
end
|
16
|
+
extend AppOpticsAPM::API::Util
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
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
|
+
APPOPTICS_STR_BLANK = ''.freeze
|
26
|
+
APPOPTICS_STR_LAYER = 'Layer'.freeze
|
27
|
+
APPOPTICS_STR_LABEL = 'Label'.freeze
|
28
|
+
|
29
|
+
# Used in tests to store local trace data
|
30
|
+
TRACE_FILE = '/tmp/appoptics_traces.bson'.freeze
|
31
|
+
|
32
|
+
##
|
33
|
+
# This module is the base module for the various implementations of AppOpticsAPM reporting.
|
34
|
+
# Current variations as of 2014-09-10 are a c-extension, JRuby (using AppOpticsAPM Java
|
35
|
+
# instrumentation) and a Heroku c-extension (with embedded tracelyzer)
|
36
|
+
module AppOpticsAPMBase
|
37
|
+
extend ::AppOpticsAPM::ThreadLocal
|
38
|
+
|
39
|
+
attr_accessor :reporter
|
40
|
+
attr_accessor :loaded
|
41
|
+
thread_local :sample_source
|
42
|
+
thread_local :sample_rate
|
43
|
+
thread_local :layer
|
44
|
+
thread_local :layer_op
|
45
|
+
# Semaphore used during the test suite to test
|
46
|
+
# global config options.
|
47
|
+
thread_local :config_lock
|
48
|
+
|
49
|
+
# The following accessors indicate the incoming tracing state received
|
50
|
+
# by the rack layer. These are primarily used to identify state
|
51
|
+
# between the Ruby and JAppOpticsAPM instrumentation under JRuby.
|
52
|
+
#
|
53
|
+
# This is because that even though there may be an incoming
|
54
|
+
# X-Trace request header, tracing may have already been started
|
55
|
+
# by Joboe. Such a scenario occurs when the application is being
|
56
|
+
# hosted by a Java container (such as Tomcat or Glassfish) and
|
57
|
+
# JAppOpticsAPM has already initiated tracing. In this case, we shouldn't
|
58
|
+
# pickup the X-Trace context in the X-Trace header and we shouldn't
|
59
|
+
# set the outgoing response X-Trace header or clear context.
|
60
|
+
# Yeah I know. Yuck.
|
61
|
+
|
62
|
+
# Occurs only on Jruby. Indicates that Joboe (the java instrumentation)
|
63
|
+
# has already started tracing before it hit the JRuby instrumentation.
|
64
|
+
thread_local :has_incoming_context
|
65
|
+
|
66
|
+
# Indicates the existence of a valid X-Trace request header
|
67
|
+
thread_local :has_xtrace_header
|
68
|
+
|
69
|
+
# This indicates that this trace was continued from
|
70
|
+
# an incoming X-Trace request header or in the case
|
71
|
+
# of JRuby, a trace already started by JAppOpticsAPM.
|
72
|
+
thread_local :is_continued_trace
|
73
|
+
|
74
|
+
##
|
75
|
+
# extended
|
76
|
+
#
|
77
|
+
# Invoked when this module is extended.
|
78
|
+
# e.g. extend AppOpticsAPMBase
|
79
|
+
#
|
80
|
+
def self.extended(cls)
|
81
|
+
cls.loaded = true
|
82
|
+
|
83
|
+
# This gives us pretty accessors with questions marks at the end
|
84
|
+
# e.g. is_continued_trace --> is_continued_trace?
|
85
|
+
AppOpticsAPM.methods.select { |m| m =~ /^is_|^has_/ }.each do |c|
|
86
|
+
unless c =~ /\?$|=$/
|
87
|
+
# AppOpticsAPM.logger.debug "aliasing #{c}? to #{c}"
|
88
|
+
alias_method "#{c}?", c
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# pickup_context
|
95
|
+
#
|
96
|
+
# Determines whether we should pickup context
|
97
|
+
# from an incoming X-Trace request header. The answer
|
98
|
+
# is generally yes but there are cases in JRuby under
|
99
|
+
# Tomcat (or Glassfish etc.) where tracing may have
|
100
|
+
# been already started by the Java instrumentation (Joboe)
|
101
|
+
# in which case we don't want to do this.
|
102
|
+
#
|
103
|
+
def pickup_context?(xtrace)
|
104
|
+
return false unless AppOpticsAPM::XTrace.valid?(xtrace)
|
105
|
+
|
106
|
+
if defined?(JRUBY_VERSION) && AppOpticsAPM.tracing?
|
107
|
+
return false
|
108
|
+
else
|
109
|
+
return true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# tracing_layer?
|
115
|
+
#
|
116
|
+
# Queries the thread local variable about the current
|
117
|
+
# layer being traced. This is used in cases of recursive
|
118
|
+
# operation tracing or one instrumented operation calling another.
|
119
|
+
#
|
120
|
+
def tracing_layer?(layer)
|
121
|
+
AppOpticsAPM.layer == layer.to_sym
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# tracing_layer_op?
|
126
|
+
#
|
127
|
+
# Queries the thread local variable about the current
|
128
|
+
# operation being traced. This is used in cases of recursive
|
129
|
+
# operation tracing or one instrumented operation calling another.
|
130
|
+
#
|
131
|
+
# <operation> can be a single symbol or an array of symbols that
|
132
|
+
# will be checked against.
|
133
|
+
#
|
134
|
+
# In such cases, we only want to trace the outermost operation.
|
135
|
+
#
|
136
|
+
def tracing_layer_op?(operation)
|
137
|
+
if operation.is_a?(Array)
|
138
|
+
operation.include?(AppOpticsAPM.layer_op)
|
139
|
+
else
|
140
|
+
AppOpticsAPM.layer_op == operation.to_sym
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Returns true if the tracing_mode is set to always.
|
146
|
+
# False otherwise
|
147
|
+
#
|
148
|
+
def always?
|
149
|
+
AppOpticsAPM::Config[:tracing_mode] &&
|
150
|
+
AppOpticsAPM::Config[:tracing_mode].to_sym == :always
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Returns true if the tracing_mode is set to never.
|
155
|
+
# False otherwise
|
156
|
+
#
|
157
|
+
def never?
|
158
|
+
AppOpticsAPM::Config[:tracing_mode] &&
|
159
|
+
AppOpticsAPM::Config[:tracing_mode].to_sym == :never
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Returns true if we are currently tracing a request
|
164
|
+
# False otherwise
|
165
|
+
#
|
166
|
+
def tracing?
|
167
|
+
return false if !AppOpticsAPM.loaded || AppOpticsAPM.never?
|
168
|
+
AppOpticsAPM::Context.isSampled
|
169
|
+
end
|
170
|
+
|
171
|
+
def heroku?
|
172
|
+
ENV.key?('APPOPTICS_URL')
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Determines if we are running under a forking webserver
|
177
|
+
#
|
178
|
+
def forking_webserver?
|
179
|
+
if (defined?(::Unicorn) && ($PROGRAM_NAME =~ /unicorn/i)) ||
|
180
|
+
(defined?(::Puma) && ($PROGRAM_NAME =~ /puma/i))
|
181
|
+
true
|
182
|
+
else
|
183
|
+
false
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Debugging helper method
|
189
|
+
#
|
190
|
+
def pry!
|
191
|
+
# Only valid for development or test environments
|
192
|
+
env = ENV['RACK_ENV'] || ENV['RAILS_ENV']
|
193
|
+
return unless %w(development, test).include? env
|
194
|
+
|
195
|
+
if RUBY_VERSION > '1.9.3'
|
196
|
+
require 'pry'
|
197
|
+
require 'pry-byebug'
|
198
|
+
|
199
|
+
if defined?(PryByebug)
|
200
|
+
Pry.commands.alias_command 'c', 'continue'
|
201
|
+
Pry.commands.alias_command 's', 'step'
|
202
|
+
Pry.commands.alias_command 'n', 'next'
|
203
|
+
Pry.commands.alias_command 'f', 'finish'
|
204
|
+
|
205
|
+
Pry::Commands.command(/^$/, 'repeat last command') do
|
206
|
+
_pry_.run_command Pry.history.to_a.last
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
byebug
|
211
|
+
else
|
212
|
+
require 'ruby-debug'; debugger
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
##
|
217
|
+
# Indicates whether a supported framework is in use
|
218
|
+
# or not
|
219
|
+
#
|
220
|
+
def framework?
|
221
|
+
defined?(::Rails) || defined?(::Sinatra) || defined?(::Padrino) || defined?(::Grape)
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
# These methods should be implemented by the descendants
|
226
|
+
# (Oboe_metal, JOboe_metal (JRuby), Heroku_metal)
|
227
|
+
#
|
228
|
+
def sample?(_opts = {})
|
229
|
+
fail 'sample? should be implemented by metal layer.'
|
230
|
+
end
|
231
|
+
|
232
|
+
def log(_layer, _label, _options = {})
|
233
|
+
fail 'log should be implemented by metal layer.'
|
234
|
+
end
|
235
|
+
|
236
|
+
def set_tracing_mode(_mode)
|
237
|
+
fail 'set_tracing_mode should be implemented by metal layer.'
|
238
|
+
end
|
239
|
+
|
240
|
+
def set_sample_rate(_rate)
|
241
|
+
fail 'set_sample_rate should be implemented by metal layer.'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
module AppOpticsAPM
|
246
|
+
extend AppOpticsAPMBase
|
247
|
+
end
|
248
|
+
|
249
|
+
# Setup an alias so we don't bug users
|
250
|
+
# about single letter capitalization
|
251
|
+
Appoptics = AppOpticsAPM
|
252
|
+
AO = AppOpticsAPM
|