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,103 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ unless defined?(JRUBY_VERSION)
5
+ require 'minitest_helper'
6
+ require 'webmock/minitest'
7
+ require 'mocha/mini_test'
8
+ WebMock.allow_net_connect!
9
+
10
+ class RestClientMockedTest < Minitest::Test
11
+
12
+ def setup
13
+ WebMock.enable!
14
+ WebMock.disable_net_connect!
15
+ AppOpticsAPM.config_lock.synchronize do
16
+ @sample_rate = AppOpticsAPM::Config[:sample_rate]
17
+ end
18
+ end
19
+
20
+ def teardown
21
+ AppOpticsAPM.config_lock.synchronize do
22
+ AppOpticsAPM::Config[:sample_rate] = @sample_rate
23
+ AppOpticsAPM::Config[:blacklist] = []
24
+ end
25
+ WebMock.reset!
26
+ WebMock.allow_net_connect!
27
+ WebMock.disable!
28
+ end
29
+
30
+ def test_tracing_sampling
31
+ stub_request(:get, "http://127.0.0.1:8101/").to_return(status: 200, body: "", headers: {})
32
+
33
+ AppOpticsAPM::API.start_trace('rest_client_tests') do
34
+ RestClient::Resource.new('http://127.0.0.1:8101').get
35
+ end
36
+
37
+ assert_requested :get, "http://127.0.0.1:8101/", headers: {'X-Trace'=>/^2B[0-9,A-F]*01$/}, times: 1
38
+ end
39
+
40
+ def test_tracing_not_sampling
41
+ stub_request(:get, "http://127.0.0.2:8101/").to_return(status: 200, body: "", headers: {})
42
+
43
+ AppOpticsAPM.config_lock.synchronize do
44
+ AppOpticsAPM::Config[:sample_rate] = 0
45
+ AppOpticsAPM::API.start_trace('rest_client_tests') do
46
+ RestClient::Resource.new('http://127.0.0.2:8101').get
47
+ end
48
+ end
49
+
50
+ assert_requested :get, "http://127.0.0.2:8101/", headers: {'X-Trace'=>/^2B[0-9,A-F]*00$/}, times: 1
51
+ assert_not_requested :get, "http://127.0.0.2:8101/", headers: {'X-Trace'=>/^2B0*$/}
52
+ end
53
+
54
+ def test_no_xtrace
55
+ stub_request(:get, "http://127.0.0.3:8101/").to_return(status: 200, body: "", headers: {})
56
+
57
+ RestClient::Resource.new('http://127.0.0.3:8101').get
58
+
59
+ assert_requested :get, "http://127.0.0.3:8101/", times: 1
60
+ assert_not_requested :get, "http://127.0.0.3:8101/", headers: {'X-Trace'=>/^.*$/}
61
+ end
62
+
63
+ def test_blacklisted
64
+ stub_request(:get, "http://127.0.0.4:8101/").to_return(status: 200, body: "", headers: {})
65
+
66
+ AppOpticsAPM.config_lock.synchronize do
67
+ AppOpticsAPM::Config.blacklist << '127.0.0.4'
68
+ AppOpticsAPM::API.start_trace('rest_client_tests') do
69
+ RestClient::Resource.new('http://127.0.0.4:8101').get
70
+ end
71
+ end
72
+
73
+ assert_requested :get, "http://127.0.0.4:8101/", times: 1
74
+ assert_not_requested :get, "http://127.0.0.4:8101/", headers: {'X-Trace'=>/^.*$/}
75
+ end
76
+
77
+ def test_not_sampling_blacklisted
78
+ stub_request(:get, "http://127.0.0.5:8101/").to_return(status: 200, body: "", headers: {})
79
+
80
+ AppOpticsAPM.config_lock.synchronize do
81
+ AppOpticsAPM::Config[:sample_rate] = 0
82
+ AppOpticsAPM::Config.blacklist << '127.0.0.5'
83
+ AppOpticsAPM::API.start_trace('rest_client_tests') do
84
+ RestClient::Resource.new('http://127.0.0.5:8101').get
85
+ end
86
+ end
87
+
88
+ assert_requested :get, "http://127.0.0.5:8101/", times: 1
89
+ assert_not_requested :get, "http://127.0.0.5:8101/", headers: {'X-Trace'=>/^.*$/}
90
+ end
91
+
92
+ def test_preserves_custom_headers
93
+ stub_request(:get, "http://127.0.0.6:8101/").to_return(status: 200, body: "", headers: {})
94
+
95
+ AppOpticsAPM::API.start_trace('rest_client_tests') do
96
+ RestClient::Resource.new('http://127.0.0.6:8101', headers: { 'Custom' => 'specialvalue' }).get
97
+ end
98
+
99
+ assert_requested :get, "http://127.0.0.6:8101/", headers: {'Custom'=>'specialvalue'}, times: 1
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,192 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ unless defined?(JRUBY_VERSION)
5
+ require 'minitest_helper'
6
+ require 'mocha/mini_test'
7
+
8
+ class TyphoeusMockedTest < Minitest::Test
9
+
10
+ def setup
11
+ AppOpticsAPM.config_lock.synchronize do
12
+ @sample_rate = AppOpticsAPM::Config[:sample_rate]
13
+ end
14
+ end
15
+
16
+ def teardown
17
+ AppOpticsAPM.config_lock.synchronize do
18
+ AppOpticsAPM::Config[:sample_rate] = @sample_rate
19
+ AppOpticsAPM::Config[:blacklist] = []
20
+ end
21
+ end
22
+
23
+ ############# Typhoeus::Request ##############################################
24
+
25
+ def test_tracing_sampling
26
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
27
+ request = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
28
+ request.run
29
+
30
+ assert request.options[:headers]['X-Trace']
31
+ assert_match /^2B[0-9,A-F]*01$/,request.options[:headers]['X-Trace']
32
+ end
33
+ end
34
+
35
+ def test_tracing_not_sampling
36
+ AppOpticsAPM.config_lock.synchronize do
37
+ AppOpticsAPM::Config[:sample_rate] = 0
38
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
39
+ request = Typhoeus::Request.new("http://127.0.0.1:8101/", {:method=>:get})
40
+ request.run
41
+
42
+ assert request.options[:headers]['X-Trace']
43
+ assert_match /^2B[0-9,A-F]*00$/, request.options[:headers]['X-Trace']
44
+ refute_match /^2B0*$/, request.options[:headers]['X-Trace']
45
+ end
46
+ end
47
+ end
48
+
49
+ def test_no_xtrace
50
+ request = Typhoeus::Request.new("http://127.0.0.1:8101/", {:method=>:get})
51
+ request.run
52
+
53
+ refute request.options[:headers]['X-Trace']
54
+ end
55
+
56
+ def test_blacklisted
57
+ AppOpticsAPM.config_lock.synchronize do
58
+ AppOpticsAPM::Config.blacklist << '127.0.0.1'
59
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
60
+ request = Typhoeus::Request.new("http://127.0.0.1:8101/", {:method=>:get})
61
+ request.run
62
+
63
+ refute request.options[:headers]['X-Trace']
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_not_sampling_blacklisted
69
+ AppOpticsAPM.config_lock.synchronize do
70
+ AppOpticsAPM::Config[:sample_rate] = 0
71
+ AppOpticsAPM::Config.blacklist << '127.0.0.1'
72
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
73
+ request = Typhoeus::Request.new("http://127.0.0.1:8101/", {:method=>:get})
74
+ request.run
75
+
76
+ refute request.options[:headers]['X-Trace']
77
+ end
78
+ end
79
+ end
80
+
81
+ def test_preserves_custom_headers
82
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
83
+ request = Typhoeus::Request.new('http://127.0.0.6:8101', headers: { 'Custom' => 'specialvalue' }, :method => :get)
84
+ request.run
85
+
86
+ assert request.options[:headers]['Custom']
87
+ assert_match /specialvalue/, request.options[:headers]['Custom']
88
+ end
89
+ end
90
+
91
+
92
+ ############# Typhoeus::Hydra ##############################################
93
+
94
+ def test_hydra_tracing_sampling
95
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
96
+ hydra = Typhoeus::Hydra.hydra
97
+ request_1 = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
98
+ request_2 = Typhoeus::Request.new("http://127.0.0.2:8101/counting_sheep", {:method=>:get})
99
+ hydra.queue(request_1)
100
+ hydra.queue(request_2)
101
+ hydra.run
102
+
103
+ assert request_1.options[:headers]['X-Trace'], "There is an X-Trace header"
104
+ assert_match /^2B[0-9,A-F]*01$/, request_1.options[:headers]['X-Trace']
105
+ assert request_2.options[:headers]['X-Trace'], "There is an X-Trace header"
106
+ assert_match /^2B[0-9,A-F]*01$/, request_2.options[:headers]['X-Trace']
107
+ end
108
+ end
109
+
110
+ def test_hydra_tracing_not_sampling
111
+ AppOpticsAPM.config_lock.synchronize do
112
+ AppOpticsAPM::Config[:sample_rate] = 0
113
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
114
+ hydra = Typhoeus::Hydra.hydra
115
+ request_1 = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
116
+ request_2 = Typhoeus::Request.new("http://127.0.0.2:8101/counting_sheep", {:method=>:get})
117
+ hydra.queue(request_1)
118
+ hydra.queue(request_2)
119
+ hydra.run
120
+
121
+ assert request_1.options[:headers]['X-Trace'], "There is an X-Trace header"
122
+ assert_match /^2B[0-9,A-F]*00$/, request_1.options[:headers]['X-Trace']
123
+ refute_match /^2B0*$/, request_1.options[:headers]['X-Trace']
124
+ assert request_2.options[:headers]['X-Trace'], "There is an X-Trace header"
125
+ assert_match /^2B[0-9,A-F]*00$/, request_2.options[:headers]['X-Trace']
126
+ refute_match /^2B0*$/, request_2.options[:headers]['X-Trace']
127
+ end
128
+ end
129
+ end
130
+
131
+ def test_hydra_no_xtrace
132
+ hydra = Typhoeus::Hydra.hydra
133
+ request_1 = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
134
+ request_2 = Typhoeus::Request.new("http://127.0.0.2:8101/counting_sheep", {:method=>:get})
135
+ hydra.queue(request_1)
136
+ hydra.queue(request_2)
137
+ hydra.run
138
+
139
+ refute request_1.options[:headers]['X-Trace'], "There should not be an X-Trace header"
140
+ refute request_2.options[:headers]['X-Trace'], "There should not be an X-Trace header"
141
+ end
142
+
143
+ def test_hydra_blacklisted
144
+ AppOpticsAPM.config_lock.synchronize do
145
+ AppOpticsAPM::Config.blacklist << '127.0.0.2'
146
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
147
+ hydra = Typhoeus::Hydra.hydra
148
+ request_1 = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
149
+ request_2 = Typhoeus::Request.new("http://127.0.0.2:8101/counting_sheep", {:method=>:get})
150
+ hydra.queue(request_1)
151
+ hydra.queue(request_2)
152
+ hydra.run
153
+
154
+ refute request_1.options[:headers]['X-Trace'], "There should not be an X-Trace header"
155
+ refute request_2.options[:headers]['X-Trace'], "There should not be an X-Trace header"
156
+ end
157
+ end
158
+ end
159
+
160
+ def test_hydra_not_sampling_blacklisted
161
+ AppOpticsAPM.config_lock.synchronize do
162
+ AppOpticsAPM::Config[:sample_rate] = 0
163
+ AppOpticsAPM::Config.blacklist << '127.0.0.2'
164
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
165
+ hydra = Typhoeus::Hydra.hydra
166
+ request_1 = Typhoeus::Request.new("http://127.0.0.2:8101/", {:method=>:get})
167
+ request_2 = Typhoeus::Request.new("http://127.0.0.2:8101/counting_sheep", {:method=>:get})
168
+ hydra.queue(request_1)
169
+ hydra.queue(request_2)
170
+ hydra.run
171
+
172
+ refute request_1.options[:headers]['X-Trace'], "There should not be an X-Trace header"
173
+ refute request_2.options[:headers]['X-Trace'], "There should not be an X-Trace header"
174
+ end
175
+ end
176
+ end
177
+
178
+
179
+ def test_hydra_preserves_custom_headers
180
+ AppOpticsAPM::API.start_trace('typhoeus_tests') do
181
+ hydra = Typhoeus::Hydra.hydra
182
+ request = Typhoeus::Request.new('http://127.0.0.6:8101', headers: { 'Custom' => 'specialvalue' }, :method => :get)
183
+ hydra.queue(request)
184
+ hydra.run
185
+
186
+ assert request.options[:headers]['Custom']
187
+ assert_match /specialvalue/, request.options[:headers]['Custom']
188
+ end
189
+ end
190
+
191
+ end
192
+ end
@@ -0,0 +1,36 @@
1
+ # Somehow the Padrino::Reloader v14 is detecting and loading
2
+ # this file when it shouldn't. Block it from loading for
3
+ # Padrino for now.
4
+ unless defined?(Padrino)
5
+ class Widget < ActiveRecord::Base
6
+ def do_work(*args)
7
+ Widget.first
8
+ end
9
+
10
+ def do_error(*args)
11
+ raise "FakeTestError"
12
+ end
13
+ end
14
+
15
+ if Rails.version >= '5.1'
16
+ class CreateWidgets < ActiveRecord::Migration[5.1]
17
+ def change
18
+ create_table :widgets do |t|
19
+ t.string :name
20
+ t.text :description
21
+ t.timestamps
22
+ end
23
+ end
24
+ end
25
+ else
26
+ class CreateWidgets < ActiveRecord::Migration
27
+ def change
28
+ create_table :widgets do |t|
29
+ t.string :name
30
+ t.text :description
31
+ t.timestamps
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,201 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'minitest_helper'
5
+
6
+ describe "LegacyAppOpticsAPMMethodProfiling" do
7
+ before do
8
+ clear_all_traces
9
+ # Conditionally Undefine TestWorker
10
+ # http://stackoverflow.com/questions/11503558/how-to-undefine-class-in-ruby
11
+ Object.send(:remove_const, :TestWorker) if defined?(TestWorker)
12
+ end
13
+
14
+ it 'should be loaded, defined and ready' do
15
+ defined?(::AppOpticsAPMMethodProfiling).wont_match nil
16
+ end
17
+
18
+ it 'should trace Class methods' do
19
+ class TestWorker
20
+ def self.do_work
21
+ sleep 1
22
+ end
23
+
24
+ class << self
25
+ include AppOpticsAPMMethodProfiling
26
+ profile_method :do_work, 'do_work'
27
+ end
28
+ end
29
+
30
+ ::AppOpticsAPM::API.start_trace('method_profiling', '', {}) do
31
+ # Call the profiled class method
32
+ TestWorker.do_work
33
+ end
34
+
35
+ traces = get_all_traces
36
+ traces.count.must_equal 4
37
+
38
+ validate_outer_layers(traces, 'method_profiling')
39
+
40
+ kvs = {}
41
+ kvs["Label"] = 'profile_entry'
42
+ kvs["Language"] = "ruby"
43
+ kvs["ProfileName"] = "do_work"
44
+ kvs["FunctionName"] = "do_work"
45
+ kvs["Class"] = "TestWorker"
46
+
47
+ validate_event_keys(traces[1], kvs)
48
+
49
+ traces[1].has_key?("Layer").must_equal false
50
+ traces[1].has_key?("File").must_equal true
51
+ traces[1].has_key?("LineNumber").must_equal true
52
+
53
+ kvs.clear
54
+ kvs["Label"] = "profile_exit"
55
+ kvs["Language"] = "ruby"
56
+ kvs["ProfileName"] = "do_work"
57
+
58
+ validate_event_keys(traces[2], kvs)
59
+ traces[2].has_key?("Layer").must_equal false
60
+ end
61
+
62
+ it 'should trace Instance methods' do
63
+ class TestWorker
64
+ def do_work
65
+ sleep 1
66
+ end
67
+
68
+ include AppOpticsAPMMethodProfiling
69
+ profile_method :do_work, 'do_work'
70
+ end
71
+
72
+ ::AppOpticsAPM::API.start_trace('method_profiling', '', {}) do
73
+ # Call the profiled class method
74
+ tw = TestWorker.new
75
+ tw.do_work
76
+ end
77
+
78
+ traces = get_all_traces
79
+ traces.count.must_equal 4
80
+
81
+ validate_outer_layers(traces, 'method_profiling')
82
+
83
+ kvs = {}
84
+ kvs["Label"] = 'profile_entry'
85
+ kvs["Language"] = "ruby"
86
+ kvs["ProfileName"] = "do_work"
87
+ kvs["FunctionName"] = "do_work"
88
+ kvs["Class"] = "TestWorker"
89
+
90
+ validate_event_keys(traces[1], kvs)
91
+
92
+ traces[1].has_key?("Layer").must_equal false
93
+ traces[1].has_key?("File").must_equal true
94
+ traces[1].has_key?("LineNumber").must_equal true
95
+
96
+ kvs.clear
97
+ kvs["Label"] = "profile_exit"
98
+ kvs["Language"] = "ruby"
99
+ kvs["ProfileName"] = "do_work"
100
+
101
+ validate_event_keys(traces[2], kvs)
102
+ traces[2].has_key?("Layer").must_equal false
103
+ end
104
+
105
+ it 'should trace Module class methods' do
106
+ module TestWorker
107
+ def self.do_work
108
+ sleep 1
109
+ end
110
+
111
+ class << self
112
+ include AppOpticsAPMMethodProfiling
113
+ profile_method :do_work, 'do_work'
114
+ end
115
+ end
116
+
117
+ ::AppOpticsAPM::API.start_trace('method_profiling', '', {}) do
118
+ # Call the profiled class method
119
+ TestWorker.do_work
120
+ end
121
+
122
+ traces = get_all_traces
123
+ traces.count.must_equal 4
124
+ validate_outer_layers(traces, 'method_profiling')
125
+
126
+ kvs = {}
127
+ kvs["Label"] = 'profile_entry'
128
+ kvs["Language"] = "ruby"
129
+ kvs["ProfileName"] = "do_work"
130
+ kvs["FunctionName"] = "do_work"
131
+ kvs["Module"] = "TestWorker"
132
+
133
+ validate_event_keys(traces[1], kvs)
134
+
135
+ traces[1].has_key?("Layer").must_equal false
136
+ traces[1].has_key?("File").must_equal true
137
+ traces[1].has_key?("LineNumber").must_equal true
138
+
139
+ kvs.clear
140
+ kvs["Label"] = "profile_exit"
141
+ kvs["Language"] = "ruby"
142
+ kvs["ProfileName"] = "do_work"
143
+
144
+ validate_event_keys(traces[2], kvs)
145
+ traces[2].has_key?("Layer").must_equal false
146
+ end
147
+
148
+ it 'should not store arguments and return value by default' do
149
+ class TestWorker
150
+ def self.do_work(_s, _i, _a, _h)
151
+ sleep 1
152
+ return "the zebra is loose"
153
+ end
154
+
155
+ class << self
156
+ include AppOpticsAPMMethodProfiling
157
+ # Default call method
158
+ profile_method :do_work, 'do_work'
159
+ end
160
+ end
161
+
162
+ ::AppOpticsAPM::API.start_trace('method_profiling', '', {}) do
163
+ # Call the profiled class method
164
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
165
+ end
166
+
167
+ traces = get_all_traces
168
+ traces.count.must_equal 4
169
+
170
+ traces[1].has_key?("Args").must_equal false
171
+ traces[2].has_key?("ReturnValue").must_equal false
172
+ end
173
+
174
+ it 'should store arguments and return value when asked' do
175
+ class TestWorker
176
+ def self.do_work(_s, _i, _a, _h)
177
+ sleep 1
178
+ return "the zebra is loose"
179
+ end
180
+
181
+ class << self
182
+ include AppOpticsAPMMethodProfiling
183
+ profile_method :do_work, 'do_work', true, true
184
+ end
185
+ end
186
+
187
+ ::AppOpticsAPM::API.start_trace('method_profiling', '', {}) do
188
+ # Call the profiled class method
189
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
190
+ end
191
+
192
+ traces = get_all_traces
193
+ traces.count.must_equal 4
194
+
195
+ traces[1].has_key?("Args").must_equal true
196
+ traces[1]["Args"].must_equal "\"String Argument\"\n203984\n[\"1\", \"2\", 3]\n{:color=>:black}\n"
197
+
198
+ traces[2].has_key?("ReturnValue").must_equal true
199
+ traces[2]["ReturnValue"].must_equal "\"the zebra is loose\"\n"
200
+ end
201
+ end