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
@@ -15,26 +15,116 @@ module NewRelic
15
15
  end
16
16
 
17
17
  def gather_stats(snap)
18
+ gather_gc_stats(snap)
19
+ gather_thread_stats(snap)
20
+ end
21
+
22
+ def gather_gc_stats(snap)
18
23
  snap.gc_runs = GC.count
19
24
 
25
+ # Rubinius::Metrics is available since Rubinius 2.3
26
+ if has_metrics?
27
+ gather_stats_from_metrics(snap)
28
+ else
29
+ gather_stats_from_gc_stat(snap)
30
+ end
31
+
32
+ gather_gc_time(snap)
33
+ end
34
+
35
+ # The '+ 0' bits in here are a workaround for a Rubinius bug wherein
36
+ # Rubinius::Metrics.data returns 0's as Bignums, and these Bignums
37
+ # cannot be safely subtraced from Fixnums. The + 0 has the effect of
38
+ # truncating to a Fixnum if possible without loss of precision.
39
+ # See https://github.com/rubinius/rubinius/issues/3316
40
+ def gather_stats_from_metrics(snap)
41
+ snap.major_gc_count = metric(:'gc.immix.count') + 0
42
+ snap.minor_gc_count = metric(:'gc.young.count') + 0
43
+
44
+ snap.heap_live = metric(:'memory.large.objects.current') +
45
+ metric(:'memory.young.objects.current') +
46
+ metric(:'memory.immix.objects.current')
47
+
48
+ snap.total_allocated_object =
49
+ metric(:'memory.large.objects.total') +
50
+ metric(:'memory.young.objects.total') +
51
+ metric(:'memory.immix.objects.total')
52
+
53
+ snap.method_cache_invalidations = metric(:'vm.inline_cache.resets') + 0
54
+ end
55
+
56
+ def gather_stats_from_gc_stat(snap)
20
57
  gc_stats = GC.stat[:gc]
58
+
21
59
  if gc_stats
22
60
  snap.major_gc_count = gc_stats[:full][:count] if gc_stats[:full]
23
61
  snap.minor_gc_count = gc_stats[:young][:count] if gc_stats[:young]
24
62
  end
63
+ end
64
+
65
+ def gather_gc_time(snap)
66
+ if GC.respond_to?(:time)
67
+ # On Rubinius GC.time returns a time in miliseconds, not seconds.
68
+ snap.gc_total_time = GC.time / 1000
69
+ end
70
+ end
25
71
 
72
+ def gather_thread_stats(snap)
26
73
  snap.thread_count = Thread.list.size
27
74
  end
28
75
 
