newrelic_rpm 3.3.1 → 3.3.2.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/CHANGELOG +6 -0
- data/lib/new_relic/agent/database.rb +29 -9
- data/lib/new_relic/agent/samplers/memory_sampler.rb +5 -6
- data/lib/new_relic/agent/transaction_sampler.rb +10 -2
- data/lib/new_relic/control/frameworks/rails3.rb +1 -1
- data/lib/new_relic/language_support.rb +3 -2
- data/lib/new_relic/local_environment.rb +3 -4
- data/lib/new_relic/rack/browser_monitoring.rb +9 -8
- data/lib/new_relic/rack/developer_mode.rb +2 -2
- data/lib/new_relic/recipes.rb +7 -3
- data/lib/new_relic/stats.rb +0 -53
- data/lib/new_relic/transaction_sample.rb +1 -1
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +2 -2
- data/test/new_relic/agent/database_test.rb +33 -46
- data/test/new_relic/rack/browser_monitoring_test.rb +20 -16
- data/test/new_relic/rack/developer_mode_test.rb +31 -0
- data/test/new_relic/stats_test.rb +0 -15
- metadata +6 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v3.3.2
|
2
|
+
* deployments recipe change: truncate git SHAs to 7 characters
|
3
|
+
* Fixes for obfuscation of PostgreSQL and SQLite queries
|
4
|
+
* Fix for lost database connections when using a forking framework
|
5
|
+
* Workaround for RedHat kernel bug which prevented blocking reads of /proc fs
|
6
|
+
|
1
7
|
v3.3.1
|
2
8
|
* improved Ruby 1.8.6 support
|
3
9
|
* fix for issues with RAILS_ROOT deprecation warnings
|
@@ -187,16 +187,36 @@ module NewRelic
|
|
187
187
|
end
|
188
188
|
|
189
189
|
def default_sql_obfuscator(sql)
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
190
|
+
stmt = sql.kind_of?(Statement) ? sql : Statement.new(sql)
|
191
|
+
adapter = stmt.adapter
|
192
|
+
obfuscated = remove_escaped_quotes(stmt)
|
193
|
+
obfuscated = obfuscate_single_quote_literals(obfuscated)
|
194
|
+
if !(adapter.to_s =~ /postgres/ || adapter.to_s =~ /sqlite/)
|
195
|
+
obfuscated = obfuscate_double_quote_literals(obfuscated)
|
196
|
+
end
|
197
|
+
obfuscated = obfuscate_numeric_literals(obfuscated)
|
198
|
+
obfuscated.to_s # return back to a regular String
|
199
|
+
end
|
200
|
+
|
201
|
+
def remove_escaped_quotes(sql)
|
202
|
+
sql.gsub(/\\"/, '').gsub(/\\'/, '')
|
199
203
|
end
|
204
|
+
|
205
|
+
def obfuscate_single_quote_literals(sql)
|
206
|
+
sql.gsub(/'(?:[^']|'')*'/, '?')
|
207
|
+
end
|
208
|
+
|
209
|
+
def obfuscate_double_quote_literals(sql)
|
210
|
+
sql.gsub(/"(?:[^"]|"")*"/, '?')
|
211
|
+
end
|
212
|
+
|
213
|
+
def obfuscate_numeric_literals(sql)
|
214
|
+
sql.gsub(/\b\d+\b/, "?")
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class Statement < String
|
219
|
+
attr_accessor :adapter
|
200
220
|
end
|
201
221
|
end
|
202
222
|
end
|
@@ -122,18 +122,17 @@ module NewRelic
|
|
122
122
|
# Returns the amount of resident memory this process is using in MB
|
123
123
|
#
|
124
124
|
def get_memory
|
125
|
-
File.open(proc_status_file, "r")
|
126
|
-
|
127
|
-
|
128
|
-
return $1.to_f / 1024.0
|
129
|
-
end
|
130
|
-
end
|
125
|
+
proc_status = File.open(proc_status_file, "r") {|f| f.read_nonblock(4096).strip }
|
126
|
+
if proc_status =~ /RSS:\s*(\d+) kB/i
|
127
|
+
return $1.to_f / 1024.0
|
131
128
|
end
|
132
129
|
raise "Unable to find RSS in #{proc_status_file}"
|
133
130
|
end
|
131
|
+
|
134
132
|
def proc_status_file
|
135
133
|
"/proc/#{$$}/status"
|
136
134
|
end
|
135
|
+
|
137
136
|
def to_s
|
138
137
|
"proc status file sampler: #{proc_status_file}"
|
139
138
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'new_relic/agent'
|
2
2
|
require 'new_relic/control'
|
3
3
|
require 'new_relic/agent/transaction_sample_builder'
|
4
|
+
|
4
5
|
module NewRelic
|
5
6
|
module Agent
|
6
7
|
|
@@ -271,8 +272,14 @@ module NewRelic
|
|
271
272
|
return unless builder
|
272
273
|
segment = builder.current_segment
|
273
274
|
if segment
|
274
|
-
|
275
|
-
|
275
|
+
new_message = truncate_message(append_new_message(segment[key],
|
276
|
+
message))
|
277
|
+
if key == :sql && config.respond_to?(:has_key?) && config.has_key?(:adapter)
|
278
|
+
segment[key] = Database::Statement.new(new_message)
|
279
|
+
segment[key].adapter = config[:adapter]
|
280
|
+
else
|
281
|
+
segment[key] = new_message
|
282
|
+
end
|
276
283
|
segment[config_key] = config if config_key
|
277
284
|
append_backtrace(segment, duration)
|
278
285
|
end
|
@@ -336,6 +343,7 @@ module NewRelic
|
|
336
343
|
@harvest_count += 1
|
337
344
|
if (@harvest_count.to_i % @sampling_rate.to_i) == 0
|
338
345
|
result << @random_sample if @random_sample
|
346
|
+
@harvest_count = 0
|
339
347
|
end
|
340
348
|
nil # don't assume this method returns anything
|
341
349
|
end
|
@@ -27,8 +27,9 @@ module NewRelic::LanguageSupport
|
|
27
27
|
def self.included(base)
|
28
28
|
# need to use syck rather than psych when possible
|
29
29
|
if defined?(::YAML::ENGINE)
|
30
|
-
|
31
|
-
|
30
|
+
if !NewRelic::LanguageSupport.using_engine?('jruby') &&
|
31
|
+
(NewRelic::LanguageSupport.using_version?('1.9.1') ||
|
32
|
+
NewRelic::LanguageSupport.using_version?('1.9.2'))
|
32
33
|
base.class_eval do
|
33
34
|
def load_newrelic_yml(*args)
|
34
35
|
yamler = ::YAML::ENGINE.yamler
|
@@ -106,7 +106,9 @@ module NewRelic
|
|
106
106
|
def gather_cpu_info
|
107
107
|
return unless File.readable? '/proc/cpuinfo'
|
108
108
|
@processors = append_environment_value('Processors') do
|
109
|
-
|
109
|
+
cpuinfo = File.open("/proc/cpuinfo") {|f| f.read_nonblock(4096).strip }
|
110
|
+
processors = cpuinfo.split("\n").select {|line| line =~ /^processor\s*:/ }.size
|
111
|
+
|
110
112
|
raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
|
111
113
|
processors
|
112
114
|
end
|
@@ -156,9 +158,6 @@ module NewRelic
|
|
156
158
|
end
|
157
159
|
end
|
158
160
|
end
|
159
|
-
append_environment_value 'Database schema version' do
|
160
|
-
ActiveRecord::Migrator.current_version
|
161
|
-
end
|
162
161
|
end
|
163
162
|
|
164
163
|
# Datamapper version
|
@@ -15,13 +15,13 @@ module NewRelic::Rack
|
|
15
15
|
# NewRelic::Agent::TransactionInfo.get.force_persist = true
|
16
16
|
# NewRelic::Agent::TransactionInfo.get.capture_deep_tt = true
|
17
17
|
# end
|
18
|
-
|
18
|
+
|
19
19
|
# if req.params['nr_capture_tt']
|
20
20
|
# NewRelic::Agent::TransactionInfo.get.force_persist = true
|
21
21
|
# end
|
22
|
-
|
22
|
+
|
23
23
|
result = @app.call(env) # [status, headers, response]
|
24
|
-
|
24
|
+
|
25
25
|
if (NewRelic::Agent.browser_timing_header != "") && should_instrument?(result[0], result[1])
|
26
26
|
response_string = autoinstrument_source(result[2], result[1])
|
27
27
|
|
@@ -37,24 +37,25 @@ module NewRelic::Rack
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def should_instrument?(status, headers)
|
40
|
-
status == 200 && headers["Content-Type"] && headers["Content-Type"].include?("text/html")
|
40
|
+
status == 200 && headers["Content-Type"] && headers["Content-Type"].include?("text/html") &&
|
41
|
+
!headers['Content-Disposition'].to_s.include?('attachment')
|
41
42
|
end
|
42
43
|
|
43
44
|
def autoinstrument_source(response, headers)
|
44
45
|
source = nil
|
45
46
|
response.each {|fragment| source ? (source << fragment.to_s) : (source = fragment.to_s)}
|
46
47
|
return nil unless source
|
47
|
-
|
48
|
+
|
48
49
|
body_start = source.index("<body")
|
49
50
|
body_close = source.rindex("</body>")
|
50
51
|
|
51
52
|
if body_start && body_close
|
52
53
|
footer = NewRelic::Agent.browser_timing_footer
|
53
54
|
header = NewRelic::Agent.browser_timing_header
|
54
|
-
|
55
|
+
|
55
56
|
if source.include?('X-UA-Compatible')
|
56
57
|
# put at end of header if UA-Compatible meta tag found
|
57
|
-
head_pos = source.index("</head>")
|
58
|
+
head_pos = source.index("</head>")
|
58
59
|
elsif head_open = source.index("<head")
|
59
60
|
# put at the beginning of the header
|
60
61
|
head_pos = source.index(">", head_open) + 1
|
@@ -71,5 +72,5 @@ module NewRelic::Rack
|
|
71
72
|
source
|
72
73
|
end
|
73
74
|
end
|
74
|
-
|
75
|
+
|
75
76
|
end
|
@@ -83,9 +83,9 @@ module NewRelic
|
|
83
83
|
@obfuscated_sql = @segment.obfuscated_sql
|
84
84
|
end
|
85
85
|
|
86
|
-
explanations = @segment.explain_sql
|
86
|
+
headers, explanations = @segment.explain_sql
|
87
87
|
if explanations
|
88
|
-
@explanation = explanations
|
88
|
+
@explanation = explanations
|
89
89
|
if !@explanation.blank?
|
90
90
|
first_row = @explanation.first
|
91
91
|
# Show the standard headers if it looks like a mysql explain plan
|
data/lib/new_relic/recipes.rb
CHANGED
@@ -33,10 +33,14 @@ make_notify_task = Proc.new do
|
|
33
33
|
end
|
34
34
|
changelog = `#{log_command}`
|
35
35
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
if rev.nil?
|
37
|
+
rev = source.query_revision(source.head()) do |cmd|
|
38
|
+
logger.debug "executing locally: '#{cmd}'"
|
39
|
+
`#{cmd}`
|
40
|
+
end
|
41
|
+
rev = rev[0..6] if scm == :git
|
39
42
|
end
|
43
|
+
new_revision = rev
|
40
44
|
deploy_options = { :environment => rails_env,
|
41
45
|
:revision => new_revision,
|
42
46
|
:changelog => changelog,
|
data/lib/new_relic/stats.rb
CHANGED
@@ -104,43 +104,6 @@ module NewRelic
|
|
104
104
|
stats.merge!(other_stats)
|
105
105
|
end
|
106
106
|
|
107
|
-
# split into an array of timeslices whose
|
108
|
-
# time boundaries start on (begin_time + (n * duration)) and whose
|
109
|
-
# end time ends on (begin_time * (n + 1) * duration), except for the
|
110
|
-
# first and last elements, whose begin time and end time are the begin
|
111
|
-
# and end times of this stats instance, respectively. Yield to caller
|
112
|
-
# for the code that creates the actual stats instance
|
113
|
-
def split(rollup_begin_time, rollup_period)
|
114
|
-
rollup_begin_time = rollup_begin_time.to_f
|
115
|
-
rollup_begin_time += ((self.begin_time - rollup_begin_time) / rollup_period).floor * rollup_period
|
116
|
-
|
117
|
-
current_begin_time = self.begin_time
|
118
|
-
current_end_time = rollup_begin_time + rollup_period
|
119
|
-
|
120
|
-
return [self] if current_end_time >= self.end_time
|
121
|
-
|
122
|
-
timeslices = []
|
123
|
-
while current_end_time < self.end_time do
|
124
|
-
ts = yield(current_begin_time, current_end_time)
|
125
|
-
if ts
|
126
|
-
ts.fraction_of(self)
|
127
|
-
timeslices << ts
|
128
|
-
end
|
129
|
-
current_begin_time = current_end_time
|
130
|
-
current_end_time = current_begin_time + rollup_period
|
131
|
-
end
|
132
|
-
|
133
|
-
if self.end_time > current_begin_time
|
134
|
-
percentage = rollup_period / self.duration + (self.begin_time - rollup_begin_time) / rollup_period
|
135
|
-
ts = yield(current_begin_time, self.end_time)
|
136
|
-
if ts
|
137
|
-
ts.fraction_of(self)
|
138
|
-
timeslices << ts
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
timeslices
|
143
|
-
end
|
144
107
|
|
145
108
|
def is_reset?
|
146
109
|
call_count == 0 && total_call_time == 0.0 && total_exclusive_time == 0.0
|
@@ -216,22 +179,6 @@ module NewRelic
|
|
216
179
|
"[#{Time.at(begin_time.to_f).utc.strftime(format)} UTC, #{'%2.3fs' % duration.to_f}; #{'%2i' % call_count.to_i} calls #{'%4i' % average_call_time.to_f}s]"
|
217
180
|
end
|
218
181
|
|
219
|
-
# calculate this set of stats to be a percentage fraction
|
220
|
-
# of the provided stats, which has an overlapping time window.
|
221
|
-
# used as a key part of the split algorithm
|
222
|
-
def fraction_of(s)
|
223
|
-
min_end = (end_time < s.end_time ? end_time : s.end_time)
|
224
|
-
max_begin = (begin_time > s.begin_time ? begin_time : s.begin_time)
|
225
|
-
percentage = (min_end - max_begin) / s.duration
|
226
|
-
|
227
|
-
self.total_exclusive_time = s.total_exclusive_time * percentage
|
228
|
-
self.total_call_time = s.total_call_time * percentage
|
229
|
-
self.min_call_time = s.min_call_time
|
230
|
-
self.max_call_time = s.max_call_time
|
231
|
-
self.call_count = s.call_count * percentage
|
232
|
-
self.sum_of_squares = (s.sum_of_squares || 0) * percentage
|
233
|
-
end
|
234
|
-
|
235
182
|
# multiply the total time and rate by the given percentage
|
236
183
|
def multiply_by(percentage)
|
237
184
|
self.total_call_time = total_call_time * percentage
|
@@ -234,7 +234,7 @@ module NewRelic
|
|
234
234
|
when :raw then v
|
235
235
|
when :obfuscated then NewRelic::Agent::Database.obfuscate_sql(v)
|
236
236
|
else raise "Invalid value for record_sql: #{options[:record_sql]}"
|
237
|
-
end if options[:record_sql]
|
237
|
+
end.to_s if options[:record_sql]
|
238
238
|
when :connection_config
|
239
239
|
# don't copy it
|
240
240
|
else
|
data/lib/new_relic/version.rb
CHANGED
@@ -3,8 +3,8 @@ module NewRelic
|
|
3
3
|
module VERSION #:nodoc:
|
4
4
|
MAJOR = 3
|
5
5
|
MINOR = 3
|
6
|
-
TINY =
|
7
|
-
BUILD =
|
6
|
+
TINY = 2
|
7
|
+
BUILD = 'beta1' # Set to nil for a release, 'beta1', 'alpha', etc for prerelease builds
|
8
8
|
STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
|
9
9
|
end
|
10
10
|
|
data/newrelic_rpm.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{newrelic_rpm}
|
8
|
-
s.version = "3.3.
|
8
|
+
s.version = "3.3.2.beta1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Bill Kayser", "Jon Guymon", "Justin George", "Darin Swanson"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2012-01-20}
|
13
13
|
s.description = %q{New Relic is a performance management system, developed by New Relic,
|
14
14
|
Inc (http://www.newrelic.com). New Relic provides you with deep
|
15
15
|
information about the performance of your web application as it runs
|
@@ -83,59 +83,46 @@ class NewRelic::Agent::DatabaseTest < Test::Unit::TestCase
|
|
83
83
|
raise(fake_error)
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
def test_obfuscation_mysql_basic
|
88
|
+
insert = %q[INSERT INTO `X` values("test",0, 1 , 2, 'test')]
|
89
|
+
assert_equal("INSERT INTO `X` values(?,?, ? , ?, ?)",
|
90
|
+
NewRelic::Agent::Database.obfuscate_sql(insert))
|
91
|
+
select = %q[SELECT `table`.`column` FROM `table` WHERE `table`.`column` = 'value' AND `table`.`other_column` = "other value" LIMIT 1]
|
92
|
+
assert_equal(%q[SELECT `table`.`column` FROM `table` WHERE `table`.`column` = ? AND `table`.`other_column` = ? LIMIT ?],
|
93
|
+
NewRelic::Agent::Database.obfuscate_sql(select))
|
94
|
+
end
|
86
95
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
# multiple string literals
|
97
|
-
assert_equal "INSERT INTO X values(?,?,?, ? , ?)",
|
98
|
-
NewRelic::Agent::Database.obfuscate_sql("INSERT INTO X values('jim''s ssn','x',0, 1 , 2)")
|
99
|
-
|
100
|
-
# empty string literal
|
101
|
-
# NOTE: the empty string literal resolves to empty string, which for our purposes is acceptable
|
102
|
-
assert_equal "INSERT INTO X values(?,?,?, ? , ?)",
|
103
|
-
NewRelic::Agent::Database.obfuscate_sql("INSERT INTO X values('','x',0, 1 , 2)")
|
104
|
-
|
105
|
-
# try a select statement
|
106
|
-
assert_equal "select * from table where name=? and ssn=?",
|
107
|
-
NewRelic::Agent::Database.obfuscate_sql("select * from table where name='jim gochee' and ssn=0012211223")
|
108
|
-
|
109
|
-
# number literals embedded in sql - oh well
|
110
|
-
assert_equal "select * from table_? where name=? and ssn=?",
|
111
|
-
NewRelic::Agent::Database.obfuscate_sql("select * from table_007 where name='jim gochee' and ssn=0012211223")
|
96
|
+
def test_obfuscation_postgresql_basic
|
97
|
+
insert = NewRelic::Agent::Database::Statement.new(%q[INSERT INTO "X" values('test',0, 1 , 2, 'test')])
|
98
|
+
insert.adapter = :postgresql
|
99
|
+
assert_equal('INSERT INTO "X" values(?,?, ? , ?, ?)',
|
100
|
+
NewRelic::Agent::Database.obfuscate_sql(insert))
|
101
|
+
select = NewRelic::Agent::Database::Statement.new(%q[SELECT "table"."column" FROM "table" WHERE "table"."column" = 'value' AND "table"."other_column" = 'other value' LIMIT 1])
|
102
|
+
select.adapter = :postgresql
|
103
|
+
assert_equal(%q[SELECT "table"."column" FROM "table" WHERE "table"."column" = ? AND "table"."other_column" = ? LIMIT ?],
|
104
|
+
NewRelic::Agent::Database.obfuscate_sql(select))
|
112
105
|
end
|
113
106
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT '"' into table])
|
119
|
-
assert_equal "INSERT ? into table",
|
120
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT ' "some text" \" ' into table])
|
121
|
-
# could not get this one licked. no biggie
|
122
|
-
# assert_equal "INSERT ? into table",
|
123
|
-
# @agent.send(:default_sql_obfuscator, %q[INSERT '\'' into table])
|
124
|
-
assert_equal "INSERT ? into table",
|
125
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT ''' ' into table])
|
107
|
+
def test_obfuscation_escaped_literals
|
108
|
+
insert = %q[INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son', """jim''s"" hat", "\"jim''s secret\"")]
|
109
|
+
assert_equal("INSERT INTO X values(?, ?,?, ? , ?, ?, ?)",
|
110
|
+
NewRelic::Agent::Database.obfuscate_sql(insert))
|
126
111
|
end
|
127
112
|
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT "'" into table])
|
133
|
-
assert_equal "INSERT ? into table",
|
134
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT " \" " into table])
|
135
|
-
assert_equal "INSERT ? into table",
|
136
|
-
NewRelic::Agent::Database.obfuscate_sql(%q[INSERT " 'some text' " into table])
|
113
|
+
def test_obfuscation_mysql_integers_in_identifiers
|
114
|
+
select = %q[SELECT * FROM `table_007` LIMIT 1]
|
115
|
+
assert_equal(%q[SELECT * FROM `table_007` LIMIT ?],
|
116
|
+
NewRelic::Agent::Database.obfuscate_sql(select))
|
137
117
|
end
|
138
118
|
|
119
|
+
def test_obfuscation_postgresql_integers_in_identifiers
|
120
|
+
select = NewRelic::Agent::Database::Statement.new(%q[SELECT * FROM "table_007" LIMIT 1])
|
121
|
+
select.adapter = :postgresql
|
122
|
+
assert_equal(%q[SELECT * FROM "table_007" LIMIT ?],
|
123
|
+
NewRelic::Agent::Database.obfuscate_sql(select))
|
124
|
+
end
|
125
|
+
|
139
126
|
def test_sql_obfuscation_filters
|
140
127
|
NewRelic::Agent::Database.set_sql_obfuscator(:replace) do |string|
|
141
128
|
"1" + string
|
@@ -15,7 +15,7 @@ end
|
|
15
15
|
if middleware_supported?
|
16
16
|
class BrowserMonitoringTest < Test::Unit::TestCase
|
17
17
|
include Rack::Test::Methods
|
18
|
-
|
18
|
+
|
19
19
|
class TestApp
|
20
20
|
def self.doc=(other)
|
21
21
|
@@doc = other
|
@@ -38,11 +38,11 @@ EOL
|
|
38
38
|
end
|
39
39
|
include NewRelic::Agent::Instrumentation::Rack
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def app
|
43
43
|
NewRelic::Rack::BrowserMonitoring.new(TestApp.new)
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def setup
|
47
47
|
super
|
48
48
|
clear_cookies
|
@@ -54,36 +54,40 @@ EOL
|
|
54
54
|
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(config)
|
55
55
|
NewRelic::Agent.stubs(:is_transaction_traced?).returns(true)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def teardown
|
59
59
|
super
|
60
60
|
clear_cookies
|
61
61
|
mocha_teardown
|
62
62
|
TestApp.doc = nil
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def test_make_sure_header_is_set
|
66
66
|
assert NewRelic::Agent.browser_timing_header.size > 0
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def test_make_sure_footer_is_set
|
70
70
|
assert NewRelic::Agent.browser_timing_footer.size > 0
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def test_should_only_instrument_successfull_html_requests
|
74
74
|
assert app.should_instrument?(200, {'Content-Type' => 'text/html'})
|
75
75
|
assert !app.should_instrument?(500, {'Content-Type' => 'text/html'})
|
76
76
|
assert !app.should_instrument?(200, {'Content-Type' => 'text/xhtml'})
|
77
77
|
end
|
78
78
|
|
79
|
+
def test_should_not_instrument_when_content_disposition
|
80
|
+
assert !app.should_instrument?(200, {'Content-Type' => 'text/html', 'Content-Disposition' => 'attachment; filename=test.html'})
|
81
|
+
end
|
82
|
+
|
79
83
|
def test_insert_timing_header_right_after_open_head_if_no_meta_tags
|
80
84
|
get '/'
|
81
|
-
|
85
|
+
|
82
86
|
assert(last_response.body.include?("head>#{NewRelic::Agent.browser_timing_header}"),
|
83
87
|
last_response.body)
|
84
88
|
TestApp.doc = nil
|
85
|
-
end
|
86
|
-
|
89
|
+
end
|
90
|
+
|
87
91
|
def test_insert_timing_header_right_before_head_close_if_ua_compatible_found
|
88
92
|
TestApp.doc = <<-EOL
|
89
93
|
<html>
|
@@ -98,30 +102,30 @@ EOL
|
|
98
102
|
</html>
|
99
103
|
EOL
|
100
104
|
get '/'
|
101
|
-
|
105
|
+
|
102
106
|
assert(last_response.body.include?("#{NewRelic::Agent.browser_timing_header}</head>"),
|
103
107
|
last_response.body)
|
104
108
|
end
|
105
|
-
|
109
|
+
|
106
110
|
def test_insert_timing_footer_right_before_html_body_close
|
107
111
|
get '/'
|
108
|
-
|
112
|
+
|
109
113
|
assert_match(/.*NREUMQ\.push.*new Date\(\)\.getTime\(\),"","","","",""\]\)<\/script><\/body>/,
|
110
114
|
last_response.body)
|
111
115
|
end
|
112
|
-
|
116
|
+
|
113
117
|
def test_should_not_throw_exception_on_empty_reponse
|
114
118
|
TestApp.doc = ''
|
115
119
|
get '/'
|
116
120
|
|
117
121
|
assert last_response.ok?
|
118
122
|
end
|
119
|
-
|
123
|
+
|
120
124
|
def test_token_is_set_in_footer_when_set_by_cookie
|
121
125
|
token = '1234567890987654321'
|
122
126
|
set_cookie "NRAGENT=tk=#{token}"
|
123
127
|
get '/'
|
124
|
-
|
128
|
+
|
125
129
|
assert(last_response.body.include?(token), last_response.body)
|
126
130
|
end
|
127
131
|
|
@@ -40,4 +40,35 @@ class DeveloperModeTest < Test::Unit::TestCase
|
|
40
40
|
assert last_response.body.include?('SandwichesController')
|
41
41
|
assert last_response.body.include?('index')
|
42
42
|
end
|
43
|
+
|
44
|
+
def test_explain_sql_displays_query_plan
|
45
|
+
sample = @sampler.samples[0]
|
46
|
+
sql_segment = sample.sql_segments[0]
|
47
|
+
explain_results = NewRelic::Agent::Database.process_resultset(example_explain_as_hashes)
|
48
|
+
|
49
|
+
NewRelic::TransactionSample::Segment.any_instance.expects(:explain_sql).returns(explain_results)
|
50
|
+
get "/newrelic/explain_sql?id=#{sample.sample_id}&segment=#{sql_segment.segment_id}"
|
51
|
+
|
52
|
+
assert last_response.ok?
|
53
|
+
assert last_response.body.include?('PRIMARY')
|
54
|
+
assert last_response.body.include?('Key Length')
|
55
|
+
assert last_response.body.include?('Using index')
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def example_explain_as_hashes
|
61
|
+
[{
|
62
|
+
'Id' => '1',
|
63
|
+
'Select Type' => 'SIMPLE',
|
64
|
+
'Table' => 'sandwiches',
|
65
|
+
'Type' => 'range',
|
66
|
+
'Possible Keys' => 'PRIMARY',
|
67
|
+
'Key' => 'PRIMARY',
|
68
|
+
'Key Length' => '4',
|
69
|
+
'Ref' => '',
|
70
|
+
'Rows' => '1',
|
71
|
+
'Extra' => 'Using index'
|
72
|
+
}]
|
73
|
+
end
|
43
74
|
end
|
@@ -172,21 +172,6 @@ class NewRelic::StatsTest < Test::Unit::TestCase
|
|
172
172
|
assert_equal(s1.time_str(20000), "20.0 s")
|
173
173
|
end
|
174
174
|
|
175
|
-
def test_fraction_of
|
176
|
-
s1 = NewRelic::MethodTraceStats.new
|
177
|
-
s2 = NewRelic::MethodTraceStats.new
|
178
|
-
s1.trace_call 10
|
179
|
-
s2.trace_call 20
|
180
|
-
assert_equal(s1.fraction_of(s2).to_s, 'NaN')
|
181
|
-
end
|
182
|
-
|
183
|
-
def test_fraction_of2
|
184
|
-
s1 = NewRelic::MethodTraceStats.new
|
185
|
-
s1.trace_call 10
|
186
|
-
s2 = NewRelic::MethodTraceStats.new
|
187
|
-
assert_equal(s1.fraction_of(s2).to_s, 'NaN')
|
188
|
-
end
|
189
|
-
|
190
175
|
def test_multiply_by
|
191
176
|
s1 = NewRelic::MethodTraceStats.new
|
192
177
|
s1.trace_call 10
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_rpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 62196449
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 3
|
9
|
+
- 2
|
10
|
+
- beta
|
9
11
|
- 1
|
10
|
-
version: 3.3.
|
12
|
+
version: 3.3.2.beta1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Bill Kayser
|
@@ -18,7 +20,7 @@ autorequire:
|
|
18
20
|
bindir: bin
|
19
21
|
cert_chain: []
|
20
22
|
|
21
|
-
date:
|
23
|
+
date: 2012-01-20 00:00:00 -08:00
|
22
24
|
default_executable:
|
23
25
|
dependencies:
|
24
26
|
- !ruby/object:Gem::Dependency
|