traceview 3.6.0 → 3.7.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +12 -1
  3. data/CHANGELOG.md +11 -0
  4. data/CONFIG.md +22 -5
  5. data/Rakefile +2 -2
  6. data/gemfiles/delayed_job.gemfile +1 -1
  7. data/gemfiles/frameworks.gemfile +1 -1
  8. data/gemfiles/libraries.gemfile +4 -3
  9. data/gemfiles/rails31.gemfile +2 -0
  10. data/gemfiles/rails32.gemfile +5 -2
  11. data/gemfiles/rails40.gemfile +5 -3
  12. data/gemfiles/rails41.gemfile +6 -4
  13. data/gemfiles/rails42.gemfile +3 -1
  14. data/gemfiles/rails50.gemfile +43 -0
  15. data/lib/rails/generators/traceview/templates/traceview_initializer.rb +56 -32
  16. data/lib/traceview/base.rb +1 -1
  17. data/lib/traceview/frameworks/rails.rb +6 -9
  18. data/lib/traceview/frameworks/rails/inst/action_controller.rb +2 -135
  19. data/lib/traceview/frameworks/rails/inst/action_controller2.rb +59 -0
  20. data/lib/traceview/frameworks/rails/inst/action_controller3.rb +49 -0
  21. data/lib/traceview/frameworks/rails/inst/action_controller4.rb +40 -0
  22. data/lib/traceview/frameworks/rails/inst/action_controller5.rb +39 -0
  23. data/lib/traceview/frameworks/rails/inst/action_view.rb +1 -1
  24. data/lib/traceview/frameworks/rails/inst/active_record.rb +6 -3
  25. data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +1 -1
  26. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +30 -36
  27. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils5x.rb +100 -0
  28. data/lib/traceview/test.rb +39 -0
  29. data/lib/traceview/version.rb +1 -1
  30. data/test/frameworks/rails3x_test.rb +163 -7
  31. data/test/frameworks/rails4x_test.rb +162 -13
  32. data/test/frameworks/rails5x_test.rb +213 -0
  33. data/test/instrumentation/excon_test.rb +3 -0
  34. data/test/instrumentation/sequel_mysql2_test.rb +2 -5
  35. data/test/instrumentation/sequel_mysql_test.rb +2 -5
  36. data/test/instrumentation/sequel_pg_test.rb +2 -5
  37. data/test/minitest_helper.rb +25 -21
  38. data/test/servers/delayed_job.rb +2 -6
  39. data/test/servers/rails3x_8140.rb +16 -6
  40. data/test/servers/rails4x_8140.rb +20 -9
  41. data/test/servers/rails5x_8140.rb +112 -0
  42. metadata +13 -4
  43. data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +0 -18
