dolores_rpm 3.2.0.6 → 3.3.4.fork

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/CHANGELOG +32 -6
  2. data/dolores_rpm.gemspec +15 -11
  3. data/lib/new_relic/agent/agent.rb +28 -14
  4. data/lib/new_relic/agent/beacon_configuration.rb +11 -0
  5. data/lib/new_relic/agent/browser_monitoring.rb +53 -13
  6. data/lib/new_relic/agent/database.rb +34 -14
  7. data/lib/new_relic/agent/error_collector.rb +1 -1
  8. data/lib/new_relic/agent/instrumentation/active_merchant.rb +3 -1
  9. data/lib/new_relic/agent/instrumentation/active_record.rb +137 -0
  10. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +24 -5
  11. data/lib/new_relic/agent/instrumentation/data_mapper.rb +4 -36
  12. data/lib/new_relic/agent/instrumentation/metric_frame.rb +24 -3
  13. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +3 -2
  14. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +88 -30
  16. data/lib/new_relic/agent/instrumentation/sinatra.rb +40 -20
  17. data/lib/new_relic/agent/samplers/memory_sampler.rb +5 -6
  18. data/lib/new_relic/agent/sql_sampler.rb +35 -16
  19. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +123 -0
  20. data/lib/new_relic/agent/stats_engine/samplers.rb +1 -1
  21. data/lib/new_relic/agent/stats_engine/transactions.rb +2 -85
  22. data/lib/new_relic/agent/stats_engine.rb +1 -0
  23. data/lib/new_relic/agent/transaction_info.rb +74 -0
  24. data/lib/new_relic/agent/transaction_sample_builder.rb +17 -3
  25. data/lib/new_relic/agent/transaction_sampler.rb +86 -15
  26. data/lib/new_relic/agent/worker_loop.rb +1 -1
  27. data/lib/new_relic/agent.rb +15 -2
  28. data/lib/new_relic/collection_helper.rb +8 -6
  29. data/lib/new_relic/command.rb +1 -1
  30. data/lib/new_relic/commands/deployments.rb +1 -1
  31. data/lib/new_relic/control/configuration.rb +6 -2
  32. data/lib/new_relic/control/frameworks/merb.rb +1 -1
  33. data/lib/new_relic/control/frameworks/rails.rb +5 -5
  34. data/lib/new_relic/control/frameworks/rails3.rb +2 -2
  35. data/lib/new_relic/control/instance_methods.rb +3 -3
  36. data/lib/new_relic/control/instrumentation.rb +1 -1
  37. data/lib/new_relic/control/server_methods.rb +2 -2
  38. data/lib/new_relic/data_serialization.rb +10 -16
  39. data/lib/new_relic/delayed_job_injection.rb +6 -1
  40. data/lib/new_relic/language_support.rb +11 -7
  41. data/lib/new_relic/local_environment.rb +24 -10
  42. data/lib/new_relic/metric_spec.rb +7 -6
  43. data/lib/new_relic/noticed_error.rb +6 -1
  44. data/lib/new_relic/rack/browser_monitoring.rb +21 -13
  45. data/lib/new_relic/rack/developer_mode.rb +2 -2
  46. data/lib/new_relic/recipes.rb +8 -4
  47. data/lib/new_relic/stats.rb +0 -53
  48. data/lib/new_relic/transaction_sample/segment.rb +2 -0
  49. data/lib/new_relic/transaction_sample.rb +39 -23
  50. data/lib/new_relic/version.rb +3 -3
  51. data/test/active_record_fixtures.rb +3 -3
  52. data/test/fixtures/proc_cpuinfo.txt +575 -0
  53. data/test/new_relic/agent/agent/connect_test.rb +4 -11
  54. data/test/new_relic/agent/agent_test.rb +1 -0
  55. data/test/new_relic/agent/agent_test_controller_test.rb +20 -1
  56. data/test/new_relic/agent/beacon_configuration_test.rb +10 -7
  57. data/test/new_relic/agent/browser_monitoring_test.rb +90 -45
  58. data/test/new_relic/agent/database_test.rb +34 -47
  59. data/test/new_relic/agent/error_collector_test.rb +32 -15
  60. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +56 -18
  61. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +0 -2
  62. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +0 -1
  63. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +3 -3
  64. data/test/new_relic/agent/instrumentation/queue_time_test.rb +6 -11
  65. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +1 -1
  66. data/test/new_relic/agent/method_tracer_test.rb +2 -2
  67. data/test/new_relic/agent/rpm_agent_test.rb +1 -1
  68. data/test/new_relic/agent/sql_sampler_test.rb +48 -16
  69. data/test/new_relic/agent/stats_engine_test.rb +41 -6
  70. data/test/new_relic/agent/transaction_info_test.rb +13 -0
  71. data/test/new_relic/agent/transaction_sample_builder_test.rb +19 -3
  72. data/test/new_relic/agent/transaction_sampler_test.rb +49 -37
  73. data/test/new_relic/agent/worker_loop_test.rb +1 -1
  74. data/test/new_relic/agent_test.rb +12 -0
  75. data/test/new_relic/control/configuration_test.rb +12 -0
  76. data/test/new_relic/control_test.rb +2 -0
  77. data/test/new_relic/data_serialization_test.rb +12 -12
  78. data/test/new_relic/local_environment_test.rb +14 -1
  79. data/test/new_relic/metric_parser/metric_parser_test.rb +11 -0
  80. data/test/new_relic/rack/browser_monitoring_test.rb +81 -23
  81. data/test/new_relic/rack/developer_mode_test.rb +31 -0
  82. data/test/new_relic/stats_test.rb +0 -15
  83. data/test/new_relic/transaction_sample_test.rb +13 -0
  84. data/test/script/build_test_gem.sh +51 -0
  85. data/test/script/ci.sh +94 -0
  86. data/test/script/ci_bench.sh +52 -0
  87. data/test/test_helper.rb +1 -0
  88. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +5 -0
  89. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +17 -4
  90. metadata +25 -19
  91. data/dolores_rpm-3.2.0.2.gem +0 -0
  92. data/dolores_rpm-3.2.0.5.gem +0 -0
  93. data/dolores_rpm-3.3.4.fork.gem +0 -0
  94. data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +0 -115
  95. data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +0 -122
