newrelic_rpm 3.9.9.275 → 3.10.0.279

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +51 -0
  3. data/config.dot +0 -3
  4. data/lib/new_relic/agent.rb +7 -5
  5. data/lib/new_relic/agent/agent.rb +4 -4
  6. data/lib/new_relic/agent/instrumentation/active_job.rb +5 -8
  7. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +17 -34
  8. data/lib/new_relic/agent/instrumentation/grape.rb +60 -23
  9. data/lib/new_relic/agent/instrumentation/merb/controller.rb +10 -2
  10. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +33 -21
  11. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +7 -3
  12. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +0 -9
  13. data/lib/new_relic/agent/instrumentation/sinatra.rb +9 -12
  14. data/lib/new_relic/agent/javascript_instrumentor.rb +1 -0
  15. data/lib/new_relic/agent/new_relic_service.rb +9 -6
  16. data/lib/new_relic/agent/parameter_filtering.rb +37 -0
  17. data/lib/new_relic/agent/supported_versions.rb +7 -0
  18. data/lib/new_relic/agent/traced_method_stack.rb +1 -1
  19. data/lib/new_relic/agent/transaction.rb +182 -186
  20. data/lib/new_relic/agent/vm/rubinius_vm.rb +93 -3
  21. data/lib/new_relic/control/frameworks/rails.rb +1 -0
  22. data/lib/new_relic/rack/agent_hooks.rb +15 -23
  23. data/lib/new_relic/version.rb +2 -2
  24. data/newrelic_rpm.gemspec +12 -5
  25. data/test/agent_helper.rb +26 -14
  26. data/test/multiverse/lib/multiverse/suite.rb +1 -5
  27. data/test/multiverse/suites/activemerchant/Envfile +4 -1
  28. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +2 -12
  29. data/test/multiverse/suites/agent_only/logging_test.rb +1 -1
  30. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +4 -0
  31. data/test/multiverse/suites/agent_only/synthetics_test.rb +1 -8
  32. data/test/multiverse/suites/agent_only/testing_app.rb +1 -7
  33. data/test/multiverse/suites/agent_only/xray_sessions_test.rb +11 -11
  34. data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +4 -0
  35. data/test/multiverse/suites/grape/Envfile +1 -3
  36. data/test/multiverse/suites/grape/grape_test.rb +87 -6
  37. data/test/multiverse/suites/grape/grape_test_api.rb +5 -0
  38. data/test/multiverse/suites/grape/grape_versioning_test.rb +67 -0
  39. data/test/multiverse/suites/grape/grape_versioning_test_api.rb +72 -0
  40. data/test/multiverse/suites/rack/example_app.rb +31 -1
  41. data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +11 -10
  42. data/test/multiverse/suites/rack/rack_cascade_test.rb +46 -0
  43. data/test/multiverse/suites/rack/rack_parameter_filtering_test.rb +40 -0
  44. data/test/multiverse/suites/rails/Envfile +8 -0
  45. data/test/multiverse/suites/rails/activejob_test.rb +16 -0
  46. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +4 -2
  47. data/test/multiverse/suites/rails/parameter_capture_test.rb +49 -0
  48. data/test/multiverse/suites/rails/rails3_app/app_rails3_plus.rb +12 -1
  49. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +4 -0
  50. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +4 -0
  51. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +11 -0
  52. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +0 -58
  53. data/test/new_relic/agent/instrumentation/middleware_proxy_test.rb +49 -0
  54. data/test/new_relic/agent/instrumentation/middleware_tracing_test.rb +26 -14
  55. data/test/new_relic/agent/parameter_filtering_test.rb +39 -0
  56. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +1 -1
  57. data/test/new_relic/agent/transaction_test.rb +106 -2
  58. data/test/new_relic/agent/vm/rubinius_vm_test.rb +38 -37
  59. data/test/new_relic/agent_test.rb +8 -3
  60. data/test/new_relic/filtering_test_app.rb +18 -0
  61. data/test/new_relic/latest_changes_test.rb +1 -1
  62. data/test/new_relic/rack/browser_monitoring_test.rb +4 -4
  63. data/test/performance/lib/performance/instrumentation/gc_stats.rb +6 -4
  64. data/test/performance/lib/performance/platform.rb +1 -0
  65. data/test/performance/suites/thread_profiling.rb +12 -0
  66. metadata +38 -15
  67. metadata.gz.sig +2 -1
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'multiverse_helpers'
6
+ require File.join(File.dirname(__FILE__), 'example_app')
7
+ require 'new_relic/rack/browser_monitoring'
8
+ require 'new_relic/rack/agent_hooks'
9
+ require 'new_relic/rack/error_collector'
10
+
11
+ if NewRelic::Agent::Instrumentation::RackHelpers.rack_version_supported?
12
+
13
+ class RackCascadeTest < Minitest::Test
14
+ include MultiverseHelpers
15
+
16
+ setup_and_teardown_agent(
17
+ :beacon => 'beacon',
18
+ :browser_key => 'browserKey',
19
+ :js_agent_loader => 'loader',
20
+ :application_id => '5',
21
+ :'rum.enabled' => true,
22
+ :license_key => 'a' * 40
23
+ )
24
+
25
+ include Rack::Test::Methods
26
+
27
+ def app
28
+ Rack::Builder.app do
29
+ use NewRelic::Rack::AgentHooks
30
+ use NewRelic::Rack::BrowserMonitoring
31
+ use ResponseCodeMiddleware
32
+ run Rack::Cascade.new([FirstCascadeExampleApp.new, SecondCascadeExampleApp.new])
33
+ end
34
+ end
35
+
36
+ def test_insert_js_does_not_fire_for_rack_cascade_404_responses
37
+ rsp = get '/', { 'body' => '<html><head></head><body></body></html>', 'override-response-code' => 404 }
38
+ refute(rsp.body.include?('script'), "\nExpected\n---\n#{rsp.body}\n---\nnot to include 'script'.")
39
+ end
40
+
41
+ def test_rack_cascade_transactions_are_named_for_the_last_app
42
+ rsp = get '/cascade'
43
+ assert_metrics_recorded('Controller/SecondCascadeExampleApp/call')
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'multiverse_helpers'
6
+ require 'filtering_test_app'
7
+
8
+ if NewRelic::Agent::Instrumentation::RackHelpers.rack_version_supported?
9
+
10
+ class RackParameterFilteringTest < Minitest::Test
11
+ include MultiverseHelpers
12
+
13
+ setup_and_teardown_agent
14
+
15
+ include Rack::Test::Methods
16
+
17
+ def app
18
+ Rack::Builder.app { run FilteringTestApp.new }
19
+ end
20
+
21
+ def test_file_upload_params_are_filtered
22
+ with_config(:capture_params => true) do
23
+ params = {
24
+ :title => "blah",
25
+ :file => Rack::Test::UploadedFile.new(__FILE__, 'text/plain')
26
+ }
27
+ post '/', params
28
+ assert_equal({"title" => "blah", "file" => "[FILE]"}, last_transaction_trace_request_params)
29
+ end
30
+ end
31
+
32
+ def test_apply_filters_returns_params_when_rails_is_not_present
33
+ with_config(:capture_params => true) do
34
+ params = {"name" => "name", "password" => "mypass"}
35
+ post '/', params
36
+ assert_equal params, last_transaction_trace_request_params
37
+ end
38
+ end
39
+ end
40
+ end
@@ -27,6 +27,13 @@ gemfile <<-RB
27
27
  gem 'minitest_tu_shim', :require => false