@@ -0,0 +1,100 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module Utils
8
+
9
+ def extract_trace_details(sql, name = nil, binds = [])
10
+ opts = {}
11
+
12
+ begin
13
+ if TraceView::Config[:sanitize_sql]
14
+ # Sanitize SQL and don't report binds
15
+ opts[:Query] = TraceView::Util.sanitize_sql(sql)
16
+ else
17
+ # Report raw SQL and any binds if they exist
18
+ opts[:Query] = sql.to_s
19
+ if binds && !binds.empty?
20
+ opts[:QueryArgs] = binds.map { |i| i.value }
21
+ end
22
+ end
23
+
24
+ opts[:Name] = name.to_s if name
25
+ opts[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:active_record][:collect_backtraces]
26
+
27
+ if ::Rails::VERSION::MAJOR == 2
28
+ config = ::Rails.configuration.database_configuration[::Rails.env]
29
+ else
30
+ config = ActiveRecord::Base.connection.instance_variable_get(:@config)
31
+ end
32
+
33
+ if config
34
+ opts[:Database] = config['database'] if config.key?('database')
35
+ opts[:RemoteHost] = config['host'] if config.key?('host')
36
+ adapter_name = config[:adapter]
37
+
38
+ case adapter_name
39
+ when /mysql/i
40
+ opts[:Flavor] = 'mysql'
41
+ when /postgres/i
42
+ opts[:Flavor] = 'postgresql'
43
+ end
44
+ end
45
+ rescue StandardError => e
46
+ TraceView.logger.debug "Exception raised capturing ActiveRecord KVs: #{e.inspect}"
47
+ TraceView.logger.debug e.backtrace.join('\n')
48
+ end
49
+
50
+ return opts || {}
51
+ end
52
+
53
+ # We don't want to trace framework caches. Only instrument SQL that
54
+ # directly hits the database.
55
+ def ignore_payload?(name)
56
+ %w(SCHEMA EXPLAIN CACHE).include?(name.to_s) ||
57
+ (name && name.to_sym == :skip_logging) ||
58
+ name == 'ActiveRecord::SchemaMigration Load'
59
+ end
60
+
61
+ def exec_query_with_traceview(sql, name = nil, binds = [], prepare: false)
62
+
63
+ if TraceView.tracing? && !ignore_payload?(name)
64
+
65
+ opts = extract_trace_details(sql, name, binds)
66
+ TraceView::API.trace('activerecord', opts || {}) do
67
+ exec_query_without_traceview(sql, name, binds)
68
+ end
69
+ else
70
+ exec_query_without_traceview(sql, name, binds)
71
+ end
72
+ end
73
+
74
+ def exec_insert_with_traceview(sql, name = nil, binds = [], *args)
75
+ if TraceView.tracing? && !ignore_payload?(name)
76
+
77
+ opts = extract_trace_details(sql, name, binds)
78
+ TraceView::API.trace('activerecord', opts || {}) do
79
+ exec_insert_without_traceview(sql, name, binds, *args)
80
+ end
81
+ else
82
+ exec_insert_without_traceview(sql, name, binds, *args)
83
+ end
84
+ end
85
+
86
+ def exec_delete_with_traceview(sql, name = nil, binds = [])
87
+ if TraceView.tracing? && !ignore_payload?(name)
88
+
89
+ opts = extract_trace_details(sql, name, binds)
90
+ TraceView::API.trace('activerecord', opts || {}) do
91
+ exec_delete_without_traceview(sql, name, binds)
92
+ end
93
+ else
94
+ exec_delete_without_traceview(sql, name, binds)
95
+ end
96
+ end
97
+ end # Utils
98
+ end
99
+ end
100
+ end
@@ -44,6 +44,45 @@ module TraceView
44
44
  def gemfile
45
45
  File.basename(ENV['BUNDLE_GEMFILE']).split('.').first
46
46
  end
47
+
48
+ ##
49
+ # set_postgresql_env
50
+ #
51
+ # Used to set the postgresql specific DATABASE_URL env based
52
+ # on various conditions
53
+ def set_postgresql_env
54
+ if ENV.key?('TRAVIS_PSQL_PASS')
55
+ ENV['DATABASE_URL'] = "postgresql://postgres:#{ENV['TRAVIS_PSQL_PASS']}@127.0.0.1:5432/travis_ci_test"
56
+ else
57
+ ENV['DATABASE_URL'] = 'postgresql://postgres@127.0.0.1:5432/travis_ci_test'
58
+ end
59
+ end
60
+
61
+ ##
62
+ # set_mysql_env
63
+ #
64
+ # Used to set the mysql specific DATABASE_URL env based
65
+ # on various conditions
66
+ def set_mysql_env
67
+ if ENV.key?('TRAVIS_MYSQL_PASS')
68
+ ENV['DATABASE_URL'] = "mysql://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test"
69
+ else
70
+ ENV['DATABASE_URL'] = 'mysql://root@127.0.0.1:3306/travis_ci_test'
71
+ end
72
+ end
73
+
74
+ ##
75
+ # set_mysql2_env
76
+ #
77
+ # Used to set the mysql specific DATABASE_URL env based
78
+ # on various conditions
79
+ def set_mysql2_env
80
+ if ENV.key?('TRAVIS_MYSQL_PASS')
81
+ ENV['DATABASE_URL'] = "mysql2://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test"
82
+ else
83
+ ENV['DATABASE_URL'] = 'mysql2://root@127.0.0.1:3306/travis_ci_test'
84
+ end
85
+ end
47
86
  end