@@ -19,7 +19,8 @@ class NewRelic::Agent::BeaconConfigurationTest < Test::Unit::TestCase
19
19
  assert_equal('a browser monitoring key', bc.browser_monitoring_key)
20
20
  assert_equal('an application id', bc.application_id)
21
21
  assert_equal('a beacon', bc.beacon)
22
- assert_equal(117, bc.browser_timing_header.size, "should output the javascript with all the data available")
22
+ s = "<script type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>"
23
+ assert_equal(s, bc.browser_timing_header)
23
24
  end
24
25
 
25
26
  def test_license_bytes_nil
@@ -81,22 +82,24 @@ class NewRelic::Agent::BeaconConfigurationTest < Test::Unit::TestCase
81
82
  def test_build_load_file_js_load_episodes_file_false
82
83
  connect_data = {'rum.load_episodes_file' => false}
83
84
  bc = NewRelic::Agent::BeaconConfiguration.new(connect_data)
84
- assert_equal(160, bc.build_load_file_js(connect_data).size,
85
- "should include timing footer but not rum.js load")
85
+ s = "if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\n"
86
+ assert_equal(s, bc.build_load_file_js(connect_data))
86
87
  end
87
88
 
88
89
  def test_build_load_file_js_load_episodes_file_missing
89
90
  connect_data = {}
90
91
  bc = NewRelic::Agent::BeaconConfiguration.new(connect_data)
91
- assert_equal(278, bc.build_load_file_js(connect_data).size,
92
- "should output the javascript when there is no configuration")
92
+ s = "if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\n"
93
+
94
+ assert_equal(s, bc.build_load_file_js(connect_data))
93
95
  end
94
96
 
95
97
  def test_build_load_file_js_load_episodes_file_present
96
98
  connect_data = {'rum.load_episodes_file' => true}
97
99
  bc = NewRelic::Agent::BeaconConfiguration.new(connect_data)
98
- assert_equal(278, bc.build_load_file_js(connect_data).size,
99
- "should output the javascript when rum.load_episodes_file is true")
100
+ s = "if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\n"
101
+
102
+ assert_equal(s, bc.build_load_file_js(connect_data))
100
103
  end
101
104
 
102
105
  def test_build_load_file_js_load_episodes_file_with_episodes_url