28
28
  RB
29
29
 
30
+ gemfile <<-RB
31
+ gem 'rails', '~>3.2.20'
32
+ gem 'sinatra', '~> 1.4.5'
33
+ gem 'haml', '4.0.2' # Getting load issues with haml 4.0.3
34
+ gem 'minitest_tu_shim', :require => false
35
+ RB
36
+
30
37
  gemfile <<-RB
31
38
  gem 'rails', '~>3.1.12'
32
39
  gem 'haml', '4.0.2' # Getting load issues with haml 4.0.3
@@ -46,5 +53,6 @@ if RUBY_VERSION <= '1.9.3' && (!defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby')
46
53
  gem 'haml', '~> 3.1.0' # last haml version that supports Rails 2
47
54
  gem 'minitest_tu_shim', :require => false
48
55
  gem 'sqlite3'
56
+ gem 'i18n', '0.6.11'
49
57
  RB
50
58
  end
@@ -40,6 +40,13 @@ class MyJobWithParams < ActiveJob::Base
40
40
  end
41
41
  end
42
42
 
43
+ class MyFailure < ActiveJob::Base
44
+
45
+ def perform
46
+ raise ArgumentError.new("No it isn't!")
47
+ end
48
+ end
49
+
43
50
  class ActiveJobTest < Minitest::Test
44
51
 
45
52
  include MultiverseHelpers
@@ -51,6 +58,7 @@ class ActiveJobTest < Minitest::Test
51
58
 
52
59
  def after_teardown
53
60
  unless passed?
61
+ puts "\nEmitting log from failure: #{self.name}"
54
62
  @log.rewind
55
63
  puts @log.read
56
64
  end
@@ -132,6 +140,14 @@ class ActiveJobTest < Minitest::Test
132
140
  MyJobWithParams.perform_later("1", "2")
133
141
  assert_equal(["1", "2"], MyJobWithParams.last_params)
134
142
  end
143
+
144
+ def test_captures_errors
145
+ # Because we're processing inline, we get the error raised here
146
+ assert_raises ArgumentError do
147
+ MyFailure.perform_later
148
+ end
149
+ assert_metrics_recorded(["Errors/all"])
150
+ end
135
151
  end
136
152
 
137
153
  end
@@ -4,9 +4,11 @@
4
4
 
5
5
  require './app'
6
6
 
7
- # GC instrumentation only works with REE or MRI >= 1.9.2
7
+ # These tests only return consistent results for REE or MRI >= 1.9.2
8
8
  if NewRelic::LanguageSupport.ree? ||
9
- (RUBY_VERSION >= '1.9.2' && !NewRelic::LanguageSupport.jruby?)
9
+ (RUBY_VERSION >= '1.9.2' &&
10
+ !NewRelic::LanguageSupport.jruby? &&
11
+ !NewRelic::LanguageSupport.rubinius?)
10
12
 
11
13
  class GcController < ApplicationController
12
14
  def gc_action
@@ -166,4 +166,53 @@ class ParameterCaptureTest < RailsMultiverseTest
166
166
  end
167
167
  assert_equal('/parameter_capture/sql', last_sql_trace.url)
168
168
  end
169
+
170
+ if Rails::VERSION::MAJOR > 2
171
+ def test_params_tts_should_be_filtered_when_serviced_by_rack_app
172
+ params = {"secret" => "shhhhhhh", "name" => "name"}
173
+ with_config(:capture_params => true) do
174
+ post '/filtering_test/', params
175
+ end
176
+ expected = {"secret" => "[FILTERED]", "name" => "name"}
177
+ assert_equal expected, last_transaction_trace_request_params
178
+ end
179
+
180
+ def test_params_on_errors_should_be_filtered_when_serviced_by_rack_app
181
+ params = {"secret" => "shhhhhhh", "name" => "name"}
182
+ with_config(:capture_params => true) do
183
+ post '/filtering_test?raise=1', params
184
+ end
185
+ expected = {"secret" => "[FILTERED]", "name" => "name", "raise" => "1"}
186
+ assert_equal expected, last_traced_error_request_params
187
+ end
188
+
189
+ def test_parameter_filtering_should_not_mutate_argument
190
+ input = { "foo" => "bar", "secret" => "baz" }
191
+ env = { "action_dispatch.parameter_filter" => ["secret"] }
192
+ filtered = NewRelic::Agent::ParameterFiltering.apply_filters(env, input)
193
+
194
+ assert_equal({ "foo" => "bar", "secret" => "[FILTERED]" }, filtered)
195
+ assert_equal({ "foo" => "bar", "secret" => "baz" }, input)
196
+ end
197
+ end
198
+
199
+ if Rails::VERSION::MAJOR > 2 && defined?(Sinatra)
200
+ def test_params_tts_should_be_filtered_when_serviced_by_sinatra_app
201
+ params = {"secret" => "shhhhhhh", "name" => "name"}
202
+ with_config(:capture_params => true) do
203
+ get '/sinatra_app/', params
204
+ end
205
+ expected = {"secret" => "[FILTERED]", "name" => "name"}
206
+ assert_equal expected, last_transaction_trace_request_params
207
+ end
208
+
209
+ def test_params_on_errors_should_be_filtered_when_serviced_by_sinatra_app
210
+ params = {"secret" => "shhhhhhh", "name" => "name"}
211
+ with_config(:capture_params => true) do
212
+ get '/sinatra_app?raise=1', params
213
+ end
214
+ expected = {"secret" => "[FILTERED]", "name" => "name", "raise" => "1"}
215
+ assert_equal expected, last_traced_error_request_params
216
+ end
217
+ end
169
218
  end
@@ -5,6 +5,7 @@
5
5
  require 'action_controller/railtie'
6
6
  require 'active_model'
7
7
  require 'rails/test_help'
8
+ require 'filtering_test_app'
8
9
 
9
10
  # We define our single Rails application here, one time, upon the first inclusion
10
11
  # Tests should feel free to define their own Controllers locally, but if they
@@ -33,7 +34,6 @@ if !defined?(MyApp)
33
34
  @name = 'InstanceMiddleware'
34
35
  end
35
36
 
36
- # Yes, this is nuts. See the comment above initialize_with_new_relic_trace.
37
37
  def new(app)
38
38
  @app = app
39
39
  self
@@ -46,6 +46,15 @@ if !defined?(MyApp)
46
46
  end
47
47
  end
48
48
 
49
+ if defined?(Sinatra)
50
+ class SinatraTestApp < Sinatra::Base
51
+ get '/' do
52
+ raise "Intentional error" if params["raise"]
53
+ "SinatraTestApp#index"
54
+ end
55
+ end
56
+ end
57
+
49
58
  class MyApp < Rails::Application
50
59
  # We need a secret token for session, cookies, etc.
51
60
  config.active_support.deprecation = :log
@@ -69,6 +78,8 @@ if !defined?(MyApp)
69
78
  :constraints => lambda do |_|
70
79
  raise ActionController::RoutingError.new('this is an uncaught routing error')
71
80
  end)
