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.
- checksums.yaml +4 -4
- data/.travis.yml +12 -1
- data/CHANGELOG.md +11 -0
- data/CONFIG.md +22 -5
- data/Rakefile +2 -2
- data/gemfiles/delayed_job.gemfile +1 -1
- data/gemfiles/frameworks.gemfile +1 -1
- data/gemfiles/libraries.gemfile +4 -3
- data/gemfiles/rails31.gemfile +2 -0
- data/gemfiles/rails32.gemfile +5 -2
- data/gemfiles/rails40.gemfile +5 -3
- data/gemfiles/rails41.gemfile +6 -4
- data/gemfiles/rails42.gemfile +3 -1
- data/gemfiles/rails50.gemfile +43 -0
- data/lib/rails/generators/traceview/templates/traceview_initializer.rb +56 -32
- data/lib/traceview/base.rb +1 -1
- data/lib/traceview/frameworks/rails.rb +6 -9
- data/lib/traceview/frameworks/rails/inst/action_controller.rb +2 -135
- data/lib/traceview/frameworks/rails/inst/action_controller2.rb +59 -0
- data/lib/traceview/frameworks/rails/inst/action_controller3.rb +49 -0
- data/lib/traceview/frameworks/rails/inst/action_controller4.rb +40 -0
- data/lib/traceview/frameworks/rails/inst/action_controller5.rb +39 -0
- data/lib/traceview/frameworks/rails/inst/action_view.rb +1 -1
- data/lib/traceview/frameworks/rails/inst/active_record.rb +6 -3
- data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +1 -1
- data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +30 -36
- data/lib/traceview/frameworks/rails/inst/connection_adapters/utils5x.rb +100 -0
- data/lib/traceview/test.rb +39 -0
- data/lib/traceview/version.rb +1 -1
- data/test/frameworks/rails3x_test.rb +163 -7
- data/test/frameworks/rails4x_test.rb +162 -13
- data/test/frameworks/rails5x_test.rb +213 -0
- data/test/instrumentation/excon_test.rb +3 -0
- data/test/instrumentation/sequel_mysql2_test.rb +2 -5
- data/test/instrumentation/sequel_mysql_test.rb +2 -5
- data/test/instrumentation/sequel_pg_test.rb +2 -5
- data/test/minitest_helper.rb +25 -21
- data/test/servers/delayed_job.rb +2 -6
- data/test/servers/rails3x_8140.rb +16 -6
- data/test/servers/rails4x_8140.rb +20 -9
- data/test/servers/rails5x_8140.rb +112 -0
- metadata +13 -4
- 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
|
data/lib/traceview/test.rb
CHANGED
@@ -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
|
data/lib/traceview/version.rb
CHANGED
@@ -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
|
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
|
-
|
119
|
-
|
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 "
|
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[
|
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
|
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
|
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]['
|
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
|
-
|
86
|
-
|
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[
|
116
|
+
r.header['X-Trace'].must_equal traces[12]['X-Trace']
|
96
117
|
end
|
97
118
|
|
98
|
-
it "should trace
|
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
|
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
|