@@ -4,22 +4,41 @@ require "new_relic/agent/browser_monitoring"
4
4
 
5
5
  class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
6
6
  include NewRelic::Agent::BrowserMonitoring
7
-
7
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
8
+
8
9
  def setup
9
10
  NewRelic::Agent.manual_start
10
11
  @browser_monitoring_key = "fred"
11
12
  @episodes_file = "this_is_my_file"
12
13
  NewRelic::Agent.instance.instance_eval do
13
- @beacon_configuration = NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => true, "browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"})
14
+ @beacon_configuration = NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => true, "browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file", 'rum.jsonp' => true})
14
15
  end
15
- Thread.current[:newrelic_most_recent_transaction] = "MyCoolTransaction"
16
+ Thread.current[:last_metric_frame] = nil
17
+ NewRelic::Agent::TransactionInfo.clear
16
18
  end
17
19
 
18
20
  def teardown
19
21
  mocha_teardown
20
- Thread.current[:newrelic_start_time] = nil
21
- Thread.current[:newrelic_metric_frame] = nil
22
- Thread.current[:newrelic_most_recent_transaction] = nil
22
+ end
23
+
24
+ def test_browser_monitoring_start_time_is_reset_each_request_when_auto_instrument_is_disabled
25
+ controller = Object.new
26
+ def controller.perform_action_without_newrelic_trace(method, options={});
27
+ # noop; instrument me
28
+ end
29
+ def controller.newrelic_metric_path; "foo"; end
30
+ controller.extend ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
31
+ controller.extend ::NewRelic::Agent::BrowserMonitoring
32
+ NewRelic::Control.instance['browser_monitoring'] = { 'auto_instrument' => false }
33
+
34
+ controller.perform_action_with_newrelic_trace(:index)
35
+ first_request_start_time = controller.send(:browser_monitoring_start_time)
36
+ controller.perform_action_with_newrelic_trace(:index)
37
+ second_request_start_time = controller.send(:browser_monitoring_start_time)
38
+
39
+ # assert that these aren't the same time object
40
+ # the start time should be reinitialized each request to the controller
41
+ assert !(first_request_start_time.equal? second_request_start_time)
23
42
  end
24
43
 
25
44
  def test_browser_timing_header_with_no_beacon_configuration
@@ -65,8 +84,6 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
65
84
  browser_timing_header
66
85
  NewRelic::Control.instance.expects(:license_key).returns("a" * 13)
67
86
 
68
- Thread.current[:newrelic_start_time] = Time.now
69
-
70
87
  footer = browser_timing_footer
71
88
  snippet = '<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {
72
89
  NREUMQ.push(["load",new Date().getTime()]);
@@ -74,11 +91,6 @@ var e=document.createElement("script");'
74
91
  assert footer.include?(snippet), "Expected footer to include snippet: #{snippet}, but instead was #{footer}"
75
92
  end
76
93
 
77
- def test_browser_timing_footer_without_calling_header
78
- Thread.current[:newrelic_start_time] = nil
79
- assert_equal "", browser_timing_footer
80
- end
81
-
82
94
  def test_browser_timing_footer_with_no_browser_key_rum_enabled
83
95
  browser_timing_header