81
+ mount SinatraTestApp, :at => '/sinatra_app' if defined?(Sinatra)
82
+ post '/filtering_test' => FilteringTestApp.new
72
83
  get '/:controller(/:action(/:id))'
73
84
  end
74
85
 
@@ -84,6 +84,10 @@ get(/\/regex.*/) do
84
84
  "Yeah, regex's!"
85
85
  end
86
86
 
87
+ post '/files' do
88
+ "file uploaded"
89
+ end
90
+
87
91
  module Sinatra
88
92
  class Application < Base
89
93
  # Override to not accidentally start the app in at_exit handler
@@ -79,6 +79,10 @@ class SinatraModularTestApp < Sinatra::Base
79
79
  get(/\/regex.*/) do
80
80
  "Yeah, regex's!"
81
81
  end
82
+
83
+ post '/files' do
84
+ "file uploaded"
85
+ end
82
86
  end
83
87
 
84
88
  class SinatraModularTest < Minitest::Test
@@ -131,6 +131,17 @@ module SinatraTestCases
131
131
  get '/pass'
132
132
  end
133
133
 
134
+ def test_file_upload_params_are_filtered
135
+ with_config(:capture_params => true) do
136
+ params = {
137
+ :title => "blah",
138
+ :file => Rack::Test::UploadedFile.new(__FILE__, 'text/plain')
139
+ }
140
+ post '/files', params
141
+ assert_equal({"title" => "blah", "file" => "[FILE]"}, last_transaction_trace_request_params)
142
+ end
143
+ end
144
+
134
145
  def fail_on_second_params_call
