traceview 3.0.0-java

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 (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +5 -0
  4. data/.travis.yml +58 -0
  5. data/Appraisals +10 -0
  6. data/CHANGELOG.md +490 -0
  7. data/CONFIG.md +16 -0
  8. data/Gemfile +95 -0
  9. data/LICENSE +199 -0
  10. data/README.md +380 -0
  11. data/Rakefile +109 -0
  12. data/examples/DNT.md +35 -0
  13. data/examples/carrying_context.rb +225 -0
  14. data/examples/instrumenting_metal_controller.rb +8 -0
  15. data/examples/puma_on_heroku_config.rb +17 -0
  16. data/examples/tracing_async_threads.rb +125 -0
  17. data/examples/tracing_background_jobs.rb +52 -0
  18. data/examples/tracing_forked_processes.rb +100 -0
  19. data/examples/unicorn_on_heroku_config.rb +28 -0
  20. data/ext/oboe_metal/extconf.rb +61 -0
  21. data/ext/oboe_metal/noop/noop.c +7 -0
  22. data/ext/oboe_metal/src/bson/bson.h +221 -0
  23. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  24. data/ext/oboe_metal/src/oboe.h +275 -0
  25. data/ext/oboe_metal/src/oboe.hpp +352 -0
  26. data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
  27. data/ext/oboe_metal/tests/test.rb +11 -0
  28. data/gemfiles/mongo.gemfile +33 -0
  29. data/gemfiles/moped.gemfile +33 -0
  30. data/get_version.rb +5 -0
  31. data/init.rb +4 -0
  32. data/lib/joboe_metal.rb +206 -0
  33. data/lib/oboe/README +2 -0
  34. data/lib/oboe/backward_compatibility.rb +59 -0
  35. data/lib/oboe/inst/rack.rb +11 -0
  36. data/lib/oboe.rb +7 -0
  37. data/lib/oboe_metal.rb +151 -0
  38. data/lib/rails/generators/traceview/install_generator.rb +76 -0
  39. data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
  40. data/lib/traceview/api/layerinit.rb +51 -0
  41. data/lib/traceview/api/logging.rb +209 -0
  42. data/lib/traceview/api/memcache.rb +31 -0
  43. data/lib/traceview/api/profiling.rb +50 -0
  44. data/lib/traceview/api/tracing.rb +135 -0
  45. data/lib/traceview/api/util.rb +121 -0
  46. data/lib/traceview/api.rb +18 -0
  47. data/lib/traceview/base.rb +225 -0
  48. data/lib/traceview/config.rb +238 -0
  49. data/lib/traceview/frameworks/grape.rb +97 -0
  50. data/lib/traceview/frameworks/padrino/templates.rb +58 -0
  51. data/lib/traceview/frameworks/padrino.rb +64 -0
  52. data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
  53. data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
  54. data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
  55. data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
  56. data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
  57. data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
  58. data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
  59. data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
  60. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  61. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
  62. data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
  63. data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
  64. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
  65. data/lib/traceview/frameworks/rails.rb +145 -0
  66. data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
  67. data/lib/traceview/frameworks/sinatra.rb +95 -0
  68. data/lib/traceview/inst/cassandra.rb +279 -0
  69. data/lib/traceview/inst/dalli.rb +86 -0
  70. data/lib/traceview/inst/em-http-request.rb +99 -0
  71. data/lib/traceview/inst/excon.rb +111 -0
  72. data/lib/traceview/inst/faraday.rb +73 -0
  73. data/lib/traceview/inst/http.rb +87 -0
  74. data/lib/traceview/inst/httpclient.rb +173 -0
  75. data/lib/traceview/inst/memcache.rb +102 -0
  76. data/lib/traceview/inst/memcached.rb +94 -0
  77. data/lib/traceview/inst/mongo.rb +238 -0
  78. data/lib/traceview/inst/moped.rb +474 -0
  79. data/lib/traceview/inst/rack.rb +122 -0
  80. data/lib/traceview/inst/redis.rb +271 -0
  81. data/lib/traceview/inst/resque.rb +192 -0
  82. data/lib/traceview/inst/rest-client.rb +38 -0
  83. data/lib/traceview/inst/sequel.rb +162 -0
  84. data/lib/traceview/inst/typhoeus.rb +102 -0
  85. data/lib/traceview/instrumentation.rb +21 -0
  86. data/lib/traceview/loading.rb +94 -0
  87. data/lib/traceview/logger.rb +41 -0
  88. data/lib/traceview/method_profiling.rb +84 -0
  89. data/lib/traceview/ruby.rb +36 -0
  90. data/lib/traceview/support.rb +113 -0
  91. data/lib/traceview/thread_local.rb +26 -0
  92. data/lib/traceview/util.rb +250 -0
  93. data/lib/traceview/version.rb +16 -0
  94. data/lib/traceview/xtrace.rb +90 -0
  95. data/lib/traceview.rb +62 -0
  96. data/test/frameworks/apps/grape_nested.rb +30 -0
  97. data/test/frameworks/apps/grape_simple.rb +24 -0
  98. data/test/frameworks/apps/padrino_simple.rb +45 -0
  99. data/test/frameworks/apps/sinatra_simple.rb +24 -0
  100. data/test/frameworks/grape_test.rb +142 -0
  101. data/test/frameworks/padrino_test.rb +30 -0
  102. data/test/frameworks/sinatra_test.rb +30 -0
  103. data/test/instrumentation/cassandra_test.rb +380 -0
  104. data/test/instrumentation/dalli_test.rb +171 -0
  105. data/test/instrumentation/em_http_request_test.rb +86 -0
  106. data/test/instrumentation/excon_test.rb +207 -0
  107. data/test/instrumentation/faraday_test.rb +235 -0
  108. data/test/instrumentation/http_test.rb +140 -0
  109. data/test/instrumentation/httpclient_test.rb +296 -0
  110. data/test/instrumentation/memcache_test.rb +251 -0
  111. data/test/instrumentation/memcached_test.rb +226 -0
  112. data/test/instrumentation/mongo_test.rb +462 -0
  113. data/test/instrumentation/moped_test.rb +496 -0
  114. data/test/instrumentation/rack_test.rb +116 -0
  115. data/test/instrumentation/redis_hashes_test.rb +265 -0
  116. data/test/instrumentation/redis_keys_test.rb +318 -0
  117. data/test/instrumentation/redis_lists_test.rb +310 -0
  118. data/test/instrumentation/redis_misc_test.rb +160 -0
  119. data/test/instrumentation/redis_sets_test.rb +293 -0
  120. data/test/instrumentation/redis_sortedsets_test.rb +325 -0
  121. data/test/instrumentation/redis_strings_test.rb +333 -0
  122. data/test/instrumentation/resque_test.rb +62 -0
  123. data/test/instrumentation/rest-client_test.rb +294 -0
  124. data/test/instrumentation/sequel_mysql2_test.rb +326 -0
  125. data/test/instrumentation/sequel_mysql_test.rb +326 -0
  126. data/test/instrumentation/sequel_pg_test.rb +330 -0
  127. data/test/instrumentation/typhoeus_test.rb +285 -0
  128. data/test/minitest_helper.rb +187 -0
  129. data/test/profiling/method_test.rb +198 -0
  130. data/test/servers/rackapp_8101.rb +22 -0
  131. data/test/support/backcompat_test.rb +269 -0
  132. data/test/support/config_test.rb +128 -0
  133. data/test/support/dnt_test.rb +73 -0
  134. data/test/support/liboboe_settings_test.rb +104 -0
  135. data/test/support/xtrace_test.rb +35 -0
  136. data/traceview.gemspec +29 -0
  137. metadata +248 -0
@@ -0,0 +1,326 @@
1
+ require 'minitest_helper'
2
+
3
+ unless defined?(JRUBY_VERSION)
4
+
5
+ if ENV.key?('TRAVIS_MYSQL_PASS')
6
+ MYSQL2_DB = Sequel.connect("mysql2://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test")
7
+ else
8
+ MYSQL2_DB = Sequel.connect('mysql2://root@127.0.0.1:3306/travis_ci_test')
9
+ end
10
+
11
+ unless MYSQL2_DB.table_exists?(:items)
12
+ MYSQL2_DB.create_table :items do
13
+ primary_key :id
14
+ String :name
15
+ Float :price
16
+ end
17
+ end
18
+
19
+ describe "Sequel (mysql2)" do
20
+ before do
21
+ clear_all_traces
22
+
23
+ # These are standard entry/exit KVs that are passed up with all sequel operations
24
+ @entry_kvs = {
25
+ 'Layer' => 'sequel',
26
+ 'Label' => 'entry',
27
+ 'Database' => 'travis_ci_test',
28
+ 'RemoteHost' => '127.0.0.1',
29
+ 'RemotePort' => 3306 }
30
+
31
+ @exit_kvs = { 'Layer' => 'sequel', 'Label' => 'exit' }
32
+ @collect_backtraces = TraceView::Config[:sequel][:collect_backtraces]
33
+ @sanitize_sql = TraceView::Config[:sanitize_sql]
34
+ end
35
+
36
+ after do
37
+ TraceView::Config[:sequel][:collect_backtraces] = @collect_backtraces
38
+ TraceView::Config[:sanitize_sql] = @sanitize_sql
39
+ end
40
+
41
+ it 'Stock sequel should be loaded, defined and ready' do
42
+ defined?(::Sequel).wont_match nil
43
+ end
44
+
45
+ it 'sequel should have traceview methods defined' do
46
+ # Sequel::Database
47
+ ::Sequel::Database.method_defined?(:run_with_traceview).must_equal true
48
+
49
+ # Sequel::Dataset
50
+ ::Sequel::Dataset.method_defined?(:execute_with_traceview).must_equal true
51
+ ::Sequel::Dataset.method_defined?(:execute_ddl_with_traceview).must_equal true
52
+ ::Sequel::Dataset.method_defined?(:execute_dui_with_traceview).must_equal true
53
+ ::Sequel::Dataset.method_defined?(:execute_insert_with_traceview).must_equal true
54
+ end
55
+
56
+ it "should obey :collect_backtraces setting when true" do
57
+ TraceView::Config[:sequel][:collect_backtraces] = true
58
+
59
+ TraceView::API.start_trace('sequel_test', '', {}) do
60
+ MYSQL2_DB.run('select 1')
61
+ end
62
+
63
+ traces = get_all_traces
64
+ layer_has_key(traces, 'sequel', 'Backtrace')
65
+ end
66
+
67
+ it "should obey :collect_backtraces setting when false" do
68
+ TraceView::Config[:sequel][:collect_backtraces] = false
69
+
70
+ TraceView::API.start_trace('sequel_test', '', {}) do
71
+ MYSQL2_DB.run('select 1')
72
+ end
73
+
74
+ traces = get_all_traces
75
+ layer_doesnt_have_key(traces, 'sequel', 'Backtrace')
76
+ end
77
+
78
+ it 'should trace MYSQL2_DB.run insert' do
79
+ TraceView::API.start_trace('sequel_test', '', {}) do
80
+ MYSQL2_DB.run("insert into items (name, price) values ('blah', '12')")
81
+ end
82
+
83
+ traces = get_all_traces
84
+
85
+ traces.count.must_equal 4
86
+ validate_outer_layers(traces, 'sequel_test')
87
+
88
+ validate_event_keys(traces[1], @entry_kvs)
89
+ traces[1]['Query'].must_equal "insert into items (name, price) values ('blah', '12')"
90
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
91
+ validate_event_keys(traces[2], @exit_kvs)
92
+ end
93
+
94
+ it 'should trace MYSQL2_DB.run select' do
95
+ TraceView::API.start_trace('sequel_test', '', {}) do
96
+ MYSQL2_DB.run("select 1")
97
+ end
98
+
99
+ traces = get_all_traces
100
+
101
+ traces.count.must_equal 4
102
+ validate_outer_layers(traces, 'sequel_test')
103
+
104
+ validate_event_keys(traces[1], @entry_kvs)
105
+ traces[1]['Query'].must_equal "select 1"
106
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
107
+ validate_event_keys(traces[2], @exit_kvs)
108
+ end
109
+
110
+ it 'should trace a dataset insert and count' do
111
+ items = MYSQL2_DB[:items]
112
+ items.count
113
+
114
+ TraceView::API.start_trace('sequel_test', '', {}) do
115
+ items.insert(:name => 'abc', :price => 2.514)
116
+ items.count
117
+ end
118
+
119
+ traces = get_all_traces
120
+
121
+ traces.count.must_equal 6
122
+ validate_outer_layers(traces, 'sequel_test')
123
+
124
+ validate_event_keys(traces[1], @entry_kvs)
125
+
126
+ # SQL column/value order can vary between Ruby and gem versions
127
+ # Use must_include to test against one or the other
128
+ [
129
+ "INSERT INTO `items` (`price`, `name`) VALUES (2.514, 'abc')",
130
+ "INSERT INTO `items` (`name`, `price`) VALUES ('abc', 2.514)"
131
+ ].must_include traces[1]['Query']
132
+
133
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
134
+ traces[2]['Layer'].must_equal "sequel"
135
+ traces[2]['Label'].must_equal "exit"
136
+ traces[3]['Query'].downcase.must_equal "select count(*) as `count` from `items` limit 1"
137
+ validate_event_keys(traces[4], @exit_kvs)
138
+ end
139
+
140
+ it 'should trace a dataset insert and obey query privacy' do
141
+ TraceView::Config[:sanitize_sql] = true
142
+ items = MYSQL2_DB[:items]
143
+ items.count
144
+
145
+ TraceView::API.start_trace('sequel_test', '', {}) do
146
+ items.insert(:name => 'abc', :price => 2.514461383352462)
147
+ end
148
+
149
+ traces = get_all_traces
150
+
151
+ traces.count.must_equal 4
152
+ validate_outer_layers(traces, 'sequel_test')
153
+
154
+ validate_event_keys(traces[1], @entry_kvs)
155
+
156
+ # SQL column/value order can vary between Ruby and gem versions
157
+ # Use must_include to test against one or the other
158
+ [
159
+ "INSERT INTO `items` (`price`, `name`) VALUES (?, ?)",
160
+ "INSERT INTO `items` (`name`, `price`) VALUES (?, ?)"
161
+ ].must_include traces[1]['Query']
162
+
163
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
164
+ validate_event_keys(traces[2], @exit_kvs)
165
+ end
166
+
167
+ it 'should trace a dataset filter' do
168
+ items = MYSQL2_DB[:items]
169
+ items.count
170
+
171
+ TraceView::API.start_trace('sequel_test', '', {}) do
172
+ items.filter(:name => 'abc').all
173
+ end
174
+
175
+ traces = get_all_traces
176
+
177
+ traces.count.must_equal 4
178
+ validate_outer_layers(traces, 'sequel_test')
179
+
180
+ validate_event_keys(traces[1], @entry_kvs)
181
+ traces[1]['Query'].must_equal "SELECT * FROM `items` WHERE (`name` = 'abc')"
182
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
183
+ validate_event_keys(traces[2], @exit_kvs)
184
+ end
185
+
186
+ it 'should trace create table' do
187
+ # Drop the table if it already exists
188
+ MYSQL2_DB.drop_table(:fake) if MYSQL2_DB.table_exists?(:fake)
189
+
190
+ TraceView::API.start_trace('sequel_test', '', {}) do
191
+ MYSQL2_DB.create_table :fake do
192
+ primary_key :id
193
+ String :name
194
+ Float :price
195
+ end
196
+ end
197
+
198
+ traces = get_all_traces
199
+
200
+ traces.count.must_equal 4
201
+ validate_outer_layers(traces, 'sequel_test')
202
+
203
+ validate_event_keys(traces[1], @entry_kvs)
204
+ traces[1]['Query'].must_equal "CREATE TABLE `fake` (`id` integer PRIMARY KEY AUTO_INCREMENT, `name` varchar(255), `price` double precision)"
205
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
206
+ validate_event_keys(traces[2], @exit_kvs)
207
+ end
208
+
209
+ it 'should trace add index' do
210
+ # Drop the table if it already exists
211
+ MYSQL2_DB.drop_table(:fake) if MYSQL2_DB.table_exists?(:fake)
212
+
213
+ TraceView::API.start_trace('sequel_test', '', {}) do
214
+ MYSQL2_DB.create_table :fake do
215
+ primary_key :id
216
+ String :name
217
+ Float :price
218
+ end
219
+ end
220
+
221
+ traces = get_all_traces
222
+
223
+ traces.count.must_equal 4
224
+ validate_outer_layers(traces, 'sequel_test')
225
+
226
+ validate_event_keys(traces[1], @entry_kvs)
227
+ traces[1]['Query'].must_equal "CREATE TABLE `fake` (`id` integer PRIMARY KEY AUTO_INCREMENT, `name` varchar(255), `price` double precision)"
228
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
229
+ validate_event_keys(traces[2], @exit_kvs)
230
+ end
231
+
232
+ it 'should capture and report exceptions' do
233
+ begin
234
+ TraceView::API.start_trace('sequel_test', '', {}) do
235
+ MYSQL2_DB.run("this is bad sql")
236
+ end
237
+ rescue
238
+ # Do nothing - we're testing exception logging
239
+ end
240
+
241
+ traces = get_all_traces
242
+
243
+ traces.count.must_equal 5
244
+ validate_outer_layers(traces, 'sequel_test')
245
+
246
+ validate_event_keys(traces[1], @entry_kvs)
247
+ traces[1]['Query'].must_equal "this is bad sql"
248
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
249
+ traces[2]['Layer'].must_equal "sequel"
250
+ traces[2]['Label'].must_equal "error"
251
+ traces[2].has_key?('Backtrace').must_equal true
252
+ traces[2]['ErrorClass'].must_equal "Sequel::DatabaseError"
253
+ validate_event_keys(traces[3], @exit_kvs)
254
+ end
255
+
256
+ it 'should trace placeholder queries with bound vars' do
257
+ items = MYSQL2_DB[:items]
258
+ items.count
259
+
260
+ TraceView::API.start_trace('sequel_test', '', {}) do
261
+ ds = items.where(:name=>:$n)
262
+ ds.call(:select, :n=>'abc')
263
+ ds.call(:delete, :n=>'cba')
264
+ end
265
+
266
+ traces = get_all_traces
267
+
268
+ traces.count.must_equal 6
269
+ validate_outer_layers(traces, 'sequel_test')
270
+
271
+ validate_event_keys(traces[1], @entry_kvs)
272
+ traces[1]['Query'].must_equal "SELECT * FROM `items` WHERE (`name` = 'abc')"
273
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
274
+ traces[3]['Query'].must_equal "DELETE FROM `items` WHERE (`name` = 'cba')"
275
+ traces[3].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
276
+ validate_event_keys(traces[2], @exit_kvs)
277
+ end
278
+
279
+ it 'should trace prepared statements' do
280
+ ds = MYSQL2_DB[:items].filter(:name=>:$n)
281
+ ps = ds.prepare(:select, :select_by_name)
282
+
283
+ TraceView::API.start_trace('sequel_test', '', {}) do
284
+ ps.call(:n=>'abc')
285
+ end
286
+
287
+ traces = get_all_traces
288
+
289
+ traces.count.must_equal 4
290
+ validate_outer_layers(traces, 'sequel_test')
291
+
292
+ validate_event_keys(traces[1], @entry_kvs)
293
+ traces[1]['Query'].must_equal "select_by_name"
294
+ if RUBY_VERSION < "1.9"
295
+ traces[1]['QueryArgs'].must_equal "abc"
296
+ else
297
+ traces[1]['QueryArgs'].must_equal "[\"abc\"]"
298
+ end
299
+ traces[1]['IsPreparedStatement'].must_equal "true"
300
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
301
+ validate_event_keys(traces[2], @exit_kvs)
302
+ end
303
+
304
+ it 'should trace prep\'d stmnts and obey query privacy' do
305
+ TraceView::Config[:sanitize_sql] = true
306
+ ds = MYSQL2_DB[:items].filter(:name=>:$n)
307
+ ps = ds.prepare(:select, :select_by_name)
308
+
309
+ TraceView::API.start_trace('sequel_test', '', {}) do
310
+ ps.call(:n=>'abc')
311
+ end
312
+
313
+ traces = get_all_traces
314
+
315
+ traces.count.must_equal 4
316
+ validate_outer_layers(traces, 'sequel_test')
317
+
318
+ validate_event_keys(traces[1], @entry_kvs)
319
+ traces[1]['Query'].must_equal "select_by_name"
320
+ traces[1]['QueryArgs'].must_equal nil
321
+ traces[1]['IsPreparedStatement'].must_equal "true"
322
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
323
+ validate_event_keys(traces[2], @exit_kvs)
324
+ end
325
+ end
326
+ end
@@ -0,0 +1,326 @@
1
+ require 'minitest_helper'
2
+
3
+ unless defined?(JRUBY_VERSION)
4
+
5
+ if ENV.key?('TRAVIS_MYSQL_PASS')
6
+ MYSQL_DB = Sequel.connect("mysql://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test")
7
+ else
8
+ MYSQL_DB = Sequel.connect('mysql://root@127.0.0.1:3306/travis_ci_test')
9
+ end
10
+
11
+ unless MYSQL_DB.table_exists?(:items)
12
+ MYSQL_DB.create_table :items do
13
+ primary_key :id
14
+ String :name
15
+ Float :price
16
+ end
17
+ end
18
+
19
+ describe "Sequel (mysql)" do
20
+ before do
21
+ clear_all_traces
22
+
23
+ # These are standard entry/exit KVs that are passed up with all sequel operations
24
+ @entry_kvs = {
25
+ 'Layer' => 'sequel',
26
+ 'Label' => 'entry',
27
+ 'Database' => 'travis_ci_test',
28
+ 'RemoteHost' => '127.0.0.1',
29
+ 'RemotePort' => 3306 }
30
+
31
+ @exit_kvs = { 'Layer' => 'sequel', 'Label' => 'exit' }
32
+ @collect_backtraces = TraceView::Config[:sequel][:collect_backtraces]
33
+ @sanitize_sql = TraceView::Config[:sanitize_sql]
34
+ end
35
+
36
+ after do
37
+ TraceView::Config[:sequel][:collect_backtraces] = @collect_backtraces
38
+ TraceView::Config[:sanitize_sql] = @sanitize_sql
39
+ end
40
+
41
+ it 'Stock sequel should be loaded, defined and ready' do
42
+ defined?(::Sequel).wont_match nil
43
+ end
44
+
45
+ it 'sequel should have traceview methods defined' do
46
+ # Sequel::Database
47
+ ::Sequel::Database.method_defined?(:run_with_traceview).must_equal true
48
+
49
+ # Sequel::Dataset
50
+ ::Sequel::Dataset.method_defined?(:execute_with_traceview).must_equal true
51
+ ::Sequel::Dataset.method_defined?(:execute_ddl_with_traceview).must_equal true
52
+ ::Sequel::Dataset.method_defined?(:execute_dui_with_traceview).must_equal true
53
+ ::Sequel::Dataset.method_defined?(:execute_insert_with_traceview).must_equal true
54
+ end
55
+
56
+ it "should obey :collect_backtraces setting when true" do
57
+ TraceView::Config[:sequel][:collect_backtraces] = true
58
+
59
+ TraceView::API.start_trace('sequel_test', '', {}) do
60
+ MYSQL_DB.run('select 1')
61
+ end
62
+
63
+ traces = get_all_traces
64
+ layer_has_key(traces, 'sequel', 'Backtrace')
65
+ end
66
+
67
+ it "should obey :collect_backtraces setting when false" do
68
+ TraceView::Config[:sequel][:collect_backtraces] = false
69
+
70
+ TraceView::API.start_trace('sequel_test', '', {}) do
71
+ MYSQL_DB.run('select 1')
72
+ end
73
+
74
+ traces = get_all_traces
75
+ layer_doesnt_have_key(traces, 'sequel', 'Backtrace')
76
+ end
77
+
78
+ it 'should trace MYSQL_DB.run insert' do
79
+ TraceView::API.start_trace('sequel_test', '', {}) do
80
+ MYSQL_DB.run("insert into items (name, price) values ('blah', '12')")
81
+ end
82
+
83
+ traces = get_all_traces
84
+
85
+ traces.count.must_equal 4
86
+ validate_outer_layers(traces, 'sequel_test')
87
+
88
+ validate_event_keys(traces[1], @entry_kvs)
89
+ traces[1]['Query'].must_equal "insert into items (name, price) values ('blah', '12')"
90
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
91
+ validate_event_keys(traces[2], @exit_kvs)
92
+ end
93
+
94
+ it 'should trace MYSQL_DB.run select' do
95
+ TraceView::API.start_trace('sequel_test', '', {}) do
96
+ MYSQL_DB.run("select 1")
97
+ end
98
+
99
+ traces = get_all_traces
100
+
101
+ traces.count.must_equal 4
102
+ validate_outer_layers(traces, 'sequel_test')
103
+
104
+ validate_event_keys(traces[1], @entry_kvs)
105
+ traces[1]['Query'].must_equal "select 1"
106
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
107
+ validate_event_keys(traces[2], @exit_kvs)
108
+ end
109
+
110
+ it 'should trace a dataset insert and count' do
111
+ items = MYSQL_DB[:items]
112
+ items.count
113
+
114
+ TraceView::API.start_trace('sequel_test', '', {}) do
115
+ items.insert(:name => 'abc', :price => 2.514)
116
+ items.count
117
+ end
118
+
119
+ traces = get_all_traces
120
+
121
+ traces.count.must_equal 6
122
+ validate_outer_layers(traces, 'sequel_test')
123
+
124
+ validate_event_keys(traces[1], @entry_kvs)
125
+
126
+ # SQL column/value order can vary between Ruby and gem versions
127
+ # Use must_include to test against one or the other
128
+ [
129
+ "INSERT INTO `items` (`price`, `name`) VALUES (2.514, 'abc')",
130
+ "INSERT INTO `items` (`name`, `price`) VALUES ('abc', 2.514)"
131
+ ].must_include traces[1]['Query']
132
+
133
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
134
+ traces[2]['Layer'].must_equal "sequel"
135
+ traces[2]['Label'].must_equal "exit"
136
+ traces[3]['Query'].downcase.must_equal "select count(*) as `count` from `items` limit 1"
137
+ validate_event_keys(traces[4], @exit_kvs)
138
+ end
139
+
140
+ it 'should trace a dataset insert and obey query privacy' do
141
+ TraceView::Config[:sanitize_sql] = true
142
+ items = MYSQL_DB[:items]
143
+ items.count
144
+
145
+ TraceView::API.start_trace('sequel_test', '', {}) do
146
+ items.insert(:name => 'abc', :price => 2.514461383352462)
147
+ end
148
+
149
+ traces = get_all_traces
150
+
151
+ traces.count.must_equal 4
152
+ validate_outer_layers(traces, 'sequel_test')
153
+
154
+ validate_event_keys(traces[1], @entry_kvs)
155
+
156
+ # SQL column/value order can vary between Ruby and gem versions
157
+ # Use must_include to test against one or the other
158
+ [
159
+ "INSERT INTO `items` (`price`, `name`) VALUES (?, ?)",
160
+ "INSERT INTO `items` (`name`, `price`) VALUES (?, ?)"
161
+ ].must_include traces[1]['Query']
162
+
163
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
164
+ validate_event_keys(traces[2], @exit_kvs)
165
+ end
166
+
167
+ it 'should trace a dataset filter' do
168
+ items = MYSQL_DB[:items]
169
+ items.count
170
+
171
+ TraceView::API.start_trace('sequel_test', '', {}) do
172
+ items.filter(:name => 'abc').all
173
+ end
174
+
175
+ traces = get_all_traces
176
+
177
+ traces.count.must_equal 4
178
+ validate_outer_layers(traces, 'sequel_test')
179
+
180
+ validate_event_keys(traces[1], @entry_kvs)
181
+ traces[1]['Query'].must_equal "SELECT * FROM `items` WHERE (`name` = 'abc')"
182
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
183
+ validate_event_keys(traces[2], @exit_kvs)
184
+ end
185
+
186
+ it 'should trace create table' do
187
+ # Drop the table if it already exists
188
+ MYSQL_DB.drop_table(:fake) if MYSQL_DB.table_exists?(:fake)
189
+
190
+ TraceView::API.start_trace('sequel_test', '', {}) do
191
+ MYSQL_DB.create_table :fake do
192
+ primary_key :id
193
+ String :name
194
+ Float :price
195
+ end
196
+ end
197
+
198
+ traces = get_all_traces
199
+
200
+ traces.count.must_equal 4
201
+ validate_outer_layers(traces, 'sequel_test')
202
+
203
+ validate_event_keys(traces[1], @entry_kvs)
204
+ traces[1]['Query'].must_equal "CREATE TABLE `fake` (`id` integer PRIMARY KEY AUTO_INCREMENT, `name` varchar(255), `price` double precision)"
205
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
206
+ validate_event_keys(traces[2], @exit_kvs)
207
+ end
208
+
209
+ it 'should trace add index' do
210
+ # Drop the table if it already exists
211
+ MYSQL_DB.drop_table(:fake) if MYSQL_DB.table_exists?(:fake)
212
+
213
+ TraceView::API.start_trace('sequel_test', '', {}) do
214
+ MYSQL_DB.create_table :fake do
215
+ primary_key :id
216
+ String :name
217
+ Float :price
218
+ end
219
+ end
220
+
221
+ traces = get_all_traces
222
+
223
+ traces.count.must_equal 4
224
+ validate_outer_layers(traces, 'sequel_test')
225
+
226
+ validate_event_keys(traces[1], @entry_kvs)
227
+ traces[1]['Query'].must_equal "CREATE TABLE `fake` (`id` integer PRIMARY KEY AUTO_INCREMENT, `name` varchar(255), `price` double precision)"
228
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
229
+ validate_event_keys(traces[2], @exit_kvs)
230
+ end
231
+
232
+ it 'should capture and report exceptions' do
233
+ begin
234
+ TraceView::API.start_trace('sequel_test', '', {}) do
235
+ MYSQL_DB.run("this is bad sql")
236
+ end
237
+ rescue
238
+ # Do nothing - we're testing exception logging
239
+ end
240
+
241
+ traces = get_all_traces
242
+
243
+ traces.count.must_equal 5
244
+ validate_outer_layers(traces, 'sequel_test')
245
+
246
+ validate_event_keys(traces[1], @entry_kvs)
247
+ traces[1]['Query'].must_equal "this is bad sql"
248
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
249
+ traces[2]['Layer'].must_equal "sequel"
250
+ traces[2]['Label'].must_equal "error"
251
+ traces[2].has_key?('Backtrace').must_equal true
252
+ traces[2]['ErrorClass'].must_equal "Sequel::DatabaseError"
253
+ validate_event_keys(traces[3], @exit_kvs)
254
+ end
255
+
256
+ it 'should trace placeholder queries with bound vars' do
257
+ items = MYSQL_DB[:items]
258
+ items.count
259
+
260
+ TraceView::API.start_trace('sequel_test', '', {}) do
261
+ ds = items.where(:name=>:$n)
262
+ ds.call(:select, :n=>'abc')
263
+ ds.call(:delete, :n=>'cba')
264
+ end
265
+
266
+ traces = get_all_traces
267
+
268
+ traces.count.must_equal 6
269
+ validate_outer_layers(traces, 'sequel_test')
270
+
271
+ validate_event_keys(traces[1], @entry_kvs)
272
+ traces[1]['Query'].must_equal "SELECT * FROM `items` WHERE (`name` = 'abc')"
273
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
274
+ traces[3]['Query'].must_equal "DELETE FROM `items` WHERE (`name` = 'cba')"
275
+ traces[3].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
276
+ validate_event_keys(traces[2], @exit_kvs)
277
+ end
278
+
279
+ it 'should trace prepared statements' do
280
+ ds = MYSQL_DB[:items].filter(:name=>:$n)
281
+ ps = ds.prepare(:select, :select_by_name)
282
+
283
+ TraceView::API.start_trace('sequel_test', '', {}) do
284
+ ps.call(:n=>'abc')
285
+ end
286
+
287
+ traces = get_all_traces
288
+
289
+ traces.count.must_equal 4
290
+ validate_outer_layers(traces, 'sequel_test')
291
+
292
+ validate_event_keys(traces[1], @entry_kvs)
293
+ traces[1]['Query'].must_equal "select_by_name"
294
+ if RUBY_VERSION < "1.9"
295
+ traces[1]['QueryArgs'].must_equal "abc"
296
+ else
297
+ traces[1]['QueryArgs'].must_equal "[\"abc\"]"
298
+ end
299
+ traces[1]['IsPreparedStatement'].must_equal "true"
300
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
301
+ validate_event_keys(traces[2], @exit_kvs)
302
+ end
303
+
304
+ it 'should trace prep\'d stmnts and obey query privacy' do
305
+ TraceView::Config[:sanitize_sql] = true
306
+ ds = MYSQL_DB[:items].filter(:name=>:$n)
307
+ ps = ds.prepare(:select, :select_by_name)
308
+
309
+ TraceView::API.start_trace('sequel_test', '', {}) do
310
+ ps.call(:n=>'abc')
311
+ end
312
+
313
+ traces = get_all_traces
314
+
315
+ traces.count.must_equal 4
316
+ validate_outer_layers(traces, 'sequel_test')
317
+
318
+ validate_event_keys(traces[1], @entry_kvs)
319
+ traces[1]['Query'].must_equal "select_by_name"
320
+ traces[1]['QueryArgs'].must_equal nil
321
+ traces[1]['IsPreparedStatement'].must_equal "true"
322
+ traces[1].has_key?('Backtrace').must_equal TraceView::Config[:sequel][:collect_backtraces]
323
+ validate_event_keys(traces[2], @exit_kvs)
324
+ end
325
+ end
326
+ end