48
87
  end
49
88
  end
@@ -7,7 +7,7 @@ module TraceView
7
7
  # traceview.gemspec during gem build process
8
8
  module Version
9
9
  MAJOR = 3
10
- MINOR = 6
10
+ MINOR = 7
11
11
  PATCH = 0
12
12
  BUILD = nil
13
13
 
@@ -98,25 +98,30 @@ if defined?(::Rails)
98
98
  r.header['X-Trace'].must_equal traces[4]['X-Trace']
99
99
  end
100
100
 
101
- it "should trace rails db calls" do
101
+ it "should trace rails postgresql db calls" do
102
102
  # Skip for JRuby since the java instrumentation
103
103
  # handles DB instrumentation for JRuby
104
- skip if defined?(JRUBY_VERSION)
104
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "postgresql"
105
105
 
106
106
  uri = URI.parse('http://127.0.0.1:8140/hello/db')
107
107
  r = Net::HTTP.get_response(uri)
108
108
 
109
109
  traces = get_all_traces
110
110
 
111
- traces.count.must_equal 12
111
+ traces.count.must_equal 14
112
112
  valid_edges?(traces).must_equal true
113
113
  validate_outer_layers(traces, 'rack')
114
114
 
115
115
  traces[4]['Layer'].must_equal "activerecord"
116
116
  traces[4]['Label'].must_equal "entry"
117
117
  traces[4]['Flavor'].must_equal "postgresql"
118
- traces[4]['Query'].must_equal "SELECT \"widgets\".* FROM \"widgets\" "
119
- traces[4]['Name'].must_equal "Widget Load"
118
+
119
+ # Some versions of rails adds in another space before the ORDER keyword.
120
+ # Make 2 or more consecutive spaces just 1
121
+ sql = traces[4]['Query'].gsub(/\s{2,}/, ' ')
122
+ sql.must_equal "INSERT INTO \"widgets\" (\"created_at\", \"description\", \"name\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"id\""
123
+
124
+ traces[4]['Name'].must_equal "SQL"
120
125
  traces[4].key?('Backtrace').must_equal true
121
126
 
122
127
  traces[5]['Layer'].must_equal "activerecord"
@@ -125,7 +130,60 @@ if defined?(::Rails)
125
130
  traces[6]['Layer'].must_equal "activerecord"
126
131
  traces[6]['Label'].must_equal "entry"
127
132
  traces[6]['Flavor'].must_equal "postgresql"