84
96
  NewRelic::Agent.instance.expects(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new({"rum.enabled" => true, "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
@@ -95,7 +107,6 @@ var e=document.createElement("script");'
95
107
 
96
108
  def test_browser_timing_footer_with_rum_enabled_not_specified
97
109
  browser_timing_header
98
- Thread.current[:newrelic_start_time] = Time.now
99
110
 
100
111
  license_bytes = [];
101
112
  ("a" * 13).each_byte {|byte| license_bytes << byte}
@@ -118,14 +129,6 @@ var e=document.createElement("script");'
118
129
  assert_equal "", footer
119
130
  end
120
131
 
121
- def test_browser_timing_footer_with_no_start_time
122
- browser_timing_header
123
- Thread.current[:newrelic_start_time] = nil
124
- NewRelic::Agent.instance.expects(:beacon_configuration).returns( NewRelic::Agent::BeaconConfiguration.new({"browser_key" => "browserKey", "application_id" => "apId", "beacon"=>"beacon", "episodes_url"=>"this_is_my_file"}))
125
- footer = browser_timing_footer
126
- assert_equal('', footer)
127
- end
128
-
129
132
 
130
133
  def test_browser_timing_footer_disable_all_tracing
131
134
  browser_timing_header
@@ -157,37 +160,62 @@ var e=document.createElement("script");'
157
160
 
158
161
  def test_generate_footer_js_null_case
159
162
  self.expects(:browser_monitoring_start_time).returns(nil)
160
- assert_equal('', generate_footer_js, "should not send javascript when there is no start time")
163
+ assert_equal('', generate_footer_js(NewRelic::Agent.instance.beacon_configuration), "should not send javascript when there is no start time")
161
164
  end
162
-
165
+
163
166
  def test_generate_footer_js_with_start_time
164
167
  self.expects(:browser_monitoring_start_time).returns(Time.at(100))
165
168
  fake_bc = mock('beacon configuration')
166
169
  fake_bc.expects(:application_id).returns(1)
167
170
  fake_bc.expects(:beacon).returns('beacon')
168
171
  fake_bc.expects(:browser_monitoring_key).returns('a' * 40)
169
- NewRelic::Agent.instance.expects(:beacon_configuration).returns(fake_bc)
170
- self.expects(:footer_js_string).with('beacon', 'a' * 40, 1).returns('footer js')
171
- assert_equal('footer js', generate_footer_js, 'should generate and return the footer JS when there is a start time')
172
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns(fake_bc)
173
+ self.expects(:footer_js_string).with(NewRelic::Agent.instance.beacon_configuration, 'beacon', 'a' * 40, 1).returns('footer js')
174
+ assert_equal('footer js', generate_footer_js(NewRelic::Agent.instance.beacon_configuration), 'should generate and return the footer JS when there is a start time')
172
175
  end
173
176
 
174
177
  def test_browser_monitoring_transaction_name_basic
175
- Thread.current[:newrelic_most_recent_transaction] = 'a transaction name'
178
+ mock = mock('transaction sample')
179
+ NewRelic::Agent::TransactionInfo.set(mock)
180
+ mock.stubs(:transaction_name).returns('a transaction name')
181
+
176
182
  assert_equal('a transaction name', browser_monitoring_transaction_name, "should take the value from the thread local")
177
183
  end
178
184
 
179
185
  def test_browser_monitoring_transaction_name_empty
180
- Thread.current[:newrelic_most_recent_transaction] = ''
186
+ mock = mock('transaction sample')
187
+ NewRelic::Agent::TransactionInfo.set(mock)
188
+
189
+ mock.stubs(:transaction_name).returns('')
181
190
  assert_equal('', browser_monitoring_transaction_name, "should take the value even when it is empty")
182
191
  end
183
192
 
184
193
  def test_browser_monitoring_transaction_name_nil
185
- Thread.current[:newrelic_most_recent_transaction] = nil
186
- assert_equal('<unknown>', browser_monitoring_transaction_name, "should fill in a default when it is nil")
194
+ assert_equal('(unknown)', browser_monitoring_transaction_name, "should fill in a default when it is nil")
187
195
  end
196
+
197
+ def test_browser_monitoring_transaction_name_when_tt_disabled
198
+ @sampler = NewRelic::Agent.instance.transaction_sampler
199
+ @sampler.disable
188
200
 
201
+ perform_action_with_newrelic_trace(:name => 'disabled_transactions') do
202
+ self.class.inspect
203
+ end
204
+
205
+ assert_match(/disabled_transactions/, browser_monitoring_transaction_name,
206
+ "should name transaction when transaction tracing disabled")
207
+ ensure
208
+ @sampler.enable
209
+ end
210
+
211
+
189
212
  def test_browser_monitoring_start_time
190
- Thread.current[:newrelic_start_time] = Time.at(100)
213
+ mock = mock('transaction info')
214
+
215
+ NewRelic::Agent::TransactionInfo.set(mock)
216
+
217
+ mock.stubs(:start_time).returns(Time.at(100))
218
+ mock.stubs(:guid).returns('ABC')
191
219
  assert_equal(Time.at(100), browser_monitoring_start_time, "should take the value from the thread local")
192
220
  end
193
221
 
@@ -205,22 +233,24 @@ var e=document.createElement("script");'
205
233
  end
206
234
 
207
235
  def test_browser_monitoring_queue_time_nil
208
- Thread.current[:newrelic_queue_time] = nil
209
236
  assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is no queue time')
210
237
  end
211
238
 
212
239
  def test_browser_monitoring_queue_time_zero
213
- Thread.current[:newrelic_queue_time] = 0.0
240
+ frame = Thread.current[:last_metric_frame] = mock('metric frame')
241
+ frame.expects(:queue_time).returns(0.0)
214
242
  assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is zero queue time')
215
243
  end
216
244
 
217
245
  def test_browser_monitoring_queue_time_ducks
218
- Thread.current[:newrelic_queue_time] = 'a duck'
246
+ frame = Thread.current[:last_metric_frame] = mock('metric frame')
247
+ frame.expects(:queue_time).returns('a duck')
219
248
  assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is an incorrect queue time')
220
249
  end
221
250
 
222
251
  def test_browser_monitoring_queue_time_nonzero
223
- Thread.current[:newrelic_queue_time] = 3.00002
252
+ frame = Thread.current[:last_metric_frame] = mock('metric frame')
253
+ frame.expects(:queue_time).returns(3.00002)
224
254
  assert_equal(3000, browser_monitoring_queue_time, 'should return a rounded time')
225
255
  end
226
256
 
@@ -229,16 +259,31 @@ var e=document.createElement("script");'
229
259
  license_key = ''
230
260
  application_id = 1
231
261
 
232
- Thread.current[:newrelic_queue_time] = nil
233
262
  # mocking this because JRuby thinks that Time.now - Time.now
234
263
  # always takes at least 1ms
235
264
  self.expects(:browser_monitoring_app_time).returns(0)
236
- Thread.current[:newrelic_most_recent_transaction] = 'most recent transaction'
237
-
238
- self.expects(:obfuscate).with('most recent transaction').returns('most recent transaction')
239
-
240
- value = footer_js_string(beacon, license_key, application_id)
241
- assert_equal("<script type=\"text/javascript\">if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"this_is_my_file\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push([\"nrf2\",\"\",\"\",1,\"most recent transaction\",0,0,new Date().getTime()])</script>", value, "should return the javascript given some default values")
265
+ frame = Thread.current[:last_metric_frame] = mock('metric frame')
266
+ user_attributes = {:user => "user", :account => "account", :product => "product"}
267
+ frame.expects(:user_attributes).returns(user_attributes).at_least_once
268
+ frame.expects(:queue_time).returns(0)
269
+
270
+ sample = mock('transaction info')
271
+ NewRelic::Agent::TransactionInfo.set(sample)
272
+
273
+ sample.stubs(:start_time).returns(Time.at(100))
274
+ sample.stubs(:guid).returns('ABC')
275
+ sample.stubs(:transaction_name).returns('most recent transaction')
276
+ sample.stubs(:include_guid?).returns(true)
277
+ sample.stubs(:duration).returns(12.0)
278
+ sample.stubs(:token).returns('0123456789ABCDEF')
279
+
280
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'most recent transaction').returns('most recent transaction')
281
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'user').returns('user')
282
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'account').returns('account')
283
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'product').returns('product')
284
+
285
+ value = footer_js_string(NewRelic::Agent.instance.beacon_configuration, beacon, license_key, application_id)
286
+ assert_equal("<script type=\"text/javascript\">if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"this_is_my_file\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push([\"nrfj\",\"\",\"\",1,\"most recent transaction\",0,0,new Date().getTime(),\"ABC\",\"0123456789ABCDEF\",\"user\",\"account\",\"product\"])</script>", value, "should return the javascript given some default values")
242
287
  end
243
288
 
244
289
  def test_html_safe_if_needed_unsafed
@@ -264,7 +309,7 @@ var e=document.createElement("script");'
264
309
  text = 'a happy piece of small text'
265
310
  key = (1..40).to_a
266
311
  NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
267
- output = obfuscate(text)
312
+ output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
268
313
  assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1', output, "should output obfuscated text")
269
314
  end
270
315
 
@@ -272,7 +317,7 @@ var e=document.createElement("script");'
272
317
  text = 'a happy piece of small text' * 5
273
318
  key = (1..40).to_a
274
319
  NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
275
- output = obfuscate(text)
320
+ output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
276
321
  assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1YyNsZHZ3cSl6YmluZCJsYiV1amllZit4aHl2YiRtZ3d4cCp7ZWhiZyNrYyZ0ZWhmZyx5ZHp3ZSVuZnh5cyt8ZGRhZiRqYCd7ZGtnYC11Z3twZCZvaXl6cix9aGdgYSVpYSh6Z2pgYSF2Znxx', output, "should output obfuscated text")
277
322
  end
278
323
  end
@@ -74,7 +74,7 @@ class NewRelic::Agent::DatabaseTest < Test::Unit::TestCase
74
74
  end
75
75
 
76
76
  def test_handle_exception_in_explain
77
- fake_error = Exception.new('a message')
77
+ fake_error = StandardError.new('a message')
78
78
  NewRelic::Control.instance.log.expects(:error).with('Error getting query plan: a message')
79
79
  # backtrace can be basically any string, just should get logged
80
80
  NewRelic::Control.instance.log.expects(:debug).with(instance_of(String))
@@ -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 test_sql_normalization
88
- # basic statement
89
- assert_equal "INSERT INTO X values(?,?, ? , ?)",
90
- NewRelic::Agent::Database.obfuscate_sql("INSERT INTO X values('test',0, 1 , 2)")
91
-
92
- # escaped literals
93
- assert_equal "INSERT INTO X values(?, ?,?, ? , ?)",
94
- NewRelic::Agent::Database.obfuscate_sql("INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son')")
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 test_sql_normalization__single_quotes
115
- assert_equal "INSERT ? into table",
116
- NewRelic::Agent::Database.obfuscate_sql("INSERT 'this isn''t a real value' into table")
117
- assert_equal "INSERT ? into table",
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 test_sql_normalization__double_quotes
129
- assert_equal "INSERT ? into table",
130
- NewRelic::Agent::Database.obfuscate_sql(%q[INSERT "this isn't a real value" into table])
131
- assert_equal "INSERT ? into table",
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
@@ -3,12 +3,12 @@ ENV['SKIP_RAILS'] = 'true'
3
3
  require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
4
4
 
5
5
  class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
6
-
7
6
  def setup
8
7
  super
9
8
  @error_collector = NewRelic::Agent::ErrorCollector.new
10
9
  @error_collector.stubs(:enabled).returns(true)
11
10
  end
11
+
12
12
  def test_empty
13
13
  @error_collector.harvest_errors([])
14
14
  @error_collector.notice_error(nil, :metric=> 'path', :request_params => {:x => 'y'})
@@ -26,10 +26,10 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
26
26
  assert_equal '', err.params[:request_referer]
27
27
  assert_equal 'path', err.path
28
28
  assert_equal 'Error', err.exception_class
29
-
30
29
  end
30
+
31
31
  def test_simple
32
- @error_collector.notice_error(Exception.new("message"), :uri => '/myurl/', :metric => 'path', :referer => 'test_referer', :request_params => {:x => 'y'})
32
+ @error_collector.notice_error(StandardError.new("message"), :uri => '/myurl/', :metric => 'path', :referer => 'test_referer', :request_params => {:x => 'y'})
33
33
 
34
34
  old_errors = []
35
35
  errors = @error_collector.harvest_errors(old_errors)
@@ -42,7 +42,7 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
42
42
  assert err.params[:request_uri] == '/myurl/'
43
43
  assert err.params[:request_referer] == "test_referer"
44
44
  assert err.path == 'path'
45
- assert err.exception_class == 'Exception'
45
+ assert err.exception_class == 'StandardError'
46
46
 
47
47
  # the collector should now return an empty array since nothing
48
48
  # has been added since its last harvest
@@ -53,7 +53,7 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
53
53
  def test_long_message
54
54
  #yes, times 500. it's a 5000 byte string. Assuming strings are
55
55
  #still 1 byte / char.
56
- @error_collector.notice_error(Exception.new("1234567890" * 500), :uri => '/myurl/', :metric => 'path', :request_params => {:x => 'y'})
56
+ @error_collector.notice_error(StandardError.new("1234567890" * 500), :uri => '/myurl/', :metric => 'path', :request_params => {:x => 'y'})
57
57
 
58
58
  old_errors = []
59
59
  errors = @error_collector.harvest_errors(old_errors)
@@ -66,13 +66,13 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
66
66
  end
67
67
 
68
68
  def test_collect_failover
69
- @error_collector.notice_error(Exception.new("message"), :metric => 'first', :request_params => {:x => 'y'})
69
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'first', :request_params => {:x => 'y'})
70
70
 
71
71
  errors = @error_collector.harvest_errors([])
72
72
 
73
- @error_collector.notice_error(Exception.new("message"), :metric => 'second', :request_params => {:x => 'y'})
74
- @error_collector.notice_error(Exception.new("message"), :metric => 'path', :request_params => {:x => 'y'})
75
- @error_collector.notice_error(Exception.new("message"), :metric => 'last', :request_params => {:x => 'y'})
73
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'second', :request_params => {:x => 'y'})
74
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'path', :request_params => {:x => 'y'})
75
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'last', :request_params => {:x => 'y'})
76
76
 