29
- SUPPORTED_KEYS = [
76
+ def has_metrics?
77
+ Rubinius.const_defined?(:Metrics)
78
+ end
79
+
80
+ def metric(key)
81
+ Rubinius::Metrics.data[key]
82
+ end
83
+
84
+ SUPPORTED_KEYS_GC_RBX_METRICS = [
30
85
  :gc_runs,
86
+ :heap_live,
31
87
  :major_gc_count,
32
88
  :minor_gc_count,
33
- :thread_count
89
+ :method_cache_invalidations,
90
+ :thread_count,
91
+ :total_allocated_object
34
92
  ].freeze
35
93
 
36
94
  def supports?(key)
37
- SUPPORTED_KEYS.include?(key)
95
+ if has_metrics?
96
+ case key
97
+ when :major_gc_count
98
+ true
99
+ when :minor_gc_count
100
+ true
101
+ when :heap_live
102
+ true
103
+ when :total_allocated_object
104
+ true
105
+ when :method_cache_invalidations
106
+ true
107
+ when :gc_runs
108
+ true
109
+ when :gc_total_time
110
+ GC.respond_to?(:time)
111
+ when :thread_count
112
+ true
113
+ else
114
+ false
115
+ end
116
+ else
117
+ case key
118
+ when :major_gc_count
119
+ true
120
+ when :minor_gc_count
121
+ true
122
+ when :thread_count
123
+ true
124
+ else
125
+ false
126
+ end
127
+ end
38
128
  end
39
129
  end
40
130
  end
@@ -70,6 +70,7 @@ module NewRelic
70
70
  return if config.nil? || !config.respond_to?(:middleware)
71
71
  begin
72
72
  require 'new_relic/rack/agent_hooks'
73
+ return unless NewRelic::Rack::AgentHooks.needed?
73
74
  config.middleware.use NewRelic::Rack::AgentHooks
74
75
  ::NewRelic::Agent.logger.debug("Installed New Relic Agent Hooks middleware")
75
76
  rescue => e
@@ -7,35 +7,27 @@ require 'new_relic/rack/agent_middleware'
7
7
  require 'new_relic/agent/instrumentation/middleware_proxy'
8
8
 
9
9
  module NewRelic::Rack
10
- # This middleware is used by the agent internally, and is usually injected
11
- # automatically into the middleware chain. If automatic injection is not
12
- # working, you may manually use it in your middleware chain instead.
10
+ # This middleware is used internally by the agent in the rare case
11
+ # where the disable_middleware_instrumentation configuration setting
12
+ # is true. In Rails and Sinatra applications this middleware will be
13
+ # automatically injected if necessary.
14
+ #
15
+ # If you have disabled middleware instrumentation and are not using Rails or
16
+ # Sinatra you can include this middleware manually in your config.ru file.
17
+ #
18
+ # All of the functionality of this module resides in the MiddlewareTracing
19
+ # module, which is shared between it and our third party middleware
20
+ # instrumentation.
13
21
  #
14
22
  # @api public
15
23
  #
16
24
  class AgentHooks < AgentMiddleware
17
- # We use this key in the Rack env hash to note when we've already fired
18
- # events for a given request, in case this middleware gets installed
19
- # multiple times in the middleware chain because of a misconfiguration.
20
- ENV_KEY = "newrelic.agent_hooks_fired".freeze
21
-
22
- def traced_call(env)
23
- if env[ENV_KEY]
24
- # Already fired the hooks, just pass through
25
- @app.call(env)
26
- else
27
- env[ENV_KEY] = true
28
-
29
- events.notify(:before_call, env)
30
- result = @app.call(env)
31
- events.notify(:after_call, env, result)
32
-
33
- result
34
- end
25
+ def self.needed?
26
+ !NewRelic::Agent.config[:disable_middleware_instrumentation]
35
27
  end
36
28
 
37
- def events
38
- NewRelic::Agent.instance.events
29
+ def traced_call(env)
30
+ @app.call(env)
39
31
  end
40
32
  end
41
33
  end
@@ -11,8 +11,8 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 3
14
- MINOR = 9
15
- TINY = 9
14
+ MINOR = 10
15
+ TINY = 0
16
16
 
17
17
  begin
18
18
  require File.join(File.dirname(__FILE__), 'build')
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.version = NewRelic::VERSION::STRING
11
11
  s.required_ruby_version = '>= 1.8.7'
12
12
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
13
- s.authors = [ "Jason Clark", "Tim Krajcar", "Chris Pine", "Jonan Scheffler", "Ben Weintraub" ]
13
+ s.authors = [ "Jason Clark", "Tim Krajcar", "Jonan Scheffler", "Matthew Wear", "Ben Weintraub" ]
14
14
  s.date = Time.now.strftime('%Y-%m-%d')
15
15
  s.licenses = ['New Relic', 'MIT', 'Ruby']
16
16
  s.description = <<-EOS
@@ -47,14 +47,21 @@ EOS
47
47
  s.add_development_dependency 'yard'
48
48
  s.add_development_dependency 'rails', '~> 3.2.13'
49
49
  s.add_development_dependency 'pry', '~> 0.9.12'
50
- s.add_development_dependency 'guard', '~> 1.8.3' # Guard 2.0 is Ruby 1.9 only
51
- s.add_development_dependency 'guard-minitest'
52
- s.add_development_dependency 'rb-fsevent', '~> 0.9.1'
53
50
  s.add_development_dependency 'hometown', '~> 0.2.5'
54
- s.add_development_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
51
+
52
+ # Only let Guard run on newer Rubies
53
+ if RUBY_VERSION >= "1.9.3"
54
+ s.add_development_dependency 'guard'
55
+ s.add_development_dependency 'guard-minitest'
56
+ s.add_development_dependency 'rb-fsevent'
57
+ end
58
+
59
+ # version lock down for i18n that is compatible with Ruby 1.8.7
60
+ s.add_development_dependency 'i18n', '0.6.11'
55
61
 
56
62
  if RUBY_PLATFORM == 'java'
57
63
  s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
64
+ s.add_development_dependency 'jruby-openssl'
58
65
  else
59
66
  s.add_development_dependency 'sqlite3'
60
67
  end
@@ -216,6 +216,8 @@ def assert_metrics_not_recorded(not_expected)
216
216
  assert_equal([], found_but_not_expected, "Found unexpected metrics: #{format_metric_spec_list(found_but_not_expected)}")
217
217
  end
218
218
 
219
+ alias :refute_metrics_recorded :assert_metrics_not_recorded
220
+
219
221
  def assert_no_metrics_match(regex)
220
222
  matching_metrics = []
221
223
  NewRelic::Agent.instance.stats_engine.metrics.each do |metric|
@@ -229,6 +231,8 @@ def assert_no_metrics_match(regex)
229
231
  )
230
232
  end
231
233
 