135
146
  Sinatra::Request.any_instance.
136
147
  stubs(:params).returns({}).
@@ -51,17 +51,6 @@ module NewRelic::Agent::Instrumentation
51
51
  alias_method :perform_action, :perform_action_with_newrelic_trace
52
52
  end
53
53
 
54
- def test_non_block_form
55
- state = NewRelic::Agent::TransactionState.tl_get
56
- state.push_traced(false)
57
-
58
- object = TestNonBlockObject.new
59
- object.perform_action
60
- assert object.called
61
- ensure
62
- state.pop_traced if state
63
- end
64
-
65
54
  def setup
66
55
  NewRelic::Agent.drop_buffered_data
67
56
  @object = TestObject.new
@@ -275,14 +264,6 @@ module NewRelic::Agent::Instrumentation
275
264
  assert TestObject.already_added_transaction_tracer?(TestObject, with_method_name)
276
265
  end
277
266
 
278
- # ControllerInstrumentation historically was used to instrument Rails 2
279
- # controllers, and in this case is called without a block. In that case, and
280
- # that case *only*, we want to try to call params on the host object to
281
- # extract request params.
282
- #
283
- # In the more modern usage where it's called with a block we do *not* want to
284
- # call params on the host object. This is important because doing so could
285
- # actually crash in some cases.
286
267
  def test_should_not_call_params_on_host_if_called_with_block
287
268
  host_class = Class.new do
288
269
  include ControllerInstrumentation
@@ -304,45 +285,6 @@ module NewRelic::Agent::Instrumentation
304
285
  host.doit
305
286
  end
306
287
 