77
77
  errors = @error_collector.harvest_errors(errors)
78
78
 
@@ -80,8 +80,8 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
80
80
  assert_equal 'first', errors.first.path
81
81
  assert_equal 'last', errors.last.path
82
82
 
83
- @error_collector.notice_error(Exception.new("message"), :metric => 'first', :request_params => {:x => 'y'})
84
- @error_collector.notice_error(Exception.new("message"), :metric => 'last', :request_params => {:x => 'y'})
83
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'first', :request_params => {:x => 'y'})
84
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'last', :request_params => {:x => 'y'})
85
85
 
86
86
  errors = @error_collector.harvest_errors(nil)
87
87
  assert_equal 2, errors.length
@@ -95,7 +95,7 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
95
95
 
96
96
  silence_stream(::STDOUT) do
97
97
  (max_q_length + 5).times do |n|
98
- @error_collector.notice_error(Exception.new("exception #{n}"), :metric => "path", :request_params => {:x => n})
98
+ @error_collector.notice_error(StandardError.new("exception #{n}"), :metric => "path", :request_params => {:x => n})
99
99
  end
100
100
  end
101
101
 
@@ -120,13 +120,13 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
120
120
  [1.1, '1.1'],
121
121
  ['hi', 'hi'],
122
122
  [:hi, :hi],