128
- traces[6]['Query'].must_equal "INSERT INTO \"widgets\" (\"created_at\", \"description\", \"name\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"id\""
133
+ traces[6]['Query'].must_equal "SELECT \"widgets\".* FROM \"widgets\" WHERE \"widgets\".\"name\" = 'blah' LIMIT 1"
134
+ traces[6]['Name'].must_equal "Widget Load"
135
+ traces[6].key?('Backtrace').must_equal true
136
+ traces[6].key?('QueryArgs').must_equal false
137
+
138
+ traces[7]['Layer'].must_equal "activerecord"
139
+ traces[7]['Label'].must_equal "exit"
140
+
141
+ traces[8]['Layer'].must_equal "activerecord"
142
+ traces[8]['Label'].must_equal "entry"
143
+ traces[8]['Flavor'].must_equal "postgresql"
144
+
145
+ # Remove the widget id so we can test everything else
146
+ sql = traces[8]['Query'].gsub(/\d+/, 'xxx')
147
+ sql.must_equal "DELETE FROM \"widgets\" WHERE \"widgets\".\"id\" = xxx"
148
+
149
+ traces[8]['Name'].must_equal "SQL"
150
+ traces[8].key?('Backtrace').must_equal true
151
+ traces[8].key?('QueryArgs').must_equal false
152
+
153
+ traces[9]['Layer'].must_equal "activerecord"
154
+ traces[9]['Label'].must_equal "exit"
155
+
156
+ # Validate the existence of the response header
157
+ r['X-Trace'].must_equal traces[13]['X-Trace']
158
+ end
159
+
160
+ it "should trace rails mysql db calls" do
161
+ # Skip for JRuby since the java instrumentation
162
+ # handles DB instrumentation for JRuby
163
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "mysql"
164
+
165
+ uri = URI.parse('http://127.0.0.1:8140/hello/db')
166
+ r = Net::HTTP.get_response(uri)
167
+
168
+ traces = get_all_traces
169
+
170
+ traces.count.must_equal 18
171
+ valid_edges?(traces).must_equal true
172
+ validate_outer_layers(traces, 'rack')
173
+
174
+ traces[4]['Layer'].must_equal "activerecord"
175
+ traces[4]['Label'].must_equal "entry"
176
+ traces[4]['Flavor'].must_equal "mysql"
177
+ traces[4]['Query'].must_equal "BEGIN"
178
+ traces[4].key?('Backtrace').must_equal true
179
+
180
+ traces[5]['Layer'].must_equal "activerecord"
181
+ traces[5]['Label'].must_equal "exit"
182
+
183
+ traces[6]['Layer'].must_equal "activerecord"
184
+ traces[6]['Label'].must_equal "entry"
185
+ traces[6]['Flavor'].must_equal "mysql"
186
+ traces[6]['Query'].must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES (?, ?, ?, ?)"
129
187
  traces[6]['Name'].must_equal "SQL"
130
188
  traces[6].key?('Backtrace').must_equal true
131
189
  traces[6].key?('QueryArgs').must_equal true
@@ -133,9 +191,107 @@ if defined?(::Rails)
133
191
  traces[7]['Layer'].must_equal "activerecord"
134
192
  traces[7]['Label'].must_equal "exit"
135
193
 