234
+ alias :refute_metrics_match :assert_no_metrics_match
235
+
232
236
  def format_metric_spec_list(specs)
233
237
  spec_strings = specs.map do |spec|
234
238
  "#{spec.name} (#{spec.scope.empty? ? '<unscoped>' : spec.scope})"
@@ -237,12 +241,12 @@ def format_metric_spec_list(specs)
237
241
  end
238
242
 
239
243
  def assert_truthy(expected, msg = nil)
240
- msg = "Expected #{expected.inspect} to be truthy"
244
+ msg ||= "Expected #{expected.inspect} to be truthy"
241
245
  assert !!expected, msg
242
246
  end
243
247
 
244
248
  def assert_falsy(expected, msg = nil)
245
- msg = "Expected #{expected.inspect} to be falsy"
249
+ msg ||= "Expected #{expected.inspect} to be falsy"
246
250
  assert !expected, msg
247
251
  end
248
252
 
@@ -274,20 +278,19 @@ end
274
278
  # With a transaction name plus category:
275
279
  # in_transaction('foobar', :category => :controller) { ... }
276
280
  #
277
- def in_transaction(*args)
278
- opts = (args.last && args.last.is_a?(Hash)) ? args.pop : {}
279
- opts[:transaction_name] = args.first || 'dummy'
281
+ def in_transaction(*args, &blk)
282
+ opts = (args.last && args.last.is_a?(Hash)) ? args.pop : {}
280
283
  category = (opts && opts.delete(:category)) || :other
284
+
285
+ # At least one test passes `:transaction_name => nil`, so handle it gently
286
+ name = opts.key?(:transaction_name) ? opts.delete(:transaction_name) :
287
+ args.first || 'dummy'
288
+
281
289
  state = NewRelic::Agent::TransactionState.tl_get
282
290
 
283
- NewRelic::Agent::Transaction.start(state, category, opts)
284
- val = nil
285
- begin
286
- val = yield state.current_transaction
287
- ensure
288
- NewRelic::Agent::Transaction.stop(state)
291
+ NewRelic::Agent::Transaction.wrap(state, name, category, opts) do
292
+ yield state.current_transaction
289
293
  end
290
- val
291
294
  end
292
295
 
293
296
  def stub_transaction_guid(guid)
@@ -416,8 +419,17 @@ end
416
419
 
417
420
 
418
421
  def freeze_time(now=Time.now)
419
- Time.stubs(:now).returns(now)
420
- now
422
+ if block_given?
423
+ begin
424
+ Time.stubs(:now).returns(now)
425
+ yield now
426
+ ensure
427
+ Time.unstub(:now)
428
+ end
429
+ else
430
+ Time.stubs(:now).returns(now)
431
+ now
432
+ end
421
433
  end
422
434
 
423
435
  def advance_time(seconds)
@@ -163,7 +163,7 @@ module Multiverse
163
163
  bundler_out = exclusive_bundle
164
164
  puts bundler_out if verbose? || $? != 0
165
165
  raise "bundle command failed with (#{$?})" unless $? == 0
166
- cache_gemfile_lock(env_index)
166
+ cache_gemfile_lock(env_index) if use_cache?
167
167
  end
168
168
 
169
169
  def generate_gemfile(gemfile_text, env_index, local = true)
@@ -199,10 +199,6 @@ module Multiverse
199
199
  return unless is_rbx?
200
200
 
201
201
  f.puts "gem 'rubysl', :platforms => [:rbx]" unless gemfile_text =~ /^\s*gem .rubysl./
202
- # Compilation issues with rubysl-openssl 2.2.1, lock at 2.1.0 for now.
203
- # https://github.com/rubysl/rubysl-openssl/issues/11
204
- f.puts "gem 'rubysl-openssl', '2.1.0', :platforms => [:rbx]" unless gemfile_text =~ /^\s*gem .rubysl-openssl./
205
-
206
202
  f.puts "gem 'json', :platforms => [:rbx]" unless gemfile_text =~ /^\s*gem .json./
207
203
  f.puts "gem 'racc', :platforms => [:rbx]" unless gemfile_text =~ /^\s*gem .racc./
208
204
  end
@@ -6,6 +6,7 @@ gemfile <<-RB
6
6
  # Very special versioning to keep us running on 1.8.7 versions of Ruby
7
7
  gem 'activesupport', '~>2.3.14', :require => 'active_support'
8
8
  gem 'nokogiri', '~>1.4.7'
9
+ gem 'i18n', '~>0.6.11'
9
10
  else
10
11
  gem 'activesupport', '~>4.0.4'
11
12
  gem 'nokogiri', '~>1.6.1'
@@ -17,12 +18,14 @@ RB
17
18
 
18
19
  gemfile <<-RB