123
- [Exception.new("test"), "#<Exception>"],
123
+ [StandardError.new("test"), "#<StandardError>"],
124
124
  [TestClass.new, "#<NewRelic::Agent::ErrorCollectorTest::TestClass>"]
125
125
  ]
126
126
 
127
127
 
128
128
  types.each do |test|
129
- @error_collector.notice_error(Exception.new("message"), :metric => 'path', :request_params => {:x => test[0]})
129
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'path', :request_params => {:x => test[0]})
130
130
 
131
131
  assert_equal test[1], @error_collector.harvest_errors([])[0].params[:request_params][:x]
132
132
  end
@@ -148,13 +148,30 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
148
148
  @error_collector.ignore_error_filter &wrapped_filter_proc
149
149
 
150
150
  @error_collector.notice_error(IOError.new("message"), :metric => 'path', :request_params => {:x => 'y'})
151
- @error_collector.notice_error(Exception.new("message"), :metric => 'path', :request_params => {:x => 'y'})
151
+ @error_collector.notice_error(StandardError.new("message"), :metric => 'path', :request_params => {:x => 'y'})
152
152
 
153
153
  errors = @error_collector.harvest_errors([])
154
154
 
155
155
  assert_equal 1, errors.length
156
156
  end
157
157
 
158
+ def test_obfuscates_error_messages_when_high_security_is_set
159
+ NewRelic::Control.instance['high_security'] = true
160
+
161
+ @error_collector.notice_error(StandardError.new("YO SQL BAD: serect * flom test where foo = 'bar'"))
162
+ @error_collector.notice_error(StandardError.new("YO SQL BAD: serect * flom test where foo in (1,2,3,4,5)"))
163
+
164
+ old_errors = []
165
+ errors = @error_collector.harvest_errors([])
166
+
167
+ assert_equal('YO SQL BAD: serect * flom test where foo = ?',
168
+ errors[0].message)
169
+ assert_equal('YO SQL BAD: serect * flom test where foo in (?,?,?,?,?)',
170
+ errors[1].message)
171
+
172
+ NewRelic::Control.instance['high_security'] = nil
173
+ end
174
+
158
175
  private
159
176
 
160
177
  def wrapped_filter_proc