194
+ traces[8]['Layer'].must_equal "activerecord"
195
+ traces[8]['Label'].must_equal "entry"
196
+ traces[8]['Flavor'].must_equal "mysql"
197
+ traces[8]['Query'].must_equal "COMMIT"
198
+ traces[8].key?('Backtrace').must_equal true
199
+
200
+ traces[9]['Layer'].must_equal "activerecord"
201
+ traces[9]['Label'].must_equal "exit"
202
+
203
+ traces[10]['Layer'].must_equal "activerecord"
204
+ traces[10]['Label'].must_equal "entry"
205
+ traces[10]['Flavor'].must_equal "mysql"
206
+ traces[10]['Name'].must_equal "Widget Load"
207
+ traces[10].key?('Backtrace').must_equal true
208
+
209
+ # Some versions of rails adds in another space before the ORDER keyword.
210
+ # Make 2 or more consecutive spaces just 1
211
+ sql = traces[10]['Query'].gsub(/\s{2,}/, ' ')
212
+ sql.must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = 'blah' LIMIT 1"
213
+
214
+ traces[11]['Layer'].must_equal "activerecord"
215
+ traces[11]['Label'].must_equal "exit"
216
+
217
+ traces[12]['Layer'].must_equal "activerecord"
218
+ traces[12]['Label'].must_equal "entry"
219
+ traces[12]['Flavor'].must_equal "mysql"
220
+ traces[12]['Name'].must_equal "SQL"
221
+ traces[12].key?('Backtrace').must_equal true
222
+ traces[12].key?('QueryArgs').must_equal false
223
+
224
+ # Replace the datestamps with xxx to make testing easier
225
+ sql = traces[12]['Query'].gsub(/\d+/, 'xxx')
226
+ sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = xxx"
227
+
228
+ traces[13]['Layer'].must_equal "activerecord"
229
+ traces[13]['Label'].must_equal "exit"
230
+
231
+ traces[14]['Layer'].must_equal "actionview"
232
+ traces[14]['Label'].must_equal "entry"
233
+
234
+ # Validate the existence of the response header
235
+ r['X-Trace'].must_equal traces[17]['X-Trace']
236
+ end
237
+
238
+ it "should trace rails mysql2 db calls" do
239
+ # Skip for JRuby since the java instrumentation
240
+ # handles DB instrumentation for JRuby
241
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != 'mysql2'
242
+
243
+ uri = URI.parse('http://127.0.0.1:8140/hello/db')
244
+ r = Net::HTTP.get_response(uri)
245
+
246
+ traces = get_all_traces
247
+
248
+ traces.count.must_equal 14
249
+ valid_edges?(traces).must_equal true
250
+ validate_outer_layers(traces, 'rack')
251
+
252
+ traces[4]['Layer'].must_equal "activerecord"
253
+ traces[4]['Label'].must_equal "entry"
254
+ traces[4]['Flavor'].must_equal "mysql"
255
+
256
+ # Replace the datestamps with xxx to make testing easier
257
+ sql = traces[4]['Query'].gsub(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/, 'xxx')
258
+ sql.must_equal "INSERT INTO `widgets` (`created_at`, `description`, `name`, `updated_at`) VALUES ('xxx', 'This is an amazing widget.', 'blah', 'xxx')"
259
+
260
+ traces[4]['Name'].must_equal "SQL"
261
+ traces[4].key?('Backtrace').must_equal true
262
+
263
+ traces[5]['Layer'].must_equal "activerecord"
264
+ traces[5]['Label'].must_equal "exit"
265
+
266
+ traces[6]['Layer'].must_equal "activerecord"
267
+ traces[6]['Label'].must_equal "entry"
268
+ traces[6]['Flavor'].must_equal "mysql"
269
+ traces[6]['Query'].must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = 'blah' LIMIT 1"
270
+ traces[6]['Name'].must_equal "Widget Load"
271
+ traces[6].key?('Backtrace').must_equal true
272
+ traces[6].key?('QueryArgs').must_equal false
273
+
274
+ traces[7]['Layer'].must_equal "activerecord"
275
+ traces[7]['Label'].must_equal "exit"
276
+
277
+ traces[8]['Layer'].must_equal "activerecord"
278
+ traces[8]['Label'].must_equal "entry"
279
+ traces[8]['Flavor'].must_equal "mysql"
280
+
281
+ # Replace the datestamps with xxx to make testing easier
282
+ sql = traces[8]['Query'].gsub(/\d+/, 'xxx')
283
+ sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = xxx"
284
+
285
+ traces[8]['Name'].must_equal "SQL"
286
+ traces[8].key?('Backtrace').must_equal true
287
+ traces[8].key?('QueryArgs').must_equal false
288
+
289
+ traces[9]['Layer'].must_equal "activerecord"
290
+ traces[9]['Label'].must_equal "exit"
291
+
136
292
  # Validate the existence of the response header
137
293
  r.header.key?('X-Trace').must_equal true
138
- r.header['X-Trace'].must_equal traces[11]['X-Trace']
294
+ r.header['X-Trace'].must_equal traces[13]['X-Trace']
139
295
  end
140
296
  end
141
297
  end
@@ -8,6 +8,7 @@ if defined?(::Rails)
8
8
  describe "Rails4x" do
9
9
  before do
10
10
  clear_all_traces
11
+ ENV['DBTYPE'] = "postgresql" unless ENV['DBTYPE']
11
12
  end
12
13
 
13
14
  it "should trace a request to a rails stack" do
@@ -51,52 +52,201 @@ if defined?(::Rails)
51
52
  traces[6]['Label'].must_equal "exit"
52
53
 
