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,58 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v3
11
+ #
12
+ module ActionController
13
+ include ::AppOpticsAPM::Inst::RailsBase
14
+
15
+ def self.included(base)
16
+ base.class_eval do
17
+ alias_method_chain :process, :appoptics
18
+ alias_method_chain :process_action, :appoptics
19
+ alias_method_chain :render, :appoptics
20
+ end
21
+ end
22
+
23
+ def process_with_appoptics(*args)
24
+ kvs = {
25
+ :Controller => self.class.name,
26
+ :Action => self.action_name,
27
+ }
28
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
29
+ request.env['appoptics_apm.action'] = kvs[:Action]
30
+
31
+ trace('rails') do
32
+ process_without_appoptics(*args)
33
+ end
34
+ end
35
+
36
+ def process_action_with_appoptics(*args)
37
+ kvs = {
38
+ :Controller => self.class.name,
39
+ :Action => action_name,
40
+ }
41
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
42
+ request.env['appoptics_apm.action'] = kvs[:Action]
43
+
44
+ return process_action_without_appoptics(*args) unless AppOpticsAPM.tracing?
45
+ begin
46
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller][:collect_backtraces]
47
+ AppOpticsAPM::API.log(nil, 'info', kvs)
48
+
49
+ process_action_without_appoptics(*args)
50
+ rescue Exception
51
+ kvs[:Status] = 500
52
+ AppOpticsAPM::API.log(nil, 'info', kvs)
53
+ raise
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v4
11
+ #
12
+ module ActionController
13
+ include ::AppOpticsAPM::Inst::RailsBase
14
+
15
+ def self.included(base)
16
+ base.class_eval do
17
+ alias_method_chain :process_action, :appoptics
18
+ alias_method_chain :render, :appoptics
19
+ end
20
+ end
21
+
22
+ def process_action_with_appoptics(method_name, *args)
23
+ kvs = {
24
+ :Controller => self.class.name,
25
+ :Action => self.action_name,
26
+ }
27
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
28
+ request.env['appoptics_apm.action'] = kvs[:Action]
29
+
30
+ return process_action_without_appoptics(method_name, *args) unless AppOpticsAPM.tracing?
31
+ begin
32
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller][:collect_backtraces]
33
+
34
+ AppOpticsAPM::API.log_entry('rails', kvs)
35
+
36
+ process_action_without_appoptics(method_name, *args)
37
+
38
+ rescue Exception => e
39
+ AppOpticsAPM::API.log_exception(nil, e) if log_rails_error?(e)
40
+ raise
41
+ ensure
42
+ AppOpticsAPM::API.log_exit('rails')
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v5
11
+ #
12
+ module ActionController
13
+ include ::AppOpticsAPM::Inst::RailsBase
14
+
15
+ def process_action(method_name, *args)
16
+ kvs = {
17
+ :Controller => self.class.name,
18
+ :Action => self.action_name,
19
+ }
20
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
21
+ request.env['appoptics_apm.action'] = kvs[:Action]
22
+
23
+ return super(method_name, *args) unless AppOpticsAPM.tracing?
24
+ begin
25
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller][:collect_backtraces]
26
+
27
+ AppOpticsAPM::API.log_entry('rails', kvs)
28
+ super(method_name, *args)
29
+
30
+ rescue Exception => e
31
+ AppOpticsAPM::API.log_exception(nil, e) if log_rails_error?(e)
32
+ raise
33
+ ensure
34
+ AppOpticsAPM::API.log_exit('rails')
35
+ end
36
+ end
37
+
38
+ #
39
+ # render
40
+ #
41
+ # Our render wrapper that calls 'trace', which will log if we are tracing
42
+ #
43
+ def render(*args, &blk)
44
+ trace('actionview') do
45
+ super(*args, &blk)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ #
7
+ # ActionController
8
+ #
9
+ # This modules contains the instrumentation code specific
10
+ # to Rails v5.
11
+ #
12
+ module ActionControllerAPI
13
+ include ::AppOpticsAPM::Inst::RailsBase
14
+
15
+ def process_action(method_name, *args)
16
+ kvs = {
17
+ :Controller => self.class.name,
18
+ :Action => self.action_name
19
+ }
20
+ request.env['appoptics_apm.controller'] = kvs[:Controller]
21
+ request.env['appoptics_apm.action'] = kvs[:Controller]
22
+
23
+ return super(method_name, *args) unless AppOpticsAPM.tracing?
24
+ begin
25
+ kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_controller_api][:collect_backtraces]
26
+
27
+ AppOpticsAPM::API.log_entry('rails-api', kvs)
28
+ super(method_name, *args)
29
+
30
+ rescue Exception => e
31
+ AppOpticsAPM::API.log_exception(nil, e) if log_rails_error?(e)
32
+ raise
33
+ ensure
34
+ AppOpticsAPM::API.log_exit('rails-api')
35
+ end
36
+ end
37
+
38
+ #
39
+ # render
40
+ #
41
+ # Our render wrapper that calls 'add_logging', which will log if we are tracing
42
+ #
43
+ def render(*args, &blk)
44
+ trace('actionview') do
45
+ super(*args, &blk)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
5
+
6
+ ##
7
+ # ActionView Instrumentation is version dependent. ActionView 2.x is separate
8
+ # and ActionView 3.0 is a special case.
9
+ # Everything else goes here. (ActionView 3.1 - 4.0 as of this writing)
10
+ #
11
+ if (Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR > 0) || Rails::VERSION::MAJOR >= 4
12
+
13
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting actionview' if AppOpticsAPM::Config[:verbose]
14
+
15
+ ActionView::PartialRenderer.class_eval do
16
+ alias :render_partial_without_appoptics :render_partial
17
+ def render_partial
18
+ entry_kvs = {}
19
+ begin
20
+ name = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
21
+ entry_kvs[:FunctionName] = :render_partial
22
+ entry_kvs[:Class] = :PartialRenderer
23
+ entry_kvs[:Module] = :ActionView
24
+ entry_kvs[:File] = __FILE__
25
+ entry_kvs[:LineNumber] = __LINE__
26
+ rescue => e
27
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
28
+ end
29
+
30
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
31
+ render_partial_without_appoptics
32
+ end
33
+ end
34
+
35
+ alias :render_collection_without_appoptics :render_collection
36
+ def render_collection
37
+ entry_kvs = {}
38
+ begin
39
+ name = AppOpticsAPM::Util.prettify(@path)
40
+ entry_kvs[:FunctionName] = :render_collection
41
+ entry_kvs[:Class] = :PartialRenderer
42
+ entry_kvs[:Module] = :ActionView
43
+ entry_kvs[:File] = __FILE__
44
+ entry_kvs[:LineNumber] = __LINE__
45
+ rescue => e
46
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
47
+ end
48
+
49
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
50
+ render_collection_without_appoptics
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
5
+
6
+ if Rails::VERSION::MAJOR == 2
7
+
8
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting actionview' if AppOpticsAPM::Config[:verbose]
9
+
10
+ ActionView::Partials.module_eval do
11
+ alias :render_partial_without_appoptics :render_partial
12
+ def render_partial(options = {})
13
+ if options.key?(:partial) && options[:partial].is_a?(String)
14
+ entry_kvs = {}
15
+ begin
16
+ name = AppOpticsAPM::Util.prettify(options[:partial]) if options.is_a?(Hash)
17
+ entry_kvs[:FunctionName] = :render_partial
18
+ entry_kvs[:Class] = :Partials
19
+ entry_kvs[:Module] = :ActionView
20
+ entry_kvs[:File] = __FILE__
21
+ entry_kvs[:LineNumber] = __LINE__
22
+ rescue => e
23
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
24
+ end
25
+
26
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
27
+ render_partial_without_appoptics(options)
28
+ end
29
+ else
30
+ render_partial_without_appoptics(options)
31
+ end
32
+ end
33
+
34
+ alias :render_partial_collection_without_appoptics :render_partial_collection
35
+ def render_partial_collection(options = {})
36
+ entry_kvs = {}
37
+ begin
38
+ name = 'partial_collection'
39
+ entry_kvs[:FunctionName] = :render_partial_collection
40
+ entry_kvs[:Class] = :Partials
41
+ entry_kvs[:Module] = :ActionView
42
+ entry_kvs[:File] = __FILE__
43
+ entry_kvs[:LineNumber] = __LINE__
44
+ rescue => e
45
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
46
+ end
47
+
48
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
49
+ render_partial_collection_without_appoptics(options)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
5
+
6
+ if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0
7
+
8
+ ActionView::Partials::PartialRenderer.class_eval do
9
+ alias :render_partial_without_appoptics :render_partial
10
+ def render_partial(object = @object)
11
+ entry_kvs = {}
12
+ begin
13
+ name = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
14
+ entry_kvs[:FunctionName] = :render_partial
15
+ entry_kvs[:Class] = :PartialRenderer
16
+ entry_kvs[:Module] = 'ActionView::Partials'
17
+ entry_kvs[:File] = __FILE__
18
+ entry_kvs[:LineNumber] = __LINE__
19
+ rescue => e
20
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
21
+ end
22
+
23
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
24
+ render_partial_without_appoptics(object)
25
+ end
26
+ end
27
+
28
+ alias :render_collection_without_appoptics :render_collection
29
+ def render_collection
30
+ entry_kvs = {}
31
+ begin
32
+ name = AppOpticsAPM::Util.prettify(@path)
33
+ entry_kvs[:FunctionName] = :render_collection
34
+ entry_kvs[:Class] = :PartialRenderer
35
+ entry_kvs[:Module] = 'ActionView::Partials'
36
+ entry_kvs[:File] = __FILE__
37
+ entry_kvs[:LineNumber] = __LINE__
38
+ rescue => e
39
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
40
+ end
41
+
42
+ AppOpticsAPM::API.profile(name, entry_kvs, AppOpticsAPM::Config[:action_view][:collect_backtraces]) do
43
+ render_collection_without_appoptics
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/mysql'
5
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2'
6
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql'
7
+
8
+ if AppOpticsAPM::Config[:active_record][:enabled] && !defined?(JRUBY_VERSION)
9
+ begin
10
+ adapter = ActiveRecord::Base.connection.adapter_name.downcase
11
+
12
+ if Rails::VERSION::MAJOR < 5
13
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/utils'
14
+ else
15
+ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x'
16
+ end
17
+
18
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.mysql if adapter == 'mysql'
19
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.mysql2 if adapter == 'mysql2'
20
+ AppOpticsAPM::Inst::ConnectionAdapters::FlavorInitializers.postgresql if adapter == 'postgresql'
21
+
22
+ rescue StandardError => e
23
+ AppOpticsAPM.logger.error "[appoptics_apm/error] AppOpticsAPM/ActiveRecord error: #{e.inspect}"
24
+ AppOpticsAPM.logger.debug e.backtrace.join("\n")
25
+ end
26
+ end
27
+ # vim:set expandtab:tabstop=2
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.mysql
9
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord mysqladapter' if AppOpticsAPM::Config[:verbose]
10
+
11
+ # ActiveRecord 3.2 and higher
12
+ if (::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR >= 2) ||
13
+ ::ActiveRecord::VERSION::MAJOR == 4
14
+
15
+ # AbstractMysqlAdapter
16
+ AppOpticsAPM::Util.send_include(::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter,
17
+ ::AppOpticsAPM::Inst::ConnectionAdapters::Utils)
18
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, :execute)
19
+
20
+ # MysqlAdapter
21
+ AppOpticsAPM::Util.send_include(::ActiveRecord::ConnectionAdapters::MysqlAdapter,
22
+ ::AppOpticsAPM::Inst::ConnectionAdapters::Utils)
23
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::MysqlAdapter, :exec_query)
24
+
25
+ else
26
+ # ActiveRecord 3.1 and below
27
+
28
+ # MysqlAdapter
29
+ AppOpticsAPM::Util.send_include(::ActiveRecord::ConnectionAdapters::MysqlAdapter,
30
+ ::AppOpticsAPM::Inst::ConnectionAdapters::Utils)
31
+
32
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::MysqlAdapter, :execute)
33
+
34
+ if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR == 1
35
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::MysqlAdapter, :begin_db_transaction)
36
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::MysqlAdapter, :exec_delete)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.mysql2
9
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord mysql2adapter' if AppOpticsAPM::Config[:verbose]
10
+
11
+ AppOpticsAPM::Util.send_include(::ActiveRecord::ConnectionAdapters::Mysql2Adapter,
12
+ ::AppOpticsAPM::Inst::ConnectionAdapters::Utils)
13
+
14
+ if (::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR == 0) ||
15
+ ::ActiveRecord::VERSION::MAJOR == 2
16
+ # ActiveRecord 3.0 and prior
17
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::Mysql2Adapter, :execute)
18
+ else
19
+ # ActiveRecord 3.1 and above
20
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_insert)
21
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_query)
22
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::Mysql2Adapter, :exec_delete)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module FlavorInitializers
8
+ def self.postgresql
9
+
10
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting activerecord postgresqladapter' if AppOpticsAPM::Config[:verbose]
11
+
12
+ AppOpticsAPM::Util.send_include(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter,
13
+ ::AppOpticsAPM::Inst::ConnectionAdapters::Utils)
14
+
15
+ if (::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR > 0) ||
16
+ ::ActiveRecord::VERSION::MAJOR >= 4
17
+
18
+ # ActiveRecord 3.1 and up
19
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :exec_query)
20
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :exec_delete)
21
+
22
+ else
23
+ # ActiveRecord 3.0 and prior
24
+ AppOpticsAPM::Util.method_alias(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, :execute)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,120 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module Utils
8
+
9
+ def extract_trace_details(sql, name = nil, binds = [])
10
+ opts = {}
11
+ if AppOpticsAPM::Config[:sanitize_sql]
12
+ # Sanitize SQL and don't report binds
13
+ opts[:Query] = AppOpticsAPM::Util.sanitize_sql(sql)
14
+ else
15
+ # Report raw SQL and any binds if they exist
16
+ opts[:Query] = sql.to_s
17
+ opts[:QueryArgs] = binds.map { |col, val| [col.name, val.to_s] } unless binds.empty?
18
+ end
19
+
20
+ opts[:Name] = name.to_s if name
21
+ opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:active_record][:collect_backtraces]
22
+
23
+ if ::Rails::VERSION::MAJOR == 2
24
+ config = ::Rails.configuration.database_configuration[::Rails.env]
25
+ else
26
+ config = ActiveRecord::Base.connection.instance_variable_get(:@config)
27
+ end
28
+
29
+ if config
30
+ opts[:Database] = config['database'] if config.key?('database')
31
+ opts[:RemoteHost] = config['host'] if config.key?('host')
32
+ adapter_name = config[:adapter]
33
+
34
+ case adapter_name
35
+ when /mysql/i
36
+ opts[:Flavor] = 'mysql'
37
+ when /postgres/i
38
+ opts[:Flavor] = 'postgresql'
39
+ end
40
+ end
41
+ rescue StandardError => e
42
+ AppOpticsAPM.logger.debug "Exception raised capturing ActiveRecord KVs: #{e.inspect}"
43
+ AppOpticsAPM.logger.debug e.backtrace.join('\n')
44
+ ensure
45
+ return opts
46
+ end
47
+
48
+ # We don't want to trace framework caches. Only instrument SQL that
49
+ # directly hits the database.
50
+ def ignore_payload?(name)
51
+ %w(SCHEMA EXPLAIN CACHE).include?(name.to_s) ||
52
+ (name && name.to_sym == :skip_logging) ||
53
+ name == 'ActiveRecord::SchemaMigration Load'
54
+ end
55
+
56
+ # def cfg
57
+ # @config
58
+ # end
59
+
60
+ def execute_with_appoptics(sql, name = nil)
61
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
62
+
63
+ opts = extract_trace_details(sql, name)
64
+ AppOpticsAPM::API.trace('activerecord', opts || {}) do
65
+ execute_without_appoptics(sql, name)
66
+ end
67
+ else
68
+ execute_without_appoptics(sql, name)
69
+ end
70
+ end
71
+
72
+ def exec_query_with_appoptics(sql, name = nil, binds = [])
73
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
74
+
75
+ opts = extract_trace_details(sql, name, binds)
76
+ AppOpticsAPM::API.trace('activerecord', opts || {}) do
77
+ exec_query_without_appoptics(sql, name, binds)
78
+ end
79
+ else
80
+ exec_query_without_appoptics(sql, name, binds)
81
+ end
82
+ end
83
+
84
+ def exec_delete_with_appoptics(sql, name = nil, binds = [])
85
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
86
+
87
+ opts = extract_trace_details(sql, name, binds)
88
+ AppOpticsAPM::API.trace('activerecord', opts || {}) do
89
+ exec_delete_without_appoptics(sql, name, binds)
90
+ end
91
+ else
92
+ exec_delete_without_appoptics(sql, name, binds)
93
+ end
94
+ end
95
+
96
+ def exec_insert_with_appoptics(sql, name = nil, binds = [], *args)
97
+ if AppOpticsAPM.tracing? && !ignore_payload?(name)
98
+
99
+ opts = extract_trace_details(sql, name, binds)
100
+ AppOpticsAPM::API.trace('activerecord', opts || {}) do
101
+ exec_insert_without_appoptics(sql, name, binds, *args)
102
+ end
103
+ else
104
+ exec_insert_without_appoptics(sql, name, binds, *args)
105
+ end
106
+ end
107
+
108
+ def begin_db_transaction_with_appoptics
109
+ if AppOpticsAPM.tracing?
110
+ AppOpticsAPM::API.trace('activerecord', { :Query => 'BEGIN', :Flavor => :mysql }) do
111
+ begin_db_transaction_without_appoptics
112
+ end
113
+ else
114
+ begin_db_transaction_without_appoptics
115
+ end
116
+ end
117
+ end # Utils
118
+ end
119
+ end
120
+ end