19
20
  gem 'activemerchant', '~>1.25.0'
21
+ gem 'active_utils', '2.2.3'
20
22
  gem 'rack'
21
23
 
22
24
  if RUBY_VERSION <= '1.9.2'
23
25
  # Very special versioning to keep us running on 1.8.7 versions of Ruby
24
26
  gem 'activesupport', '~>2.3.14', :require => 'active_support'
25
27
  gem 'nokogiri', '~>1.4.7'
28
+ gem 'i18n', '~>0.6.11'
26
29
  else
27
30
  gem 'activesupport', '~>4.0.4'
28
31
  gem 'nokogiri', '~>1.5.11'
@@ -30,4 +33,4 @@ gemfile <<-RB
30
33
 
31
34
  # Need to load newrelic_rpm after ActiveMerchant Gateways are required
32
35
  gem 'newrelic_rpm', :require => false, :path => File.expand_path('../../../../')
33
- RB
36
+ RB
@@ -9,11 +9,6 @@ require 'multiverse_helpers'
9
9
  require 'new_relic/rack/agent_hooks'
10
10
 
11
11
  class CrossApplicationTracingTest < Minitest::Test
12
-
13
- # Important because the hooks are global that we only wire one AgentHooks up
14
- @@app = TestingApp.new
15
- @@wrapper_app = NewRelic::Rack::AgentHooks.new(@@app)
16
-
17
12
  include MultiverseHelpers
18
13
  setup_and_teardown_agent(:cross_process_id => "boo",
19
14
  :encoding_key => "\0",
@@ -25,15 +20,10 @@ class CrossApplicationTracingTest < Minitest::Test
25
20
  "ignore" => true}]})
26
21
  end
27
22
 
28
- def after_setup
29
- @@app.reset_headers
30
- @@app.response = "<html><head><title>W00t!</title></head><body><p>Hello World</p></body></html>"
31
- end
32
-
33
23
  include Rack::Test::Methods
34
24
 
35
25
  def app
36
- @@wrapper_app
26
+ Rack::Builder.app { run TestingApp.new }
37
27
  end
38
28
 
39
29
  def test_cross_app_doesnt_modify_without_header
@@ -58,7 +48,7 @@ class CrossApplicationTracingTest < Minitest::Test
58
48
  end
59
49
 
60
50
  load_cross_agent_test("cat_map").each do |test_case|
61
- # We only can do test cases here that don't involve outgoing calls
51
+ # We only can do test cases here that don't involve outgoing calls
62
52
  if !test_case["outboundRequests"]
63
53
  if test_case['inboundPayload']
64
54
  request_headers = {
@@ -140,7 +140,7 @@ class LoggingTest < Minitest::Test
140
140
  def test_logs_forking_workers
141
141
  running_agent_writes_to_log(
142
142
  { :dispatcher => :passenger },
143
- "Connecting workers after forking.")
143
+ "Deferring startup of agent reporting thread")
144
144
  end
145
145
 
146
146
  # Helpers
@@ -16,11 +16,13 @@ class SetTransactionNameTest < Minitest::Test
16
16
 
17
17
  class TestTransactor
18
18
  include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
19
+
19
20
  def parent_txn(child_category=nil)
20
21
  NewRelic::Agent.set_transaction_name('TestTransactor/parent')
21
22
  yield if block_given?
22
23
  child_txn(child_category)
23
24
  end
25
+
24
26
  add_transaction_tracer :parent_txn
25
27
 
26
28
  def child_txn(category)
@@ -28,9 +30,11 @@ class SetTransactionNameTest < Minitest::Test
28
30
  opts[:category] = category if category
29
31
  NewRelic::Agent.set_transaction_name('TestTransactor/child', opts)
30
32
  end
33
+
31
34
  add_transaction_tracer :child_txn
32
35
 
33
36
  newrelic_ignore :only => :ignored_txn
37
+
34
38
  def ignored_txn
35
39
  NewRelic::Agent.set_transaction_name('Ignore/me')
36
40
  end
@@ -8,20 +8,13 @@ require 'new_relic/rack/agent_hooks'
8
8
  require './testing_app'
9
9
 
10
10
  class SyntheticsTest < Minitest::Test
11
- @app = TestingApp.new
12
- @wrapper_app = NewRelic::Rack::AgentHooks.new(@app)
13
-
14
- def self.wrapper_app
15
- @wrapper_app
16
- end
17
-
18
11
  include MultiverseHelpers
19
12
  include Rack::Test::Methods
20
13
 
21
14
  setup_and_teardown_agent
22
15
 
23
16
  def app
24
- self.class.wrapper_app
17
+ Rack::Builder.app { run TestingApp.new }
25
18
  end
26
19
 
27
20
  def last_sent_analytics_event