53
54
  # Validate the existence of the response header
54
- r.header.key?('X-Trace').must_equal true
55
- r.header['X-Trace'].must_equal traces[6]['X-Trace']
55
+ r['X-Trace'].must_equal traces[6]['X-Trace']
56
56
  end
57
57
 
58
- it "should trace rails db calls" do
58
+ it "should trace rails postgres db calls" do
59
59
  # Skip for JRuby since the java instrumentation
60
60
  # handles DB instrumentation for JRuby
61
- skip if defined?(JRUBY_VERSION)
61
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != 'postgresql'
62
62
 
63
63
  uri = URI.parse('http://127.0.0.1:8140/hello/db')
64
64
  r = Net::HTTP.get_response(uri)
65
65
 
66
66
  traces = get_all_traces
67
67
 
68
- traces.count.must_equal 11
68
+ traces.count.must_equal 13
69
69
  valid_edges?(traces).must_equal true
70
70
  validate_outer_layers(traces, 'rack')
71
71
 
72
72
  traces[3]['Layer'].must_equal "activerecord"
73
73
  traces[3]['Label'].must_equal "entry"
74
74
  traces[3]['Flavor'].must_equal "postgresql"
75
- traces[3]['Query'].must_equal "SELECT \"widgets\".* FROM \"widgets\" ORDER BY \"widgets\".\"id\" ASC LIMIT 1"
76
- traces[3]['Name'].must_equal "Widget Load"
75
+ traces[3]['Name'].must_equal "SQL"
77
76
  traces[3].key?('Backtrace').must_equal true
78
77
 
