appoptics_apm 4.0.2

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.
Files changed (226) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +43 -0
  3. data/.dockerignore +5 -0
  4. data/.gitignore +23 -0
  5. data/.rubocop.yml +5 -0
  6. data/.travis.yml +82 -0
  7. data/CHANGELOG.md +769 -0
  8. data/CONFIG.md +33 -0
  9. data/Dockerfile +41 -0
  10. data/Dockerfile_test +66 -0
  11. data/Gemfile +41 -0
  12. data/LICENSE +193 -0
  13. data/README.md +351 -0
  14. data/Rakefile +202 -0
  15. data/Vagrantfile +67 -0
  16. data/appoptics_apm.gemspec +55 -0
  17. data/build_gems.sh +15 -0
  18. data/docker-compose.yml +73 -0
  19. data/examples/DNT.md +35 -0
  20. data/examples/carrying_context.rb +220 -0
  21. data/examples/instrumenting_metal_controller.rb +8 -0
  22. data/examples/puma_on_heroku_config.rb +17 -0
  23. data/examples/tracing_async_threads.rb +124 -0
  24. data/examples/tracing_background_jobs.rb +53 -0
  25. data/examples/tracing_forked_processes.rb +99 -0
  26. data/examples/unicorn_on_heroku_config.rb +28 -0
  27. data/ext/oboe_metal/extconf.rb +54 -0
  28. data/ext/oboe_metal/lib/.keep +0 -0
  29. data/ext/oboe_metal/lib/liboboe-1.0.so.0.0.0 +0 -0
  30. data/ext/oboe_metal/noop/noop.c +7 -0
  31. data/ext/oboe_metal/src/VERSION +1 -0
  32. data/ext/oboe_metal/src/bson/bson.h +221 -0
  33. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  34. data/ext/oboe_metal/src/oboe.h +883 -0
  35. data/ext/oboe_metal/src/oboe.hpp +793 -0
  36. data/ext/oboe_metal/src/oboe_debug.h +50 -0
  37. data/ext/oboe_metal/src/oboe_wrap.cxx +6088 -0
  38. data/ext/oboe_metal/tests/test.rb +11 -0
  39. data/gemfiles/delayed_job.gemfile +36 -0
  40. data/gemfiles/frameworks.gemfile +44 -0
  41. data/gemfiles/instrumentation_mocked.gemfile +29 -0
  42. data/gemfiles/libraries.gemfile +85 -0
  43. data/gemfiles/rails23.gemfile +39 -0
  44. data/gemfiles/rails30.gemfile +42 -0
  45. data/gemfiles/rails31.gemfile +44 -0
  46. data/gemfiles/rails32.gemfile +54 -0
  47. data/gemfiles/rails40.gemfile +27 -0
  48. data/gemfiles/rails41.gemfile +27 -0
  49. data/gemfiles/rails42.gemfile +35 -0
  50. data/gemfiles/rails50.gemfile +44 -0
  51. data/gemfiles/rails51.gemfile +44 -0
  52. data/get_version.rb +5 -0
  53. data/init.rb +4 -0
  54. data/lib/appoptics_apm/api/layerinit.rb +39 -0
  55. data/lib/appoptics_apm/api/logging.rb +359 -0
  56. data/lib/appoptics_apm/api/memcache.rb +34 -0
  57. data/lib/appoptics_apm/api/profiling.rb +201 -0
  58. data/lib/appoptics_apm/api/tracing.rb +152 -0
  59. data/lib/appoptics_apm/api/util.rb +128 -0
  60. data/lib/appoptics_apm/api.rb +18 -0
  61. data/lib/appoptics_apm/base.rb +252 -0
  62. data/lib/appoptics_apm/config.rb +281 -0
  63. data/lib/appoptics_apm/frameworks/grape.rb +93 -0
  64. data/lib/appoptics_apm/frameworks/padrino/templates.rb +58 -0
  65. data/lib/appoptics_apm/frameworks/padrino.rb +52 -0
  66. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +106 -0
  67. data/lib/appoptics_apm/frameworks/rails/inst/action_controller2.rb +61 -0
  68. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +58 -0
  69. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  70. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  71. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  72. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
  73. data/lib/appoptics_apm/frameworks/rails/inst/action_view_2x.rb +56 -0
  74. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
  75. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  76. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  77. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
  78. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
  79. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +120 -0
  80. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +101 -0
  81. data/lib/appoptics_apm/frameworks/rails.rb +116 -0
  82. data/lib/appoptics_apm/frameworks/sinatra/templates.rb +56 -0
  83. data/lib/appoptics_apm/frameworks/sinatra.rb +71 -0
  84. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  85. data/lib/appoptics_apm/inst/bunny-consumer.rb +92 -0
  86. data/lib/appoptics_apm/inst/curb.rb +329 -0
  87. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  88. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  89. data/lib/appoptics_apm/inst/em-http-request.rb +105 -0
  90. data/lib/appoptics_apm/inst/excon.rb +130 -0
  91. data/lib/appoptics_apm/inst/faraday.rb +77 -0
  92. data/lib/appoptics_apm/inst/http.rb +83 -0
  93. data/lib/appoptics_apm/inst/httpclient.rb +176 -0
  94. data/lib/appoptics_apm/inst/memcache.rb +102 -0
  95. data/lib/appoptics_apm/inst/memcached.rb +94 -0
  96. data/lib/appoptics_apm/inst/mongo.rb +242 -0
  97. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  98. data/lib/appoptics_apm/inst/moped.rb +466 -0
  99. data/lib/appoptics_apm/inst/rack.rb +146 -0
  100. data/lib/appoptics_apm/inst/redis.rb +275 -0
  101. data/lib/appoptics_apm/inst/resque.rb +151 -0
  102. data/lib/appoptics_apm/inst/rest-client.rb +50 -0
  103. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  104. data/lib/appoptics_apm/inst/sidekiq-client.rb +53 -0
  105. data/lib/appoptics_apm/inst/sidekiq-worker.rb +67 -0
  106. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  107. data/lib/appoptics_apm/inst/typhoeus.rb +113 -0
  108. data/lib/appoptics_apm/instrumentation.rb +22 -0
  109. data/lib/appoptics_apm/legacy_method_profiling.rb +97 -0
  110. data/lib/appoptics_apm/loading.rb +66 -0
  111. data/lib/appoptics_apm/logger.rb +41 -0
  112. data/lib/appoptics_apm/method_profiling.rb +33 -0
  113. data/lib/appoptics_apm/ruby.rb +35 -0
  114. data/lib/appoptics_apm/support.rb +135 -0
  115. data/lib/appoptics_apm/test.rb +94 -0
  116. data/lib/appoptics_apm/thread_local.rb +26 -0
  117. data/lib/appoptics_apm/util.rb +312 -0
  118. data/lib/appoptics_apm/version.rb +15 -0
  119. data/lib/appoptics_apm/xtrace.rb +103 -0
  120. data/lib/appoptics_apm.rb +72 -0
  121. data/lib/joboe_metal.rb +214 -0
  122. data/lib/oboe/README +2 -0
  123. data/lib/oboe/backward_compatibility.rb +80 -0
  124. data/lib/oboe/inst/rack.rb +11 -0
  125. data/lib/oboe.rb +7 -0
  126. data/lib/oboe_metal.rb +187 -0
  127. data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
  128. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +222 -0
  129. data/ruby_setup.sh +47 -0
  130. data/run_docker_build_gem_upload_to_packagecloud.sh +20 -0
  131. data/run_tests_docker.rb +32 -0
  132. data/test/benchmark/README.md +65 -0
  133. data/test/benchmark/logging_bench.rb +54 -0
  134. data/test/benchmark/with_libraries_gemfile/bunny_bench.rb +69 -0
  135. data/test/benchmark/with_rails5x_gemfile/action_controller5x_bench.rb +43 -0
  136. data/test/frameworks/apps/grape_nested.rb +33 -0
  137. data/test/frameworks/apps/grape_simple.rb +80 -0
  138. data/test/frameworks/apps/padrino_simple.rb +80 -0
  139. data/test/frameworks/apps/sinatra_simple.rb +55 -0
  140. data/test/frameworks/grape_test.rb +286 -0
  141. data/test/frameworks/padrino_test.rb +222 -0
  142. data/test/frameworks/rails3x_test.rb +554 -0
  143. data/test/frameworks/rails4x_test.rb +570 -0
  144. data/test/frameworks/rails5x_api_test.rb +210 -0
  145. data/test/frameworks/rails5x_test.rb +376 -0
  146. data/test/frameworks/rails_shared_tests.rb +172 -0
  147. data/test/frameworks/sinatra_test.rb +140 -0
  148. data/test/instrumentation/bunny_client_test.rb +276 -0
  149. data/test/instrumentation/bunny_consumer_test.rb +204 -0
  150. data/test/instrumentation/curb_test.rb +398 -0
  151. data/test/instrumentation/dalli_test.rb +177 -0
  152. data/test/instrumentation/em_http_request_test.rb +89 -0
  153. data/test/instrumentation/excon_test.rb +231 -0
  154. data/test/instrumentation/faraday_test.rb +228 -0
  155. data/test/instrumentation/http_test.rb +143 -0
  156. data/test/instrumentation/httpclient_test.rb +320 -0
  157. data/test/instrumentation/memcache_test.rb +260 -0
  158. data/test/instrumentation/memcached_test.rb +229 -0
  159. data/test/instrumentation/mongo_v1_test.rb +479 -0
  160. data/test/instrumentation/mongo_v2_index_test.rb +124 -0
  161. data/test/instrumentation/mongo_v2_test.rb +584 -0
  162. data/test/instrumentation/mongo_v2_view_test.rb +435 -0
  163. data/test/instrumentation/moped_test.rb +517 -0
  164. data/test/instrumentation/rack_test.rb +165 -0
  165. data/test/instrumentation/redis_hashes_test.rb +268 -0
  166. data/test/instrumentation/redis_keys_test.rb +321 -0
  167. data/test/instrumentation/redis_lists_test.rb +310 -0
  168. data/test/instrumentation/redis_misc_test.rb +163 -0
  169. data/test/instrumentation/redis_sets_test.rb +296 -0
  170. data/test/instrumentation/redis_sortedsets_test.rb +328 -0
  171. data/test/instrumentation/redis_strings_test.rb +349 -0
  172. data/test/instrumentation/resque_test.rb +185 -0
  173. data/test/instrumentation/rest-client_test.rb +288 -0
  174. data/test/instrumentation/sequel_mysql2_test.rb +353 -0
  175. data/test/instrumentation/sequel_mysql_test.rb +334 -0
  176. data/test/instrumentation/sequel_pg_test.rb +336 -0
  177. data/test/instrumentation/sidekiq-client_test.rb +159 -0
  178. data/test/instrumentation/sidekiq-worker_test.rb +180 -0
  179. data/test/instrumentation/twitter-cassandra_test.rb +424 -0
  180. data/test/instrumentation/typhoeus_test.rb +284 -0
  181. data/test/jobs/delayed_job/db_worker_job.rb +29 -0
  182. data/test/jobs/delayed_job/error_worker_job.rb +10 -0
  183. data/test/jobs/delayed_job/remote_call_worker_job.rb +20 -0
  184. data/test/jobs/resque/db_worker_job.rb +29 -0
  185. data/test/jobs/resque/error_worker_job.rb +10 -0
  186. data/test/jobs/resque/remote_call_worker_job.rb +20 -0
  187. data/test/jobs/sidekiq/db_worker_job.rb +29 -0
  188. data/test/jobs/sidekiq/error_worker_job.rb +10 -0
  189. data/test/jobs/sidekiq/remote_call_worker_job.rb +20 -0
  190. data/test/minitest_helper.rb +276 -0
  191. data/test/mocked/curb_mocked_test.rb +311 -0
  192. data/test/mocked/excon_mocked_test.rb +166 -0
  193. data/test/mocked/faraday_mocked_test.rb +93 -0
  194. data/test/mocked/http_mocked_test.rb +129 -0
  195. data/test/mocked/httpclient_mocked_test.rb +245 -0
  196. data/test/mocked/rest_client_mocked_test.rb +103 -0
  197. data/test/mocked/typhoeus_mocked_test.rb +192 -0
  198. data/test/models/widget.rb +36 -0
  199. data/test/profiling/legacy_method_profiling_test.rb +201 -0
  200. data/test/profiling/method_profiling_test.rb +631 -0
  201. data/test/queues/delayed_job-client_test.rb +95 -0
  202. data/test/queues/delayed_job-worker_test.rb +91 -0
  203. data/test/reporter/reporter_test.rb +14 -0
  204. data/test/servers/delayed_job.rb +107 -0
  205. data/test/servers/rackapp_8101.rb +29 -0
  206. data/test/servers/rails3x_8140.rb +96 -0
  207. data/test/servers/rails4x_8140.rb +96 -0
  208. data/test/servers/rails5x_8140.rb +95 -0
  209. data/test/servers/rails5x_api_8150.rb +78 -0
  210. data/test/servers/sidekiq.rb +29 -0
  211. data/test/servers/sidekiq.yml +7 -0
  212. data/test/servers/sidekiq_initializer.rb +25 -0
  213. data/test/settings +0 -0
  214. data/test/support/auto_tracing_test.rb +50 -0
  215. data/test/support/backcompat_test.rb +276 -0
  216. data/test/support/config_test.rb +149 -0
  217. data/test/support/dnt_test.rb +98 -0
  218. data/test/support/init_report_test.rb +25 -0
  219. data/test/support/liboboe_settings_test.rb +110 -0
  220. data/test/support/logging_test.rb +130 -0
  221. data/test/support/noop_test.rb +88 -0
  222. data/test/support/sql_sanitize_test.rb +55 -0
  223. data/test/support/tracing_mode_test.rb +33 -0
  224. data/test/support/tvalias_test.rb +15 -0
  225. data/test/support/xtrace_test.rb +41 -0
  226. 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