appoptics_apm 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
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,204 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'minitest_helper'
5
+
6
+ unless defined?(JRUBY_VERSION)
7
+ class BunnyConsumerTest < Minitest::Test
8
+ def setup
9
+ # Support specific environment variables to support remote rabbitmq servers
10
+ ENV['APPOPTICS_RABBITMQ_SERVER'] = "127.0.0.1" unless ENV['APPOPTICS_RABBITMQ_SERVER']
11
+ ENV['APPOPTICS_RABBITMQ_PORT'] = "5672" unless ENV['APPOPTICS_RABBITMQ_PORT']
12
+ ENV['APPOPTICS_RABBITMQ_USERNAME'] = "guest" unless ENV['APPOPTICS_RABBITMQ_USERNAME']
13
+ ENV['APPOPTICS_RABBITMQ_PASSWORD'] = "guest" unless ENV['APPOPTICS_RABBITMQ_PASSWORD']
14
+ ENV['APPOPTICS_RABBITMQ_VHOST'] = "/" unless ENV['APPOPTICS_RABBITMQ_VHOST']
15
+
16
+ @connection_params = {}
17
+ @connection_params[:host] = ENV['APPOPTICS_RABBITMQ_SERVER']
18
+ @connection_params[:port] = ENV['APPOPTICS_RABBITMQ_PORT']
19
+ @connection_params[:vhost] = ENV['APPOPTICS_RABBITMQ_VHOST']
20
+ @connection_params[:user] = ENV['APPOPTICS_RABBITMQ_USERNAME']
21
+ @connection_params[:pass] = ENV['APPOPTICS_RABBITMQ_PASSWORD']
22
+
23
+ clear_all_traces
24
+ end
25
+
26
+ def test_consume
27
+ @conn = Bunny.new(@connection_params)
28
+ @conn.start
29
+ @ch = @conn.create_channel
30
+ @queue = @ch.queue("tv.ruby.consumer.test", :exclusive => true)
31
+ @exchange = @ch.default_exchange
32
+
33
+ @queue.subscribe(:block => false, :manual_ack => true) do |delivery_info, properties, payload|
34
+ # Make an http call to spice things up
35
+ uri = URI('http://127.0.0.1:8101/')
36
+ http = Net::HTTP.new(uri.host, uri.port)
37
+ http.get('/?q=1').read_body
38
+ end
39
+
40
+ AppOpticsAPM::API.start_trace('bunny_consume_test') do
41
+ @exchange.publish("The Tortoise and the Hare", :routing_key => @queue.name, :app_id => "msg_app", :type => :generic)
42
+ end
43
+
44
+ sleep 1
45
+
46
+ traces = get_all_traces
47
+
48
+ traces.count.must_equal 12
49
+ assert valid_edges?(traces), "Invalid edge in traces"
50
+
51
+ traces[5]['Layer'].must_equal "net-http"
52
+ traces[5]['Label'].must_equal "entry"
53
+ traces[10]['Layer'].must_equal "net-http"
54
+ traces[10]['Label'].must_equal "exit"
55
+
56
+ traces[4]['Spec'].must_equal "job"
57
+ traces[4]['Flavor'].must_equal "rabbitmq"
58
+ traces[4]['Queue'].must_equal "tv.ruby.consumer.test"
59
+ traces[4]['RemoteHost'].must_equal @connection_params[:host]
60
+ traces[4]['RemotePort'].must_equal @connection_params[:port].to_i
61
+ traces[4]['VirtualHost'].must_equal @connection_params[:vhost]
62
+ traces[4]['RoutingKey'].must_equal "tv.ruby.consumer.test"
63
+ traces[4]['Controller'].must_equal "msg_app"
64
+ traces[4]['Action'].must_equal "generic"
65
+ traces[4]['URL'].must_equal "/bunny/tv.ruby.consumer.test"
66
+ traces[4].key?('SourceTrace').must_equal true
67
+ traces[4].key?('Backtrace').must_equal false
68
+
69
+ @conn.close
70
+ end
71
+
72
+ def test_blocking_consume
73
+ skip if RUBY_VERSION < '2.0'
74
+ @conn = Bunny.new(@connection_params)
75
+ @conn.start
76
+ @ch = @conn.create_channel
77
+ @queue = @ch.queue("tv.ruby.consumer.blocking.test", :exclusive => true)
78
+ @exchange = @ch.default_exchange
79
+
80
+ Thread.new {
81
+ @queue.subscribe(:block => true, :manual_ack => true) do |delivery_info, properties, payload|
82
+ # Make an http call to spice things up
83
+ uri = URI('http://127.0.0.1:8101/')
84
+ http = Net::HTTP.new(uri.host, uri.port)
85
+ http.get('/?q=1').read_body
86
+ end
87
+ }
88
+
89
+ @exchange.publish("The Tortoise and the Hare", :routing_key => @queue.name, :app_id => "msg_app", :type => :generic)
90
+
91
+ sleep 1
92
+
93
+ traces = get_all_traces
94
+ traces.count.must_equal 8
95
+
96
+ validate_outer_layers(traces, "rabbitmq-consumer")
97
+ assert valid_edges?(traces), "Invalid edge in traces"
98
+
99
+ traces[1]['Layer'].must_equal "net-http"
100
+ traces[1]['Label'].must_equal "entry"
101
+ traces[6]['Layer'].must_equal "net-http"
102
+ traces[6]['Label'].must_equal "exit"
103
+
104
+ traces[0]['Spec'].must_equal "job"
105
+ traces[0]['Flavor'].must_equal "rabbitmq"
106
+ traces[0]['Queue'].must_equal "tv.ruby.consumer.blocking.test"
107
+ traces[0]['RemoteHost'].must_equal @connection_params[:host]
108
+ traces[0]['RemotePort'].must_equal @connection_params[:port].to_i
109
+ traces[0]['VirtualHost'].must_equal @connection_params[:vhost]
110
+ traces[0]['RoutingKey'].must_equal "tv.ruby.consumer.blocking.test"
111
+ traces[0]['Controller'].must_equal "msg_app"
112
+ traces[0]['Action'].must_equal "generic"
113
+ traces[0]['URL'].must_equal "/bunny/tv.ruby.consumer.blocking.test"
114
+ traces[0].key?('Backtrace').must_equal false
115
+
116
+ @conn.close
117
+ end
118
+
119
+ def test_consume_error_handling
120
+ @conn = Bunny.new(@connection_params)
121
+ @conn.start
122
+ @ch = @conn.create_channel
123
+ @queue = @ch.queue("tv.ruby.consumer.error.test", :exclusive => true)
124
+ @exchange = @ch.default_exchange
125
+
126
+ @queue.subscribe(:block => false, :manual_ack => true) do |delivery_info, properties, payload|
127
+ raise "blah"
128
+ end
129
+
130
+ @exchange.publish("The Tortoise and the Hare", :routing_key => @queue.name, :app_id => "msg_app", :type => :generic)
131
+
132
+ sleep 1
133
+
134
+ traces = get_all_traces
135
+ traces.count.must_equal 3
136
+
137
+ validate_outer_layers(traces, "rabbitmq-consumer")
138
+ assert valid_edges?(traces), "Invalid edge in traces"
139
+
140
+ traces[0]['Spec'].must_equal "job"
141
+ traces[0]['Flavor'].must_equal "rabbitmq"
142
+ traces[0]['Queue'].must_equal "tv.ruby.consumer.error.test"
143
+ traces[0]['RemoteHost'].must_equal @connection_params[:host]
144
+ traces[0]['RemotePort'].must_equal @connection_params[:port].to_i
145
+ traces[0]['VirtualHost'].must_equal @connection_params[:vhost]
146
+ traces[0]['RoutingKey'].must_equal "tv.ruby.consumer.error.test"
147
+ traces[0]['Controller'].must_equal "msg_app"
148
+ traces[0]['Action'].must_equal "generic"
149
+ traces[0]['URL'].must_equal "/bunny/tv.ruby.consumer.error.test"
150
+ traces[0].key?('Backtrace').must_equal false
151
+
152
+ traces[1]['Layer'].must_equal "rabbitmq-consumer"
153
+ traces[1]['Label'].must_equal "error"
154
+ traces[1]['ErrorClass'].must_equal "RuntimeError"
155
+ traces[1]['ErrorMsg'].must_equal "blah"
156
+ traces[1].key?('Backtrace').must_equal true
157
+
158
+ traces[2]['Layer'].must_equal "rabbitmq-consumer"
159
+ traces[2]['Label'].must_equal "exit"
160
+ end
161
+
162
+ def test_message_id_capture
163
+ @conn = Bunny.new(@connection_params)
164
+ @conn.start
165
+ @ch = @conn.create_channel
166
+ @queue = @ch.queue("tv.ruby.consumer.msgid.test", :exclusive => true)
167
+ @exchange = @ch.default_exchange
168
+
169
+ @queue.subscribe(:block => false, :manual_ack => true) do |delivery_info, properties, payload|
170
+ # Make an http call to spice things up
171
+ uri = URI('http://127.0.0.1:8101/')
172
+ http = Net::HTTP.new(uri.host, uri.port)
173
+ http.get('/?q=1').read_body
174
+ end
175
+
176
+ AppOpticsAPM::API.start_trace('bunny_consume_test') do
177
+ @exchange.publish("The Tortoise and the Hare", :message_id => "1234", :routing_key => @queue.name, :app_id => "msg_app", :type => :generic)
178
+ end
179
+
180
+ sleep 1
181
+
182
+ traces = get_all_traces
183
+
184
+ traces.count.must_equal 12
185
+ assert valid_edges?(traces), "Invalid edge in traces"
186
+
187
+ traces[4]['Spec'].must_equal "job"
188
+ traces[4]['Flavor'].must_equal "rabbitmq"
189
+ traces[4]['Queue'].must_equal "tv.ruby.consumer.msgid.test"
190
+ traces[4]['RemoteHost'].must_equal @connection_params[:host]
191
+ traces[4]['RemotePort'].must_equal @connection_params[:port].to_i
192
+ traces[4]['VirtualHost'].must_equal @connection_params[:vhost]
193
+ traces[4]['RoutingKey'].must_equal "tv.ruby.consumer.msgid.test"
194
+ traces[4]['Controller'].must_equal "msg_app"
195
+ traces[4]['Action'].must_equal "generic"
196
+ traces[4]['URL'].must_equal "/bunny/tv.ruby.consumer.msgid.test"
197
+ traces[4]['MsgID'].must_equal "1234"
198
+ traces[4].key?('SourceTrace').must_equal true
199
+ traces[4].key?('Backtrace').must_equal false
200
+
201
+ @conn.close
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,398 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ if RUBY_VERSION > '1.8.7' && !defined?(JRUBY_VERSION)
5
+
6
+ require 'minitest_helper'
7
+ require 'appoptics_apm/inst/rack'
8
+ require File.expand_path(File.dirname(__FILE__) + '../../frameworks/apps/sinatra_simple')
9
+
10
+ class CurbTest < Minitest::Test
11
+ include Rack::Test::Methods
12
+
13
+ def setup
14
+ clear_all_traces
15
+ AppOpticsAPM.config_lock.synchronize {
16
+ @cb = AppOpticsAPM::Config[:curb][:collect_backtraces]
17
+ @log_args = AppOpticsAPM::Config[:curb][:log_args]
18
+ @tm = AppOpticsAPM::Config[:tracing_mode]
19
+ }
20
+ end
21
+
22
+ def teardown
23
+ AppOpticsAPM.config_lock.synchronize {
24
+ AppOpticsAPM::Config[:curb][:collect_backtraces] = @cb
25
+ AppOpticsAPM::Config[:curb][:log_args] = @log_args
26
+ AppOpticsAPM::Config[:tracing_mode] = @tm
27
+ }
28
+ end
29
+
30
+ def app
31
+ SinatraSimple
32
+ end
33
+
34
+ def assert_correct_traces(url, method)
35
+ traces = get_all_traces
36
+ assert_equal 7, traces.count, "Trace count"
37
+ validate_outer_layers(traces, "curb_tests")
38
+
39
+ assert_equal 'curb', traces[1]['Layer']
40
+ assert_equal 'entry', traces[1]['Label']
41
+ assert_equal 1, traces[1]['IsService']
42
+ assert_equal url, traces[1]['RemoteURL']
43
+ assert_equal method, traces[1]['HTTPMethod']
44
+ assert traces[1]['Backtrace']
45
+
46
+ assert_equal 'curb', traces[5]['Layer']
47
+ assert_equal 'exit', traces[5]['Label']
48
+ end
49
+
50
+ def test_reports_version_init
51
+ init_kvs = ::AppOpticsAPM::Util.build_init_report
52
+ assert init_kvs.key?('Ruby.curb.Version')
53
+ assert_equal ::Curl::CURB_VERSION, init_kvs['Ruby.curb.Version']
54
+ end
55
+
56
+ def test_class_get_request
57
+ response = nil
58
+
59
+ AppOpticsAPM::API.start_trace('curb_tests') do
60
+ response = Curl.get('http://127.0.0.1:8101/')
61
+ end
62
+
63
+ assert response.body_str == "Hello AppOpticsAPM!"
64
+ assert response.response_code == 200
65
+ assert response.header_str =~ /X-Trace/, "X-Trace response header"
66
+
67
+ assert_correct_traces('http://127.0.0.1:8101/', 'GET')
68
+ end
69
+
70
+ def test_class_delete_request
71
+ response = nil
72
+
73
+ AppOpticsAPM::API.start_trace('curb_tests') do
74
+ response = Curl.delete('http://127.0.0.1:8101/?curb_delete_test', :id => 1)
75
+ end
76
+
77
+ assert response.body_str == "Hello AppOpticsAPM!"
78
+ assert response.response_code == 200
79
+ assert response.header_str =~ /X-Trace/, "X-Trace response header"
80
+
81
+ assert_correct_traces('http://127.0.0.1:8101/?curb_delete_test', 'DELETE')
82
+ end
83
+
84
+ def test_class_post_request
85
+ response = nil
86
+
87
+ AppOpticsAPM::API.start_trace('curb_tests') do
88
+ response = Curl.post('http://127.0.0.1:8101/')
89
+ end
90
+
91
+ assert response.body_str == "Hello AppOpticsAPM!"
92
+ assert response.response_code == 200
93
+ assert response.header_str =~ /X-Trace/, "X-Trace response header"
94
+
95
+ assert_correct_traces('http://127.0.0.1:8101/', 'POST')
96
+ end
97
+
98
+ def test_easy_class_perform
99
+ response = nil
100
+
101
+ AppOpticsAPM::API.start_trace('curb_tests') do
102
+ response = Curl::Easy.perform("http://127.0.0.1:8101/")
103
+ end
104
+
105
+ assert response.is_a?(::Curl::Easy)
106
+ assert response.body_str == "Hello AppOpticsAPM!"
107
+ assert response.response_code == 200
108
+ assert response.header_str =~ /X-Trace/, "X-Trace response header"
109
+
110
+ assert_correct_traces('http://127.0.0.1:8101/', 'GET')
111
+ end
112
+
113
+ def test_easy_http_head
114
+ c = nil
115
+
116
+ AppOpticsAPM::API.start_trace('curb_tests') do
117
+ c = Curl::Easy.new("http://127.0.0.1:8101/")
118
+ c.http_head
119
+ end
120
+
121
+ assert c.is_a?(::Curl::Easy), "Response type"
122
+ assert c.response_code == 200
123
+ assert c.header_str =~ /X-Trace/, "X-Trace response header"
124
+
125
+ assert_correct_traces('http://127.0.0.1:8101/', 'GET')
126
+ end
127
+
128
+ def test_easy_http_put
129
+ c = nil
130
+
131
+ AppOpticsAPM::API.start_trace('curb_tests') do
132
+ c = Curl::Easy.new("http://127.0.0.1:8101/")
133
+ c.http_put(:id => 1)
134
+ end
135
+
136
+ assert c.is_a?(::Curl::Easy), "Response type"
137
+ assert c.response_code == 200
138
+ assert c.header_str =~ /X-Trace/, "X-Trace response header"
139
+
140
+ assert_correct_traces('http://127.0.0.1:8101/', 'PUT')
141
+ end
142
+
143
+ def test_easy_http_post
144
+ c = nil
145
+
146
+ AppOpticsAPM::API.start_trace('curb_tests') do
147
+ url = "http://127.0.0.1:8101/"
148
+ c = Curl::Easy.new(url)
149
+ c.http_post(url, :id => 1)
150
+ end
151
+
152
+ assert c.is_a?(::Curl::Easy), "Response type"
153
+ assert c.response_code == 200
154
+ assert c.header_str =~ /X-Trace/, "X-Trace response header"
155
+
156
+ assert_correct_traces('http://127.0.0.1:8101/', 'POST')
157
+ end
158
+
159
+ def test_class_fetch_with_block
160
+ response = nil
161
+
162
+ AppOpticsAPM::API.start_trace('curb_tests') do
163
+ response = Curl::Easy.perform("http://127.0.0.1:8101/") do |curl|
164
+ curl.headers["User-Agent"] = "AppOpticsAPM 2000"
165
+ end
166
+ end
167
+
168
+ assert response.is_a?(::Curl::Easy), "Response type"
169
+ assert response.response_code == 200
170
+ assert response.header_str =~ /X-Trace/, "X-Trace response header"
171
+
172
+ traces = get_all_traces
173
+ assert_equal 7, traces.count, "Trace count"
174
+ validate_outer_layers(traces, "curb_tests")
175
+
176
+ assert_correct_traces('http://127.0.0.1:8101/', 'GET')
177
+ end
178
+
179
+ def test_multi_basic_get
180
+ responses = nil
181
+ easy_options = {:follow_location => true}
182
+ multi_options = {:pipeline => false}
183
+
184
+ urls = []
185
+ urls << "http://127.0.0.1:8101/?one=1"
186
+ urls << "http://127.0.0.1:8101/?two=2"
187
+ urls << "http://127.0.0.1:8101/?three=3"
188
+
189
+ AppOpticsAPM::API.start_trace('curb_tests') do
190
+ responses = Curl::Multi.get(urls, easy_options, multi_options) do |easy|
191
+ nil
192
+ end
193
+ end
194
+
195
+ traces = get_all_traces
196
+ assert_equal 13, traces.count, "Trace count"
197
+ validate_outer_layers(traces, "curb_tests")
198
+
199
+ assert_equal traces[1]['Layer'], 'curb_multi'
200
+ assert_equal traces[1]['Label'], 'entry'
201
+ assert_equal traces[11]['Layer'], 'curb_multi'
202
+ assert_equal traces[11]['Label'], 'exit'
203
+ end
204
+
205
+ def test_multi_basic_post
206
+ easy_options = {:follow_location => true, :multipart_form_post => true}
207
+ multi_options = {:pipeline => true}
208
+
209
+ urls = []
210
+ urls << { :url => "http://127.0.0.1:8101/1", :post_fields => { :id => 1 } }
211
+ urls << { :url => "http://127.0.0.1:8101/2", :post_fields => { :id => 2 } }
212
+ urls << { :url => "http://127.0.0.1:8101/3", :post_fields => { :id => 3 } }
213
+
214
+ AppOpticsAPM::API.start_trace('curb_tests') do
215
+ Curl::Multi.post(urls, easy_options, multi_options) do |easy|
216
+ nil
217
+ end
218
+ end
219
+
220
+ traces = get_all_traces
221
+ assert_equal 13, traces.count, "Trace count"
222
+ validate_outer_layers(traces, "curb_tests")
223
+
224
+ assert_equal traces[1]['Layer'], 'curb_multi'
225
+ assert_equal traces[1]['Label'], 'entry'
226
+ assert_equal traces[11]['Layer'], 'curb_multi'
227
+ assert_equal traces[11]['Label'], 'exit'
228
+ end
229
+
230
+ def test_multi_basic_get_pipeline
231
+ easy_options = {:follow_location => true}
232
+ multi_options = {:pipeline => true}
233
+
234
+ urls = []
235
+ urls << "http://127.0.0.1:8101/?one=1"
236
+ urls << "http://127.0.0.1:8101/?two=2"
237
+ urls << "http://127.0.0.1:8101/?three=3"
238
+
239
+ AppOpticsAPM::API.start_trace('curb_tests') do
240
+ Curl::Multi.get(urls, easy_options, multi_options) do |easy|
241
+ nil
242
+ end
243
+ end
244
+
245
+ traces = get_all_traces
246
+ assert_equal 13, traces.count, "Trace count"
247
+ validate_outer_layers(traces, "curb_tests")
248
+
249
+ assert_equal traces[1]['Layer'], 'curb_multi'
250
+ assert_equal traces[1]['Label'], 'entry'
251
+ assert_equal traces[11]['Layer'], 'curb_multi'
252
+ assert_equal traces[11]['Label'], 'exit'
253
+ end
254
+
255
+ def test_multi_advanced_get
256
+ responses = {}
257
+
258
+ urls = []
259
+ urls << "http://127.0.0.1:8101/?one=1"
260
+ urls << "http://127.0.0.1:8101/?two=2"
261
+ urls << "http://127.0.0.1:8101/?three=3"
262
+
263
+ AppOpticsAPM::API.start_trace('curb_tests') do
264
+ m = Curl::Multi.new
265
+ urls.each do |url|
266
+ responses[url] = ""
267
+ c = Curl::Easy.new(url) do |curl|
268
+ curl.follow_location = true
269
+ end
270
+ m.add c
271
+ end
272
+
273
+ m.perform do
274
+ nil
275
+ end
276
+ end
277
+
278
+ traces = get_all_traces
279
+ assert_equal 13, traces.count, "Trace count"
280
+ validate_outer_layers(traces, "curb_tests")
281
+
282
+ assert_equal traces[1]['Layer'], 'curb_multi'
283
+ assert_equal traces[1]['Label'], 'entry'
284
+ assert_equal traces[11]['Layer'], 'curb_multi'
285
+ assert_equal traces[11]['Label'], 'exit'
286
+ end
287
+
288
+ def test_requests_with_errors
289
+ begin
290
+ AppOpticsAPM::API.start_trace('curb_tests') do
291
+ Curl.get('http://asfjalkfjlajfljkaljf/')
292
+ end
293
+ rescue
294
+ # ignore exception, only check traces
295
+ end
296
+
297
+ traces = get_all_traces
298
+ assert_equal 5, traces.count, "Trace count"
299
+ validate_outer_layers(traces, "curb_tests")
300
+ assert valid_edges?(traces), "Trace edge validation"
301
+
302
+ assert_equal 1, traces[1]['IsService']
303
+ assert_equal 'http://asfjalkfjlajfljkaljf/', traces[1]['RemoteURL']
304
+ assert_equal 'GET', traces[1]['HTTPMethod']
305
+ assert traces[1]['Backtrace']
306
+
307
+ assert_equal 'curb', traces[2]['Layer']
308
+ assert_equal 'error', traces[2]['Label']
309
+ assert_equal "Curl::Err::HostResolutionError", traces[2]['ErrorClass']
310
+ assert traces[2].key?('ErrorMsg')
311
+ assert traces[2].key?('Backtrace')
312
+
313
+ assert_equal 'curb', traces[3]['Layer']
314
+ assert_equal 'exit', traces[3]['Label']
315
+ end
316
+
317
+ def test_obey_log_args_when_false
318
+ # When testing global config options, use the config_lock
319
+ # semaphore to lock between other running tests.
320
+ AppOpticsAPM.config_lock.synchronize {
321
+ AppOpticsAPM::Config[:curb][:log_args] = false
322
+
323
+ AppOpticsAPM::API.start_trace('curb_tests') do
324
+ Curl.get('http://127.0.0.1:8101/?blah=1')
325
+ end
326
+ }
327
+
328
+ traces = get_all_traces
329
+ assert_equal 7, traces.count, "Trace count"
330
+ assert_equal "http://127.0.0.1:8101/", traces[1]['RemoteURL']
331
+ end
332
+
333
+ def test_obey_log_args_when_true
334
+ # When testing global config options, use the config_lock
335
+ # semaphore to lock between other running tests.
336
+ AppOpticsAPM.config_lock.synchronize {
337
+ AppOpticsAPM::Config[:curb][:log_args] = true
338
+
339
+ AppOpticsAPM::API.start_trace('curb_tests') do
340
+ Curl.get('http://127.0.0.1:8101/?blah=1')
341
+ end
342
+ }
343
+
344
+ traces = get_all_traces
345
+ assert_equal 7, traces.count, "Trace count"
346
+ assert_equal "http://127.0.0.1:8101/?blah=1", traces[1]['RemoteURL']
347
+ end
348
+
349
+ def test_without_tracing_class_get
350
+ response = ::Curl.get('http://127.0.0.1:8101/?blah=1')
351
+
352
+ assert response.headers['X-Trace'] == nil
353
+ assert response.body_str == "Hello AppOpticsAPM!"
354
+ assert response.response_code == 200
355
+ end
356
+
357
+ def test_without_tracing_easy_perform
358
+ response = Curl::Easy.perform("http://127.0.0.1:8101/")
359
+
360
+ assert response.headers['X-Trace'] == nil
361
+ assert response.body_str == "Hello AppOpticsAPM!"
362
+ assert response.response_code == 200
363
+ end
364
+
365
+ def test_obey_collect_backtraces_when_true
366
+ # When testing global config options, use the config_lock
367
+ # semaphore to lock between other running tests.
368
+ AppOpticsAPM.config_lock.synchronize {
369
+ AppOpticsAPM::Config[:curb][:collect_backtraces] = true
370
+ sleep 1
371
+
372
+ AppOpticsAPM::API.start_trace('curb_test') do
373
+ Curl.get("http://127.0.0.1:8101/")
374
+ end
375
+ }
376
+
377
+ traces = get_all_traces
378
+ layer_has_key(traces, 'curb', 'Backtrace')
379
+ end
380
+
381
+ def test_obey_collect_backtraces_when_false
382
+ # When testing global config options, use the config_lock
383
+ # semaphore to lock between other running tests.
384
+ AppOpticsAPM.config_lock.synchronize {
385
+ AppOpticsAPM::Config[:curb][:collect_backtraces] = false
386
+
387
+ AppOpticsAPM::API.start_trace('curb_test') do
388
+ Curl.get("http://127.0.0.1:8101/")
389
+ end
390
+ }
391
+
392
+ traces = get_all_traces
393
+ layer_doesnt_have_key(traces, 'curb', 'Backtrace')
394
+ end
395
+
396
+ end
397
+ end
398
+