78
+ # Use a regular expression to test the SQL string since field order varies between
79
+ # Rails versions
80
+ match_data = traces[3]['Query'].match(/INSERT\sINTO\s\"widgets\"\s\(.*\)\sVALUES\s\(\$1,\s\$2,\s\$3,\s\$4\)\sRETURNING\s\"id\"/)
81
+ match_data.wont_equal nil
82
+ match_data.class.must_equal MatchData
83
+
79
84
  traces[4]['Layer'].must_equal "activerecord"
80
85
  traces[4]['Label'].must_equal "exit"
81
86
 
82
87
  traces[5]['Layer'].must_equal "activerecord"
83
88
  traces[5]['Label'].must_equal "entry"
84
89
  traces[5]['Flavor'].must_equal "postgresql"
85
- traces[5]['Query'].must_equal "INSERT INTO \"widgets\" (\"name\", \"description\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4) RETURNING \"id\""
86
- traces[5]['Name'].must_equal "SQL"
90
+
91
+ # Some versions of rails adds in another space before the ORDER keyword.
92
+ # Make 2 or more consecutive spaces just 1
93
+ sql = traces[5]['Query'].gsub(/\s{2,}/, ' ')
94
+ sql.must_equal "SELECT \"widgets\".* FROM \"widgets\" WHERE \"widgets\".\"name\" = $1 ORDER BY \"widgets\".\"id\" ASC LIMIT 1"
95
+
96
+ traces[5]['Name'].must_equal "Widget Load"
87
97
  traces[5].key?('Backtrace').must_equal true
88
98
  traces[5].key?('QueryArgs').must_equal true
89
99
 
90
100
  traces[6]['Layer'].must_equal "activerecord"
91
101
  traces[6]['Label'].must_equal "exit"
92
102
 
103
+ traces[7]['Layer'].must_equal "activerecord"
104
+ traces[7]['Label'].must_equal "entry"
105
+ traces[7]['Flavor'].must_equal "postgresql"
106
+ traces[7]['Query'].must_equal "DELETE FROM \"widgets\" WHERE \"widgets\".\"id\" = $1"
107
+ traces[7]['Name'].must_equal "SQL"
108
+ traces[7].key?('Backtrace').must_equal true
109
+ traces[7].key?('QueryArgs').must_equal true
110
+
111
+ traces[8]['Layer'].must_equal "activerecord"
112
+ traces[8]['Label'].must_equal "exit"
113
+
93
114
  # Validate the existence of the response header
94
115
  r.header.key?('X-Trace').must_equal true
95
- r.header['X-Trace'].must_equal traces[10]['X-Trace']
116
+ r.header['X-Trace'].must_equal traces[12]['X-Trace']
96
117
  end
97
118
 
98
- it "should trace a request to a rails metal stack" do
119
+ it "should trace rails mysql db calls" do
120
+ # Skip for JRuby since the java instrumentation
121
+ # handles DB instrumentation for JRuby
122
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "mysql"
123
+
124
+ uri = URI.parse('http://127.0.0.1:8140/hello/db')
125
+ r = Net::HTTP.get_response(uri)
126
+
127
+ traces = get_all_traces
128
+
129
+ traces.count.must_equal 17
130
+ valid_edges?(traces).must_equal true
131
+ validate_outer_layers(traces, 'rack')
132
+
133
+ traces[3]['Layer'].must_equal "activerecord"
134
+ traces[3]['Label'].must_equal "entry"
135
+ traces[3]['Flavor'].must_equal "mysql"
136
+ traces[3]['Query'].must_equal "BEGIN"
137
+ traces[3].key?('Backtrace').must_equal true
138
+
139
+ traces[4]['Layer'].must_equal "activerecord"
140
+ traces[4]['Label'].must_equal "exit"
141
+
142
+ traces[5]['Layer'].must_equal "activerecord"
143
+ traces[5]['Label'].must_equal "entry"
144
+ traces[5]['Flavor'].must_equal "mysql"
145
+ traces[5]['Query'].must_equal "INSERT INTO `widgets` (`name`, `description`, `created_at`, `updated_at`) VALUES (?, ?, ?, ?)"
146
+ traces[5]['Name'].must_equal "SQL"
147
+ traces[5].key?('Backtrace').must_equal true
148
+ traces[5].key?('QueryArgs').must_equal true
149
+
150
+ traces[6]['Layer'].must_equal "activerecord"
151
+ traces[6]['Label'].must_equal "exit"
152
+
153
+ traces[7]['Layer'].must_equal "activerecord"
154
+ traces[7]['Label'].must_equal "entry"
155
+ traces[7]['Flavor'].must_equal "mysql"
156
+ traces[7]['Query'].must_equal "COMMIT"
157
+ traces[7].key?('Backtrace').must_equal true
158
+
159
+ traces[8]['Layer'].must_equal "activerecord"
160
+ traces[8]['Label'].must_equal "exit"
161
+
162
+ traces[9]['Layer'].must_equal "activerecord"
163
+ traces[9]['Label'].must_equal "entry"
164
+ traces[9]['Flavor'].must_equal "mysql"
165
+ traces[9]['Name'].must_equal "Widget Load"
166
+ traces[9].key?('Backtrace').must_equal true
167
+
168
+ # Some versions of rails adds in another space before the ORDER keyword.
169
+ # Make 2 or more consecutive spaces just 1
170
+ sql = traces[9]['Query'].gsub(/\s{2,}/, ' ')
171
+ sql.must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = ? ORDER BY `widgets`.`id` ASC LIMIT 1"
172
+
173
+ traces[10]['Layer'].must_equal "activerecord"
174
+ traces[10]['Label'].must_equal "exit"
175
+
176
+ traces[11]['Layer'].must_equal "activerecord"
177
+ traces[11]['Label'].must_equal "entry"
178
+ traces[11]['Flavor'].must_equal "mysql"
179
+ traces[11]['Name'].must_equal "SQL"
180
+ traces[11].key?('Backtrace').must_equal true
181
+ traces[11].key?('QueryArgs').must_equal true
182
+ traces[11]['Query'].must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = ?"
99
183
 
184
+ traces[12]['Layer'].must_equal "activerecord"
185
+ traces[12]['Label'].must_equal "exit"
186
+
187
+ traces[13]['Layer'].must_equal "actionview"
188
+ traces[13]['Label'].must_equal "entry"
189
+
190
+ # Validate the existence of the response header
191
+ r['X-Trace'].must_equal traces[16]['X-Trace']
192
+ end
193
+
194
+ it "should trace rails mysql2 db calls" do
195
+ # Skip for JRuby since the java instrumentation
196
+ # handles DB instrumentation for JRuby
197
+ skip if defined?(JRUBY_VERSION) || ENV['DBTYPE'] != "mysql2"
198
+
199
+ uri = URI.parse('http://127.0.0.1:8140/hello/db')
200
+ r = Net::HTTP.get_response(uri)
201
+
202
+ traces = get_all_traces
203
+
204
+ traces.count.must_equal 13
205
+ valid_edges?(traces).must_equal true
206
+ validate_outer_layers(traces, 'rack')
207
+
208
+ traces[3]['Layer'].must_equal "activerecord"
209
+ traces[3]['Label'].must_equal "entry"
210
+ traces[3]['Flavor'].must_equal "mysql"
211
+
212
+ # Replace the datestamps with xxx to make testing easier
213
+ sql = traces[3]['Query'].gsub(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/, 'xxx')
214
+ sql.must_equal "INSERT INTO `widgets` (`name`, `description`, `created_at`, `updated_at`) VALUES ('blah', 'This is an amazing widget.', 'xxx', 'xxx')"
215
+
216
+ traces[3]['Name'].must_equal "SQL"
217
+ traces[3].key?('Backtrace').must_equal true
218
+ traces[3].key?('QueryArgs').must_equal true
219
+
220
+ traces[4]['Layer'].must_equal "activerecord"
221
+ traces[4]['Label'].must_equal "exit"
222
+
223
+ traces[5]['Layer'].must_equal "activerecord"
224
+ traces[5]['Label'].must_equal "entry"
225
+ traces[5]['Flavor'].must_equal "mysql"
226
+ traces[5]['Query'].must_equal "SELECT `widgets`.* FROM `widgets` WHERE `widgets`.`name` = 'blah' ORDER BY `widgets`.`id` ASC LIMIT 1"
227
+ traces[5]['Name'].must_equal "Widget Load"
228
+ traces[5].key?('Backtrace').must_equal true
229
+
230
+ traces[6]['Layer'].must_equal "activerecord"
231
+ traces[6]['Label'].must_equal "exit"
232
+
233
+ traces[7]['Layer'].must_equal "activerecord"
234
+ traces[7]['Label'].must_equal "entry"
235
+ traces[7]['Flavor'].must_equal "mysql"
236
+ traces[7]['Name'].must_equal "SQL"
237
+ traces[7].key?('Backtrace').must_equal true
238
+
239
+ sql = traces[7]['Query'].gsub(/\d+/, 'xxx')
240
+ sql.must_equal "DELETE FROM `widgets` WHERE `widgets`.`id` = xxx"
241
+
242
+ traces[8]['Layer'].must_equal "activerecord"
243
+ traces[8]['Label'].must_equal "exit"
244
+
245
+ # Validate the existence of the response header
246
+ r['X-Trace'].must_equal traces[12]['X-Trace']
247
+ end
248
+
249
+ it "should trace a request to a rails metal stack" do
100
250
  uri = URI.parse('http://127.0.0.1:8140/hello/metal')
101
251
  r = Net::HTTP.get_response(uri)
102
252
 
@@ -134,8 +284,7 @@ if defined?(::Rails)
134
284
  traces[4]['Label'].must_equal "exit"
135
285
 
136
286
  # Validate the existence of the response header
137
- r.header.key?('X-Trace').must_equal true
138
- r.header['X-Trace'].must_equal traces[4]['X-Trace']
287
+ r['X-Trace'].must_equal traces[4]['X-Trace']
139
288
  end
140
289
  end
141
290
  end