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,584 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'minitest_helper'
5
+
6
+ ENV['APPOPTICS_MONGO_SERVER'] = "127.0.0.1:27017" unless ENV['APPOPTICS_MONGO_SERVER']
7
+ ENV['APPOPTICS_MONGO_SERVER'] += ":27017" unless ENV['APPOPTICS_MONGO_SERVER'] =~ /\:27017$/
8
+
9
+ if defined?(::Mongo::VERSION) && Mongo::VERSION >= '2.0.0'
10
+ describe "MongoCollection" do
11
+ before do
12
+ clear_all_traces
13
+
14
+ @client = Mongo::Client.new([ ENV['APPOPTICS_MONGO_SERVER'] ], :database => "appoptics_apm-#{ENV['RACK_ENV']}")
15
+ @db = @client.database
16
+
17
+ if Mongo::VERSION < '2.2'
18
+ Mongo::Logger.logger.level = Logger::INFO
19
+ else
20
+ @client.logger.level = Logger::INFO
21
+ end
22
+
23
+ @collections = @db.collection_names
24
+ @testCollection = @client[:test_collection]
25
+ @testCollection.create unless @collections.include? "test_collection"
26
+
27
+ # These are standard entry/exit KVs that are passed up with all mongo operations
28
+ @entry_kvs = {
29
+ 'Layer' => 'mongo',
30
+ 'Label' => 'entry',
31
+ 'Flavor' => 'mongodb',
32
+ 'Database' => 'appoptics_apm-test',
33
+ 'RemoteHost' => ENV['APPOPTICS_MONGO_SERVER'] }
34
+
35
+ @exit_kvs = { 'Layer' => 'mongo', 'Label' => 'exit' }
36
+ @collect_backtraces = AppOpticsAPM::Config[:mongo][:collect_backtraces]
37
+ end
38
+
39
+ after do
40
+ AppOpticsAPM::Config[:mongo][:collect_backtraces] = @collect_backtraces
41
+
42
+ if @db.collection_names.include?("temp_collection")
43
+ @db[:temp_collection].drop
44
+ end
45
+ end
46
+
47
+ it "should trace collection creation" do
48
+ r = nil
49
+ collection = @db[:temp_collection]
50
+ AppOpticsAPM::API.start_trace('mongo_test', nil, {}) do
51
+ r = collection.create
52
+ end
53
+
54
+ traces = get_all_traces
55
+ traces.count.must_equal 4
56
+
57
+ r.must_be_instance_of ::Mongo::Operation::Result
58
+ if Mongo::VERSION < '2.2'
59
+ r.successful?.must_equal true
60
+ else
61
+ r.ok?.must_equal true
62
+ end
63
+
64
+ validate_outer_layers(traces, 'mongo_test')
65
+ validate_event_keys(traces[1], @entry_kvs)
66
+ validate_event_keys(traces[2], @exit_kvs)
67
+
68
+ traces[1]['QueryOp'].must_equal "create"
69
+ traces[1]['New_Collection_Name'].must_equal "temp_collection"
70
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
71
+ end
72
+
73
+ it "should trace drop_collection" do
74
+ r = nil
75
+ collection = @db[:deleteme_collection]
76
+
77
+ # Create something to drop unless it already exists
78
+ unless @db.collection_names.include?("deleteme_collection")
79
+ collection.create
80
+ end
81
+
82
+ AppOpticsAPM::API.start_trace('mongo_test', nil, {}) do
83
+ r = collection.drop
84
+ end
85
+
86
+ traces = get_all_traces
87
+ traces.count.must_equal 4
88
+
89
+ r.must_be_instance_of ::Mongo::Operation::Result
90
+ if Mongo::VERSION < '2.2'
91
+ r.successful?.must_equal true
92
+ else
93
+ r.ok?.must_equal true
94
+ end
95
+
96
+ validate_outer_layers(traces, 'mongo_test')
97
+ validate_event_keys(traces[1], @entry_kvs)
98
+ validate_event_keys(traces[2], @exit_kvs)
99
+
100
+ traces[1]['QueryOp'].must_equal "drop"
101
+ traces[1]['Collection'].must_equal "deleteme_collection"
102
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
103
+ end
104
+
105
+ it "should capture collection creation errors" do
106
+ collection = @db[:temp_collection]
107
+ collection.create
108
+
109
+ begin
110
+ AppOpticsAPM::API.start_trace('mongo_test', nil, {}) do
111
+ collection.create
112
+ end
113
+ rescue
114
+ end
115
+
116
+ traces = get_all_traces
117
+ traces.count.must_equal 5
118
+
119
+ validate_outer_layers(traces, 'mongo_test')
120
+ validate_event_keys(traces[1], @entry_kvs)
121
+ validate_event_keys(traces[3], @exit_kvs)
122
+
123
+ traces[1]['QueryOp'].must_equal "create"
124
+ traces[1]['New_Collection_Name'].must_equal "temp_collection"
125
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
126
+
127
+ traces[2]['Layer'].must_equal "mongo"
128
+ traces[2]['Label'].must_equal "error"
129
+ traces[2]['ErrorClass'].must_equal "Mongo::Error::OperationFailure"
130
+ traces[2]['ErrorMsg'].must_match /collection.*already exists/
131
+ traces[2].has_key?('Backtrace').must_equal true
132
+ end
133
+
134
+ it "should trace insert_one" do
135
+ r = nil
136
+ collection = @db[:tv_collection]
137
+
138
+ AppOpticsAPM::API.start_trace('mongo_test', nil, {}) do
139
+ r = collection.insert_one({ name => 'Rabel Lasen' })
140
+ end
141
+
142
+ traces = get_all_traces
143
+ traces.count.must_equal 4
144
+
145
+ r.must_be_instance_of Mongo::Operation::Write::Insert::Result
146
+ if Mongo::VERSION < '2.2'
147
+ r.successful?.must_equal true
148
+ else
149
+ r.ok?.must_equal true
150
+ end
151
+
152
+ validate_outer_layers(traces, 'mongo_test')
153
+ validate_event_keys(traces[1], @entry_kvs)
154
+ validate_event_keys(traces[2], @exit_kvs)
155
+
156
+ traces[1]['QueryOp'].must_equal "insert_one"
157
+ traces[1]['Collection'].must_equal "tv_collection"
158
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
159
+ end
160
+
161
+ it "should trace insert_many" do
162
+ r = nil
163
+ collection = @db[:tv_collection]
164
+
165
+ AppOpticsAPM::API.start_trace('mongo_test', nil, {}) do
166
+ r = collection.insert_many([
167
+ { :name => 'Rabel Lasen' },
168
+ { :name => 'Louval Raiden' }])
169
+ end
170
+
171
+ traces = get_all_traces
172
+ traces.count.must_equal 4
173
+
174
+ if Mongo::VERSION < '2.1'
175
+ r.must_be_instance_of Mongo::Operation::Write::Insert::Result
176
+ else
177
+ r.must_be_instance_of Mongo::BulkWrite::Result
178
+ r.inserted_count.must_equal 2
179
+ end
180
+
181
+ validate_outer_layers(traces, 'mongo_test')
182
+ validate_event_keys(traces[1], @entry_kvs)
183
+ validate_event_keys(traces[2], @exit_kvs)
184
+
185
+ traces[1]['QueryOp'].must_equal "insert_many"
186
+ traces[1]['Collection'].must_equal "tv_collection"
187
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
188
+ end
189
+
190
+ it "should trace find" do
191
+ coll = @db[:test_collection]
192
+ r = nil
193
+
194
+ # Insert a doc to assure we get a result
195
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
196
+ coll.insert_one(doc)
197
+
198
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
199
+ r = coll.find(:name => "MyName", :limit => 1)
200
+ end
201
+
202
+ traces = get_all_traces
203
+ traces.count.must_equal 4
204
+
205
+ validate_outer_layers(traces, 'mongo_test')
206
+ validate_event_keys(traces[1], @entry_kvs)
207
+ validate_event_keys(traces[2], @exit_kvs)
208
+
209
+ r.must_be_instance_of Mongo::Collection::View
210
+
211
+ traces[1]['Collection'].must_equal "test_collection"
212
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
213
+ traces[1]['QueryOp'].must_equal "find"
214
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\",\"limit\":1}"
215
+ traces[1].has_key?('Query').must_equal true
216
+ end
217
+
218
+ it "should trace find_one_and_delete" do
219
+ skip unless Mongo::VERSION >= '2.1'
220
+
221
+ coll = @db[:test_collection]
222
+ r = nil
223
+
224
+ # Insert a doc to assure we get a result
225
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
226
+ coll.insert_one(doc)
227
+
228
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
229
+ r = coll.find_one_and_delete(:name => "MyName")
230
+ end
231
+
232
+ traces = get_all_traces
233
+ traces.count.must_equal 4
234
+
235
+ validate_outer_layers(traces, 'mongo_test')
236
+ validate_event_keys(traces[1], @entry_kvs)
237
+ validate_event_keys(traces[2], @exit_kvs)
238
+
239
+ r.must_be_instance_of BSON::Document
240
+
241
+ traces[1]['Collection'].must_equal "test_collection"
242
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
243
+ traces[1]['QueryOp'].must_equal "find_one_and_delete"
244
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
245
+ traces[1].has_key?('Query').must_equal true
246
+ end
247
+
248
+ it "should trace find_one_and_update" do
249
+ skip unless Mongo::VERSION >= '2.1'
250
+ coll = @db[:test_collection]
251
+ r = nil
252
+
253
+ # Insert a doc to assure we get a result
254
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
255
+ coll.insert_one(doc)
256
+
257
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
258
+ r = coll.find_one_and_update({ :name => 'MyName' }, { "$set" => { :name => 'test1' }}, :return_document => :after)
259
+ end
260
+
261
+ traces = get_all_traces
262
+ traces.count.must_equal 4
263
+
264
+ validate_outer_layers(traces, 'mongo_test')
265
+ validate_event_keys(traces[1], @entry_kvs)
266
+ validate_event_keys(traces[2], @exit_kvs)
267
+
268
+ r.must_be_instance_of BSON::Document
269
+
270
+ traces[1]['Collection'].must_equal "test_collection"
271
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
272
+ traces[1]['QueryOp'].must_equal "find_one_and_update"
273
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
274
+ traces[1].has_key?('Query').must_equal true
275
+ end
276
+
277
+ it "should trace find_one_and_replace" do
278
+ skip unless Mongo::VERSION >= '2.1'
279
+ coll = @db[:test_collection]
280
+ r = nil
281
+
282
+ # Insert a doc to assure we get a result
283
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
284
+ coll.insert_one(doc)
285
+
286
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
287
+ r = coll.find_one_and_replace({ :name => 'MyName' }, { "$set" => { :name => 'test1' }}, :return_document => :after)
288
+ end
289
+
290
+ traces = get_all_traces
291
+ traces.count.must_equal 4
292
+
293
+ validate_outer_layers(traces, 'mongo_test')
294
+ validate_event_keys(traces[1], @entry_kvs)
295
+ validate_event_keys(traces[2], @exit_kvs)
296
+
297
+ r.must_be_instance_of BSON::Document
298
+
299
+ traces[1]['Collection'].must_equal "test_collection"
300
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
301
+ traces[1]['QueryOp'].must_equal "find_one_and_replace"
302
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
303
+ traces[1].has_key?('Query').must_equal true
304
+ end
305
+
306
+ it "should trace update_one" do
307
+ skip unless Mongo::VERSION >= '2.1'
308
+
309
+ coll = @db[:test_collection]
310
+ r = nil
311
+
312
+ # Insert a doc to assure we get a result
313
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
314
+ coll.insert_one(doc)
315
+
316
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
317
+ r = coll.update_one({ :name => 'MyName' }, { "$set" => { :name => 'test1' }}, :return_document => :after)
318
+ end
319
+
320
+ traces = get_all_traces
321
+ traces.count.must_equal 4
322
+
323
+ validate_outer_layers(traces, 'mongo_test')
324
+ validate_event_keys(traces[1], @entry_kvs)
325
+ validate_event_keys(traces[2], @exit_kvs)
326
+
327
+ r.class.ancestors.include?(Mongo::Operation::Result).must_equal true
328
+
329
+ traces[1]['Collection'].must_equal "test_collection"
330
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
331
+ traces[1]['QueryOp'].must_equal "update_one"
332
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
333
+ traces[1].has_key?('Query').must_equal true
334
+ end
335
+
336
+ it "should trace update_many" do
337
+ skip unless Mongo::VERSION > '2.1'
338
+ coll = @db[:test_collection]
339
+ r = nil
340
+
341
+ # Insert a doc to assure we get a result
342
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
343
+ coll.insert_one(doc)
344
+
345
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
346
+ r = coll.update_many({ :name => 'MyName' }, { "$set" => { :name => 'test1' }}, :return_document => :after)
347
+ end
348
+
349
+ traces = get_all_traces
350
+ traces.count.must_equal 4
351
+
352
+ validate_outer_layers(traces, 'mongo_test')
353
+ validate_event_keys(traces[1], @entry_kvs)
354
+ validate_event_keys(traces[2], @exit_kvs)
355
+
356
+ r.class.ancestors.include?(Mongo::Operation::Result).must_equal true
357
+
358
+ traces[1]['Collection'].must_equal "test_collection"
359
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
360
+ traces[1]['QueryOp'].must_equal "update_many"
361
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
362
+ traces[1].has_key?('Query').must_equal true
363
+ end
364
+
365
+ it "should trace delete_one" do
366
+ skip unless Mongo::VERSION > '2.1'
367
+ coll = @db[:test_collection]
368
+ r = nil
369
+
370
+ # Insert a doc to assure we get a result
371
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
372
+ coll.insert_one(doc)
373
+
374
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
375
+ r = coll.delete_one({ :name => 'MyName' })
376
+ end
377
+
378
+ traces = get_all_traces
379
+ traces.count.must_equal 4
380
+
381
+ validate_outer_layers(traces, 'mongo_test')
382
+ validate_event_keys(traces[1], @entry_kvs)
383
+ validate_event_keys(traces[2], @exit_kvs)
384
+
385
+ r.class.ancestors.include?(Mongo::Operation::Result).must_equal true
386
+
387
+ traces[1]['Collection'].must_equal "test_collection"
388
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
389
+ traces[1]['QueryOp'].must_equal "delete_one"
390
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
391
+ traces[1].has_key?('Query').must_equal true
392
+ end
393
+
394
+ it "should trace delete_many" do
395
+ skip unless Mongo::VERSION > '2.1'
396
+ coll = @db[:test_collection]
397
+ r = nil
398
+
399
+ # Insert a doc to assure we get a result
400
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
401
+ coll.insert_one(doc)
402
+
403
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
404
+ r = coll.delete_many({ :name => 'MyName' })
405
+ end
406
+
407
+ traces = get_all_traces
408
+ traces.count.must_equal 4
409
+
410
+ validate_outer_layers(traces, 'mongo_test')
411
+ validate_event_keys(traces[1], @entry_kvs)
412
+ validate_event_keys(traces[2], @exit_kvs)
413
+
414
+ r.class.ancestors.include?(Mongo::Operation::Result).must_equal true
415
+
416
+ traces[1]['Collection'].must_equal "test_collection"
417
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
418
+ traces[1]['QueryOp'].must_equal "delete_many"
419
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
420
+ traces[1].has_key?('Query').must_equal true
421
+ end
422
+
423
+ it "should trace replace_one" do
424
+ skip unless Mongo::VERSION > '2.1'
425
+ coll = @db[:test_collection]
426
+ r = nil
427
+
428
+ # Insert a doc to assure we get a result
429
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
430
+ coll.insert_one(doc)
431
+
432
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
433
+ r = coll.replace_one({ :name => 'test' }, { :name => 'test1' })
434
+ end
435
+
436
+ traces = get_all_traces
437
+ traces.count.must_equal 4
438
+
439
+ validate_outer_layers(traces, 'mongo_test')
440
+ validate_event_keys(traces[1], @entry_kvs)
441
+ validate_event_keys(traces[2], @exit_kvs)
442
+
443
+ r.class.ancestors.include?(Mongo::Operation::Result).must_equal true
444
+
445
+ traces[1]['Collection'].must_equal "test_collection"
446
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
447
+ traces[1]['QueryOp'].must_equal "replace_one"
448
+ traces[1]['Query'].must_equal "{\"name\":\"test\"}"
449
+ traces[1].has_key?('Query').must_equal true
450
+ end
451
+
452
+ it "should trace count" do
453
+ skip unless Mongo::VERSION > '2.1'
454
+ coll = @db[:test_collection]
455
+ r = nil
456
+
457
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
458
+ r = coll.count({ :name => 'MyName' })
459
+ end
460
+
461
+ traces = get_all_traces
462
+ traces.count.must_equal 4
463
+
464
+ validate_outer_layers(traces, 'mongo_test')
465
+ validate_event_keys(traces[1], @entry_kvs)
466
+ validate_event_keys(traces[2], @exit_kvs)
467
+
468
+ r.is_a?(Numeric).must_equal true
469
+
470
+ traces[1]['Collection'].must_equal "test_collection"
471
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
472
+ traces[1]['QueryOp'].must_equal "count"
473
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
474
+ traces[1].has_key?('Query').must_equal true
475
+ end
476
+
477
+ it "should trace distinct" do
478
+ skip unless Mongo::VERSION > '2.1'
479
+ coll = @db[:test_collection]
480
+ r = nil
481
+
482
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
483
+ r = coll.distinct('name', { :name => 'MyName' })
484
+ end
485
+
486
+ traces = get_all_traces
487
+ traces.count.must_equal 4
488
+
489
+ validate_outer_layers(traces, 'mongo_test')
490
+ validate_event_keys(traces[1], @entry_kvs)
491
+ validate_event_keys(traces[2], @exit_kvs)
492
+
493
+ r.is_a?(Array).must_equal true
494
+
495
+ traces[1]['Collection'].must_equal "test_collection"
496
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
497
+ traces[1]['QueryOp'].must_equal "distinct"
498
+ traces[1]['Query'].must_equal "{\"name\":\"MyName\"}"
499
+ traces[1].has_key?('Query').must_equal true
500
+ end
501
+
502
+ it "should trace aggregate" do
503
+ skip unless Mongo::VERSION >= '2.1'
504
+ coll = @db[:test_collection]
505
+ r = nil
506
+
507
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
508
+ r = coll.aggregate([ { "$group" => { "_id" => "$city", "tpop" => { "$sum" => "$pop" }}} ])
509
+ end
510
+
511
+ traces = get_all_traces
512
+ traces.count.must_equal 4
513
+
514
+ validate_outer_layers(traces, 'mongo_test')
515
+ validate_event_keys(traces[1], @entry_kvs)
516
+ validate_event_keys(traces[2], @exit_kvs)
517
+
518
+ r.must_be_instance_of Mongo::Collection::View::Aggregation
519
+
520
+ traces[1]['Collection'].must_equal "test_collection"
521
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
522
+ traces[1]['QueryOp'].must_equal "aggregate"
523
+ traces[1].key?('Query').must_equal false
524
+ end
525
+
526
+ it "should trace bulk_write" do
527
+ coll = @db[:test_collection]
528
+ r = nil
529
+
530
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
531
+ r = coll.bulk_write([ { :insert_one => { :x => 1} },
532
+ { :insert_one => { :x => 3} } ],
533
+ :ordered => true)
534
+ end
535
+
536
+ traces = get_all_traces
537
+ traces.count.must_equal 4
538
+
539
+ validate_outer_layers(traces, 'mongo_test')
540
+ validate_event_keys(traces[1], @entry_kvs)
541
+ validate_event_keys(traces[2], @exit_kvs)
542
+
543
+ if Mongo::VERSION < '2.1'
544
+ r.must_be_instance_of Hash
545
+ r[:n_inserted].must_equal 2
546
+ else
547
+ r.must_be_instance_of Mongo::BulkWrite::Result
548
+ end
549
+
550
+ traces[1]['Collection'].must_equal "test_collection"
551
+ traces[1].has_key?('Backtrace').must_equal AppOpticsAPM::Config[:mongo][:collect_backtraces]
552
+ traces[1]['QueryOp'].must_equal "bulk_write"
553
+ traces[1].key?('Query').must_equal false
554
+ end
555
+
556
+ it "should obey :collect_backtraces setting when true" do
557
+ AppOpticsAPM::Config[:mongo][:collect_backtraces] = true
558
+
559
+ coll = @db[:test_collection]
560
+
561
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
562
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
563
+ coll.insert_one(doc)
564
+ end
565
+
566
+ traces = get_all_traces
567
+ layer_has_key(traces, 'mongo', 'Backtrace')
568
+ end
569
+
570
+ it "should obey :collect_backtraces setting when false" do
571
+ AppOpticsAPM::Config[:mongo][:collect_backtraces] = false
572
+
573
+ coll = @db[:test_collection]
574
+
575
+ AppOpticsAPM::API.start_trace('mongo_test', '', {}) do
576
+ doc = {"name" => "MyName", "type" => "MyType", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
577
+ coll.insert_one(doc)
578
+ end
579
+
580
+ traces = get_all_traces
581
+ layer_doesnt_have_key(traces, 'mongo', 'Backtrace')
582
+ end
583
+ end
584
+ end