307
- def test_should_not_call_params_on_host_if_no_block_given_but_does_not_respond_to_params
308
- host_class = Class.new do
309
- include ControllerInstrumentation
310
-
311
- def doit
312
- perform_action_with_newrelic_trace
313
- end
314
-
315
- def perform_action_without_newrelic_trace; end
316
- end
317
-
318
- host = host_class.new
319
- refute host.respond_to?(:params)
320
- host.doit
321
- end
322
-
323
- def test_should_call_params_on_host_if_no_block_given_and_host_responds
324
- host_class = Class.new do
325
- include ControllerInstrumentation
326
-
327
- attr_reader :params_called
328
-
329
- def params
330
- @params_called = true
331
- {}
332
- end
333
-
334
- def doit
335
- perform_action_with_newrelic_trace
336
- end
337
-
338
- def perform_action_without_newrelic_trace; end
339
- end
340
-
341
- host = host_class.new
342
- host.doit
343
- assert host.params_called
344
- end
345
-
346
288
  class UserError < StandardError
347
289
  end
348
290
 
@@ -185,5 +185,54 @@ class NewRelic::Agent::Instrumentation::MiddlewareProxyTest < Minitest::Test
185
185
 
186
186
  assert_metrics_recorded('Controller/Rack/GreatClass/call')
187
187
  end
188
+
189
+ def test_should_emit_events_once
190
+ app = Proc.new { |env| [200, {}, ["nothing"]]}
191
+ middleware = Proc.new { |env| app.call(env) }
192
+ wrapped_app = NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true)
193
+ wrapped_middleware = NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(middleware, true)
194
+
195
+ before_call_count = 0
196
+ after_call_count = 0
197
+
198
+ NewRelic::Agent.instance.events.subscribe(:before_call) { before_call_count += 1 }
199
+ NewRelic::Agent.instance.events.subscribe(:after_call) { after_call_count += 1 }
200
+
201
+ result = wrapped_middleware.call({})
202
+ assert_equal 1, before_call_count
203
+ assert_equal 1, after_call_count
204
+ end
205
+
206
+ def test_before_call_should_receive_rack_env_hash
207
+ app = Proc.new { |env| [200, {}, ["nothing"]]}
208
+ wrapped_app = NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true)
209
+
210
+ original_env = {}
211
+ env_from_before_call = nil
212
+
213
+ NewRelic::Agent.instance.events.subscribe(:before_call) { |env| env_from_before_call = env }
214
+
215
+ wrapped_app.call(original_env)
216
+ assert_same original_env, env_from_before_call
217
+ end
218
+
219
+ def test_before_call_should_receive_rack_env_hash
220
+ app = Proc.new { |env| [200, {}, ["nothing"]] }
221
+ wrapped_app = NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true)
222
+
223
+ original_env = {}
224
+ env_from_after_call = nil
225
+ result_from_after_call = nil
226
+
227
+ NewRelic::Agent.instance.events.subscribe(:after_call) do |env, result|
228
+ env_from_after_call = env
229
+ result_from_after_call = result
230
+ end
231
+
232
+ result = wrapped_app.call(original_env)
233
+
234
+ assert_same original_env, env_from_after_call
235
+ assert_same result, result_from_after_call
236
+ end
188
237
  end
189
238
 
@@ -9,29 +9,41 @@ class NewRelic::Agent::Instrumentation::MiddlewareTracingTest < Minitest::Test
9
9
  class UserError < StandardError
10
10
  end
11
11
 
12
- def test_dont_block_errors_during_malfunctioning_transaction
13
- middleware_class = Class.new do
14
- include NewRelic::Agent::Instrumentation::MiddlewareTracing
12
+ class HostClass
13
+ include NewRelic::Agent::Instrumentation::MiddlewareTracing
14
+
15
+ attr_reader :category
15
16
 
16
- attr_reader :category
17
+ def initialize(&blk)
18
+ @action = blk
19
+ end
17
20
 
18
- def target
19
- self
20
- end
21
+ def target
22
+ self
23
+ end
21
24
 
22
- def transaction_options
23
- {}
24
- end
25
+ def transaction_options
26
+ {}
27
+ end
25
28
 
26
- def traced_call(env)
27
- raise UserError.new
28
- end
29
+ def traced_call(env)
30
+ @action.call
29
31
  end
32
+ end
30
33
 
34
+ def test_dont_block_errors_during_malfunctioning_transaction
31
35
  NewRelic::Agent::Transaction.stubs(:start).returns(nil)
32
36
 
37
+ middleware = HostClass.new { raise UserError }
33
38
  assert_raises(UserError) do
34
- middleware_class.new.call({})
39
+ middleware.call({})
35
40
  end
36
41
  end
42
+
43
+ def test_dont_raise_when_transaction_start_fails
44
+ NewRelic::Agent::Transaction.stubs(:start).returns(nil)
45
+
46
+ middleware = HostClass.new { [200, {}, ['hi!']] }
47
+ middleware.call({})
48
+ end
37
49
  end