newrelic_rpm 3.7.3.204 → 3.8.0.218

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +73 -0
  3. data/README.md +1 -1
  4. data/Rakefile +1 -5
  5. data/lib/new_relic/agent.rb +1 -0
  6. data/lib/new_relic/agent/agent.rb +47 -18
  7. data/lib/new_relic/agent/agent_logger.rb +11 -1
  8. data/lib/new_relic/agent/configuration/default_source.rb +85 -1
  9. data/lib/new_relic/agent/configuration/manager.rb +5 -1
  10. data/lib/new_relic/agent/datastores/mongo.rb +8 -3
  11. data/lib/new_relic/agent/harvester.rb +5 -1
  12. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +1 -0
  13. data/lib/new_relic/agent/instrumentation/active_merchant.rb +7 -3
  14. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +13 -3
  15. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +7 -1
  16. data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -1
  17. data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -1
  18. data/lib/new_relic/agent/new_relic_service.rb +8 -0
  19. data/lib/new_relic/agent/request_sampler.rb +1 -1
  20. data/lib/new_relic/agent/sampler.rb +22 -2
  21. data/lib/new_relic/agent/sampler_collection.rb +13 -1
  22. data/lib/new_relic/agent/samplers/cpu_sampler.rb +3 -1
  23. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +2 -1
  24. data/lib/new_relic/agent/samplers/memory_sampler.rb +2 -1
  25. data/lib/new_relic/agent/samplers/object_sampler.rb +1 -3
  26. data/lib/new_relic/agent/samplers/vm_sampler.rb +126 -0
  27. data/lib/new_relic/agent/stats.rb +0 -15
  28. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +66 -75
  29. data/lib/new_relic/agent/stats_engine/stats_hash.rb +1 -1
  30. data/lib/new_relic/agent/supported_versions.rb +2 -2
  31. data/lib/new_relic/agent/transaction.rb +6 -3
  32. data/lib/new_relic/agent/vm/monotonic_gc_profiler.rb +17 -5
  33. data/lib/new_relic/agent/vm/mri_vm.rb +2 -1
  34. data/lib/new_relic/agent/vm/snapshot.rb +5 -1
  35. data/lib/new_relic/control/instance_methods.rb +8 -5
  36. data/lib/new_relic/control/instrumentation.rb +0 -9
  37. data/lib/new_relic/environment_report.rb +1 -1
  38. data/lib/new_relic/language_support.rb +4 -0
  39. data/lib/new_relic/local_environment.rb +39 -14
  40. data/lib/new_relic/noticed_error.rb +7 -4
  41. data/lib/new_relic/rack/browser_monitoring.rb +16 -3
  42. data/lib/new_relic/version.rb +2 -2
  43. data/newrelic_rpm.gemspec +1 -1
  44. data/test/agent_helper.rb +5 -3
  45. data/test/environments/lib/environments/runner.rb +8 -7
  46. data/test/environments/norails/Gemfile +1 -1
  47. data/test/environments/rails21/Gemfile +1 -0
  48. data/test/environments/rails22/Gemfile +1 -0
  49. data/test/environments/rails23/Gemfile +1 -0
  50. data/test/environments/rails30/Gemfile +4 -1
  51. data/test/environments/rails31/Gemfile +4 -1
  52. data/test/environments/rails32/Gemfile +3 -4
  53. data/test/environments/rails40/Gemfile +1 -1
  54. data/test/environments/rails41/Gemfile +1 -1
  55. data/test/flaky_proxy/lib/flaky_proxy/proxy.rb +1 -0
  56. data/test/multiverse/lib/multiverse/output_collector.rb +3 -1
  57. data/test/multiverse/lib/multiverse/runner.rb +2 -10
  58. data/test/multiverse/lib/multiverse/suite.rb +100 -30
  59. data/test/multiverse/suites/activemerchant/Envfile +16 -0
  60. data/test/multiverse/suites/activemerchant/activemerchant_test.rb +65 -0
  61. data/test/multiverse/suites/agent_only/custom_queue_time_test.rb +57 -0
  62. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +1 -1
  63. data/test/multiverse/suites/mongo/Envfile +9 -1
  64. data/test/multiverse/suites/rails/Envfile +2 -2
  65. data/test/multiverse/suites/rails/app.rb +3 -0
  66. data/test/multiverse/suites/rails/bad_instrumentation_test.rb +0 -2
  67. data/test/multiverse/suites/rails/error_tracing_test.rb +1 -2
  68. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +17 -8
  69. data/test/multiverse/suites/rails/ignore_test.rb +0 -2
  70. data/test/multiverse/suites/rails/mongrel_queue_depth_test.rb +0 -2
  71. data/test/multiverse/suites/rails/queue_time_test.rb +40 -11
  72. data/test/multiverse/suites/rails/request_statistics_test.rb +0 -3
  73. data/test/multiverse/suites/rails/view_instrumentation_test.rb +0 -2
  74. data/test/multiverse/suites/sidekiq/Envfile +7 -2
  75. data/test/multiverse/suites/sinatra/Envfile +1 -1
  76. data/test/multiverse/suites/sinatra/nested_middleware_test.rb +41 -0
  77. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +1 -1
  78. data/test/new_relic/agent/agent/connect_test.rb +32 -4
  79. data/test/new_relic/agent/agent/start_test.rb +9 -1
  80. data/test/new_relic/agent/agent_logger_test.rb +23 -2
  81. data/test/new_relic/agent/agent_test.rb +49 -7
  82. data/test/new_relic/agent/configuration/manager_test.rb +8 -0
  83. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +7 -0
  84. data/test/new_relic/agent/cross_app_monitor_test.rb +5 -6
  85. data/test/new_relic/agent/harvester_test.rb +13 -8
  86. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +28 -7
  87. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +32 -21
  88. data/test/new_relic/agent/new_relic_service_test.rb +14 -0
  89. data/test/new_relic/agent/request_sampler_test.rb +5 -3
  90. data/test/new_relic/agent/rpm_agent_test.rb +2 -3
  91. data/test/new_relic/agent/sampler_collection_test.rb +15 -5
  92. data/test/new_relic/agent/sampler_test.rb +43 -0
  93. data/test/new_relic/agent/{cpu_sampler_test.rb → samplers/cpu_sampler_test.rb} +1 -1
  94. data/test/new_relic/agent/samplers/vm_sampler_test.rb +349 -0
  95. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +165 -44
  96. data/test/new_relic/agent/stats_hash_test.rb +1 -1
  97. data/test/new_relic/agent/transaction_test.rb +14 -0
  98. data/test/new_relic/agent/vm/monotonic_gc_profiler_test.rb +5 -5
  99. data/test/new_relic/agent/vm/mri_vm_test.rb +7 -0
  100. data/test/new_relic/agent/vm/snapshot_test.rb +5 -0
  101. data/test/new_relic/agent_test.rb +2 -2
  102. data/test/new_relic/control/instance_methods_test.rb +30 -0
  103. data/test/new_relic/control_test.rb +43 -21
  104. data/test/new_relic/dispatcher_test.rb +5 -0
  105. data/test/new_relic/local_environment_test.rb +3 -26
  106. data/test/new_relic/multiverse_helpers.rb +5 -0
  107. data/test/new_relic/noticed_error_test.rb +7 -0
  108. data/test/new_relic/rack/browser_monitoring_test.rb +13 -14
  109. data/test/test_helper.rb +2 -1
  110. metadata +56 -68
  111. metadata.gz.sig +1 -1
  112. data/lib/new_relic/agent/instrumentation/puma.rb +0 -25
  113. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +0 -26
  114. data/test/multiverse/script/run_one +0 -5
  115. data/test/rum/basic.result.html +0 -10
  116. data/test/rum/basic.source.html +0 -10
  117. data/test/rum/comments1.result.html +0 -24
  118. data/test/rum/comments1.source.html +0 -24
  119. data/test/rum/comments2.result.html +0 -24
  120. data/test/rum/comments2.source.html +0 -24
  121. data/test/rum/gt_in_quotes1.result.html +0 -27
  122. data/test/rum/gt_in_quotes1.source.html +0 -27
  123. data/test/rum/gt_in_quotes2.result.html +0 -24
  124. data/test/rum/gt_in_quotes2.source.html +0 -24
  125. data/test/rum/gt_in_quotes_mismatch.result.html +0 -24
  126. data/test/rum/gt_in_quotes_mismatch.source.html +0 -24
  127. data/test/rum/gt_in_single_quotes1.result.html +0 -25
  128. data/test/rum/gt_in_single_quotes1.source.html +0 -25
  129. data/test/rum/gt_in_single_quotes_mismatch.result.html +0 -25
  130. data/test/rum/gt_in_single_quotes_mismatch.source.html +0 -25
  131. data/test/rum/incomplete_non_meta_tags.result.html +0 -10
  132. data/test/rum/incomplete_non_meta_tags.source.html +0 -10
  133. data/test/rum/no_body.result.html +0 -21
  134. data/test/rum/no_body.source.html +0 -21
  135. data/test/rum/no_header.result.html +0 -7
  136. data/test/rum/no_header.source.html +0 -7
  137. data/test/rum/no_html_and_no_header.result.html +0 -3
  138. data/test/rum/no_html_and_no_header.source.html +0 -3
  139. data/test/rum/no_start_header.result.html +0 -9
  140. data/test/rum/no_start_header.source.html +0 -9
  141. data/test/rum/script1.result.html +0 -19
  142. data/test/rum/script1.source.html +0 -19
  143. data/test/rum/script2.result.html +0 -17
  144. data/test/rum/script2.source.html +0 -17
  145. data/test/rum/x_ua_meta_tag.result.html +0 -10
  146. data/test/rum/x_ua_meta_tag.source.html +0 -10
  147. data/test/rum/x_ua_meta_tag_multiline.result.html +0 -11
  148. data/test/rum/x_ua_meta_tag_multiline.source.html +0 -11
  149. data/test/rum/x_ua_meta_tag_spaces_around_equals.result.html +0 -10
  150. data/test/rum/x_ua_meta_tag_spaces_around_equals.source.html +0 -10
  151. data/test/rum/x_ua_meta_tag_with_others.result.html +0 -11
  152. data/test/rum/x_ua_meta_tag_with_others.source.html +0 -11
  153. data/test/rum/x_ua_meta_tag_with_spaces.result.html +0 -10
  154. data/test/rum/x_ua_meta_tag_with_spaces.source.html +0 -10
@@ -21,7 +21,7 @@ module NewRelic
21
21
  attr_accessor :started_at, :harvested_at
22
22
 
23
23
  def initialize(started_at=Time.now)
24
- @started_at = started_at
24
+ @started_at = started_at.to_f
25
25
  super() { |hash, key| hash[key] = NewRelic::Agent::Stats.new }
26
26
  end
27
27
 
@@ -11,7 +11,7 @@ module NewRelic
11
11
  {
12
12
  :type => :ruby,
13
13
  :name => "MRI",
14
- :supported => ["1.8.7", "1.9.2", "1.9.3", "2.0.0", "2.1.0"],
14
+ :supported => ["1.8.7", "1.9.2", "1.9.3", "2.0.0", "~> 2.1.0"],
15
15
  :deprecated => ["1.8.6"],
16
16
  :url => "https://www.ruby-lang.org",
17
17
  :feed => "https://www.ruby-lang.org/en/feeds/news.rss",
@@ -85,7 +85,7 @@ module NewRelic
85
85
  :rails =>
86
86
  {
87
87
  :type => :web,
88
- :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0"],
88
+ :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0", "~>4.1.0"],
89
89
  :deprecated => ["~>2.0.0"],
90
90
  :url => "https://rubygems.org/gems/rails",
91
91
  :feed => "https://rubygems.org/gems/rails/versions.atom",
@@ -25,6 +25,7 @@ module NewRelic
25
25
  attr_reader :name
26
26
  attr_reader :guid
27
27
  attr_reader :stats_hash
28
+ attr_reader :gc_start_snapshot
28
29
 
29
30
  # Populated with the trace sample once this transaction is completed.
30
31
  attr_reader :transaction_trace
@@ -102,6 +103,7 @@ module NewRelic
102
103
  @apdex_start = @start_time
103
104
  @jruby_cpu_start = jruby_cpu_time
104
105
  @process_cpu_start = process_cpu
106
+ @gc_start_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
105
107
  @filtered_params = options[:filtered_params] || {}
106
108
  @force_flag = options[:force]
107
109
  @request = options[:request]
@@ -157,7 +159,6 @@ module NewRelic
157
159
  transaction_sampler.notice_first_scope_push(start_time)
158
160
  sql_sampler.notice_first_scope_push(start_time)
159
161
 
160
- NewRelic::Agent::StatsEngine::GCProfiler.init
161
162
  agent.stats_engine.start_transaction
162
163
  transaction_sampler.notice_transaction(uri, filtered_params)
163
164
  sql_sampler.notice_transaction(uri, filtered_params)
@@ -198,9 +199,11 @@ module NewRelic
198
199
  # before the transaction sampler is finished
199
200
  if traced?
200
201
  record_transaction_cpu
201
- gc_time = NewRelic::Agent::StatsEngine::GCProfiler.capture
202
+ gc_stop_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
203
+ gc_delta = NewRelic::Agent::StatsEngine::GCProfiler.record_delta(
204
+ gc_start_snapshot, gc_stop_snapshot)
202
205
  end
203
- @transaction_trace = transaction_sampler.notice_scope_empty(self, Time.now, gc_time)
206
+ @transaction_trace = transaction_sampler.notice_scope_empty(self, Time.now, gc_delta)
204
207
  sql_sampler.notice_scope_empty(@name)
205
208
  end
206
209
 
@@ -9,12 +9,14 @@
9
9
  # This class comes to the rescue. It relies on being the only party to reset
10
10
  # the underlying GC::Profiler, but otherwise gives us a steadily increasing
11
11
  # total time.
12
+
12
13
  module NewRelic
13
14
  module Agent
14
15
  module VM
15
16
  class MonotonicGCProfiler
16
17
  def initialize
17
- @total_time = 0
18
+ @total_time_s = 0
19
+ @lock = Mutex.new
18
20
  end
19
21
 
20
22
  class ProfilerNotEnabledError < StandardError
@@ -23,12 +25,22 @@ module NewRelic
23
25
  end
24
26
  end
25
27
 
26
- def total_time
28
+ def total_time_s
27
29
  raise ProfilerNotEnabledError.new unless NewRelic::LanguageSupport.gc_profiler_enabled?
28
30
 
29
- @total_time += ::GC::Profiler.total_time
30
- ::GC::Profiler.clear
31
- @total_time
31
+ # There's a race here if the next two lines don't execute as an atomic
32
+ # unit - we may end up double-counting some GC time in that scenario.
33
+ # Locking around them guarantees atomicity of the read/increment/reset
34
+ # sequence.
35
+ @lock.synchronize do
36
+ # The Ruby 1.9.x docs claim that GC::Profiler.total_time returns
37
+ # a value in milliseconds. They are incorrect - both 1.9.x and 2.x
38
+ # return values in seconds.
39
+ @total_time_s += ::GC::Profiler.total_time
40
+ ::GC::Profiler.clear
41
+ end
42
+
43
+ @total_time_s
32
44
  end
33
45
  end
34
46
  end
@@ -19,6 +19,7 @@ module NewRelic
19
19
  gather_gc_stats(snap)
20
20
  gather_ruby_vm_stats(snap)
21
21
  gather_thread_stats(snap)
22
+ gather_gc_time(snap)
22
23
  end
23
24
 
24
25
  def gather_gc_stats(snap)
@@ -38,7 +39,7 @@ module NewRelic
38
39
 
39
40
  def gather_gc_time(snap)
40
41
  if supports?(:gc_total_time)
41
- snap.gc_total_time = NewRelic::Agent.instance.monotonic_gc_profiler.total_time
42
+ snap.gc_total_time = NewRelic::Agent.instance.monotonic_gc_profiler.total_time_s
42
43
  end
43
44
  end
44
45
 
@@ -9,7 +9,11 @@ module NewRelic
9
9
  attr_accessor :gc_total_time, :gc_runs, :major_gc_count, :minor_gc_count,
10
10
  :total_allocated_object, :heap_live, :heap_free,
11
11
  :method_cache_invalidations, :constant_cache_invalidations,
12
- :thread_count
12
+ :thread_count, :taken_at
13
+
14
+ def initialize
15
+ @taken_at = Time.now.to_f
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -52,10 +52,7 @@ module NewRelic
52
52
  Agent.logger.info("Starting the New Relic agent in #{env.inspect} environment.")
53
53
  Agent.logger.info("To prevent agent startup add a NEWRELIC_ENABLE=false environment variable or modify the #{env.inspect} section of your newrelic.yml.")
54
54
 
55
- yaml = Agent::Configuration::YamlSource.new(@config_file_path, env)
56
- Agent.config.replace_or_add_config(yaml, 1)
57
-
58
- Agent.config.replace_or_add_config(Agent::Configuration::ManualSource.new(options), 1)
55
+ configure_agent(env, options)
59
56
 
60
57
  # Be sure to only create once! RUBY-1020
61
58
  if ::NewRelic::Agent.logger.is_startup_logger?
@@ -76,12 +73,18 @@ module NewRelic
76
73
  if Agent.config[:agent_enabled] && !NewRelic::Agent.instance.started?
77
74
  start_agent
78
75
  install_instrumentation
79
- load_samplers unless Agent.config[:disable_samplers]
80
76
  elsif !Agent.config[:agent_enabled]
81
77
  install_shim
82
78
  end
83
79
  end
84
80
 
81
+ def configure_agent(env, options)
82
+ yaml = Agent::Configuration::YamlSource.new(@config_file_path, env)
83
+ Agent.config.replace_or_add_config(yaml, 1)
84
+
85
+ Agent.config.replace_or_add_config(Agent::Configuration::ManualSource.new(options), 1)
86
+ end
87
+
85
88
  # Install the real agent into the Agent module, and issue the start command.
86
89
  def start_agent
87
90
  NewRelic::Agent.agent.start
@@ -52,15 +52,6 @@ module NewRelic
52
52
  _install_instrumentation
53
53
  end
54
54
 
55
- # adds samplers to the stats engine so that they run every
56
- # minute. This is dynamically recognized by any class that
57
- # subclasses NewRelic::Agent::Sampler
58
- def load_samplers
59
- NewRelic::Agent::Sampler.sampler_classes.each do | subclass |
60
- NewRelic::Agent.instance.add_harvest_sampler(subclass)
61
- end
62
- end
63
-
64
55
  private
65
56
 
66
57
  def _install_instrumentation
@@ -80,7 +80,7 @@ module NewRelic
80
80
  end
81
81
  report_on 'Rails Env' do
82
82
  if defined? ::Rails and ::Rails.respond_to?(:env)
83
- ::Rails.env
83
+ ::Rails.env.to_s
84
84
  else
85
85
  ENV['RAILS_ENV']
86
86
  end
@@ -98,6 +98,10 @@ module NewRelic::LanguageSupport
98
98
  defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
99
99
  end
100
100
 
101
+ def ree?
102
+ defined?(RUBY_DESCRIPTION) && RUBY_DESCRIPTION =~ /Ruby Enterprise Edition/
103
+ end
104
+
101
105
  def using_version?(version)
102
106
  numbers = version.split('.')
103
107
  numbers == ::RUBY_VERSION.split('.')[0, numbers.size]
@@ -6,11 +6,23 @@ require 'set'
6
6
  require 'new_relic/version'
7
7
 
8
8
  module NewRelic
9
- # An instance of LocalEnvironment is responsible for determining the 'dispatcher'
10
- # in use by the current process.
9
+ # This class is responsible for determining the 'dispatcher' in use by the
10
+ # current process. The dispatcher might be a recognized web server such as
11
+ # unicorn or passenger, a background job processor such as resque or sidekiq,
12
+ # or nil for unknown.
11
13
  #
12
- # A dispatcher might be a recognized web server such as unicorn or passenger,
13
- # a background job processor such as resque or sidekiq, or nil for unknown.
14
+ # Dispatcher detection is best-effort, and serves two purposes:
15
+ #
16
+ # 1. For some dispatchers, we need to apply specific workarounds in order for
17
+ # the agent to work correctly.
18
+ # 2. When reading logs, since multiple processes on a given host might write
19
+ # into the same log, it's useful to be able to identify what kind of
20
+ # process a given PID mapped to.
21
+ #
22
+ # Overriding the dispatcher is possible via the NEW_RELIC_DISPATCHER
23
+ # environment variable, but this should not generally be necessary unless
24
+ # you're on a dispatcher that falls into category 1 above, and our detection
25
+ # logic isn't working correctly.
14
26
  #
15
27
  # If the environment can't be determined, it will be set to nil.
16
28
  #
@@ -61,10 +73,24 @@ module NewRelic
61
73
 
62
74
  private
63
75
 
64
- # Although you can override the dispatcher with NEWRELIC_DISPATCHER this
65
- # is not advisable since it implies certain api's being available.
66
76
  def discover_dispatcher
67
- dispatchers = %w[passenger torquebox trinidad glassfish resque sidekiq delayed_job thin mongrel litespeed webrick fastcgi rainbows unicorn]
77
+ dispatchers = %w[
78
+ passenger
79
+ torquebox
80
+ trinidad
81
+ glassfish
82
+ resque
83
+ sidekiq
84
+ delayed_job
85
+ puma
86
+ thin
87
+ mongrel
88
+ litespeed
89
+ webrick
90
+ fastcgi
91
+ rainbows
92
+ unicorn
93
+ ]
68
94
  while dispatchers.any? && @discovered_dispatcher.nil?
69
95
  send 'check_for_'+(dispatchers.shift)
70
96
  end
@@ -107,13 +133,6 @@ module NewRelic
107
133
  def check_for_mongrel
108
134
  return unless defined?(::Mongrel) && defined?(::Mongrel::HttpServer)
109
135
  @discovered_dispatcher = :mongrel
110
-
111
- # Get the port from the server if it's started
112
- if mongrel && mongrel.respond_to?(:port)
113
- end
114
-
115
- # Might not have server yet, so allow one more check later on first request
116
- @looked_for_mongrel = false
117
136
  end
118
137
 
119
138
  def check_for_unicorn
@@ -130,6 +149,12 @@ module NewRelic
130
149
  end
131
150
  end
132
151
 
152
+ def check_for_puma
153
+ if defined?(::Puma) && File.basename($0) == 'puma'
154
+ @discovered_dispatcher = :puma
155
+ end
156
+ end
157
+
133
158
  def check_for_delayed_job
134
159
  if $0 =~ /delayed_job$/ || (File.basename($0) == 'rake' && ARGV.include?('jobs:work'))
135
160
  @discovered_dispatcher = :delayed_job
@@ -21,12 +21,15 @@ class NewRelic::NoticedError
21
21
  @exception_class_name = exception.is_a?(Exception) ? exception.class.name : 'Error'
22
22
  @exception_class_constant = exception.class
23
23
 
24
- if exception.respond_to?('original_exception')
25
- @message = exception.original_exception.message.to_s
26
- else
27
- @message = (exception || '<no message>').to_s
24
+ if exception.nil?
25
+ @message = '<no message>'
26
+ elsif exception.respond_to?('original_exception')
27
+ @message = (exception.original_exception || exception).to_s
28
+ else # exception is not nil, but does not respond to original_exception
29
+ @message = exception.to_s
28
30
  end
29
31
 
32
+
30
33
  unless @message.is_a?(String)
31
34
  # In pre-1.9.3, Exception.new({}).to_s.class != String
32
35
  # That is, Exception#to_s may not return a String instance if one wasn't
@@ -50,6 +50,7 @@ module NewRelic::Rack
50
50
  !headers['Content-Disposition'].to_s.include?('attachment')
51
51
  end
52
52
 
53
+ CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
53
54
  X_UA_COMPATIBLE_RE = /<\s*meta[^>]+http-equiv\s*=\s*['"]x-ua-compatible['"][^>]*>/im.freeze
54
55
 
55
56
  def autoinstrument_source(response, headers)
@@ -61,9 +62,16 @@ module NewRelic::Rack
61
62
  beginning_of_source = source[0..50_000]
62
63
 
63
64
  if body_start = find_body_start(beginning_of_source)
64
- insertion_index = find_x_ua_compatible_position(beginning_of_source) ||
65
- find_end_of_head_open(beginning_of_source) ||
66
- body_start
65
+ meta_tag_positions = [
66
+ find_x_ua_compatible_position(beginning_of_source),
67
+ find_charset_position(beginning_of_source)
68
+ ].compact
69
+
70
+ if !meta_tag_positions.empty?
71
+ insertion_index = meta_tag_positions.max
72
+ else
73
+ insertion_index = find_end_of_head_open(beginning_of_source) || body_start
74
+ end
67
75
 
68
76
  if insertion_index
69
77
  source = source[0...insertion_index] <<
@@ -106,6 +114,11 @@ module NewRelic::Rack
106
114
  match.end(0) if match
107
115
  end
108
116
 
117
+ def find_charset_position(beginning_of_source)
118
+ match = CHARSET_RE.match(beginning_of_source)
119
+ match.end(0) if match
120
+ end
121
+
109
122
  def find_end_of_head_open(beginning_of_source)
110
123
  head_open = beginning_of_source.index("<head")
111
124
  beginning_of_source.index(">", head_open) + 1 if head_open
@@ -11,8 +11,8 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 3
14
- MINOR = 7
15
- TINY = 3
14
+ MINOR = 8
15
+ TINY = 0
16
16
 
17
17
  begin
18
18
  require File.join(File.dirname(__FILE__), 'build')
@@ -49,7 +49,7 @@ EOS
49
49
  s.add_development_dependency 'sdoc-helpers'
50
50
  s.add_development_dependency 'rdoc', '>= 2.4.2'
51
51
  s.add_development_dependency 'rails', '~> 3.2.13'
52
- s.add_development_dependency 'sqlite3' unless RUBY_PLATFORM == 'java'
52
+ s.add_development_dependency 'sqlite3', '1.3.8' unless RUBY_PLATFORM == 'java'
53
53
  s.add_development_dependency 'activerecord-jdbcsqlite3-adapter' if RUBY_PLATFORM == 'java'
54
54
  s.add_development_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
55
55
  s.add_development_dependency 'sequel', '~> 3.46.0'
@@ -59,7 +59,7 @@ def assert_equal_unordered(left, right)
59
59
  end
60
60
 
61
61
  def compare_metrics(expected, actual)
62
- actual.delete_if {|a| a.include?('GC/cumulative') } # in case we are in REE
62
+ actual.delete_if {|a| a.include?('GC/Transaction/') }
63
63
  assert_equal(expected.to_a.sort, actual.to_a.sort, "extra: #{(actual - expected).to_a.inspect}; missing: #{(expected - actual).to_a.inspect}")
64
64
  end
65
65
 
@@ -78,6 +78,8 @@ def _normalize_metric_expectations(expectations)
78
78
  # Just assert that the metric is present, nothing about the attributes
79
79
  expectations.each { |k| hash[k] = { } }
80
80
  hash
81
+ when String
82
+ { expectations => {} }
81
83
  else
82
84
  expectations
83
85
  end
@@ -122,7 +124,7 @@ def assert_metrics_recorded_exclusive(expected, options={})
122
124
  recorded_metrics = recorded_metrics.select { |m| m.match(options[:filter]) }
123
125
  end
124
126
  expected_metrics = expected.keys.map { |s| metric_spec_from_specish(s).to_s }
125
- unexpected_metrics = recorded_metrics.select{|m| m !~ /GC\/cumulative/}
127
+ unexpected_metrics = recorded_metrics.select { |m| m !~ /GC\/Transaction/ }
126
128
  unexpected_metrics -= expected_metrics
127
129
  assert_equal(0, unexpected_metrics.size, "Found unexpected metrics: [#{unexpected_metrics.join(', ')}]")
128
130
  end
@@ -187,7 +189,7 @@ def in_transaction(*args)
187
189
  NewRelic::Agent.instance.stats_engine.transaction_sampler = \
188
190
  NewRelic::Agent.instance.transaction_sampler
189
191
  NewRelic::Agent::Transaction.start(transaction_type, opts || {})
190
- val = yield
192
+ val = yield NewRelic::Agent::Transaction.current
191
193
  NewRelic::Agent::Transaction.stop(name)
192
194
  val
193
195
  end
@@ -11,12 +11,12 @@ module Environments
11
11
  include Multiverse::Color
12
12
 
13
13
  BLACKLIST = {
14
+ "1.9" => ["rails21", "rails22"],
15
+ "2" => ["rails21", "rails22", "rails23"],
16
+
14
17
  "1.8.7" => ["rails40", "rails41"],
18
+ "1.9.2" => ["rails40", "rails41"],
15
19
  "ree" => ["rails40", "rails41"],
16
- "1.9.2" => ["rails21", "rails22", "rails40"],
17
- "1.9.3" => ["rails21", "rails22"],
18
- "2.0.0" => ["rails21", "rails22", "rails23"],
19
- "2.1.0" => ["rails21", "rails22", "rails23"],
20
20
  "jruby-1.6" => ["rails40", "rails41"],
21
21
  "jruby-1.7" => ["rails21", "rails22", "rails23"],
22
22
  "rbx-2.0" => ["rails21", "rails22", "rails23", "rails30", "rails31", "rails32"],
@@ -71,9 +71,10 @@ module Environments
71
71
  version = "jruby-#{JRUBY_VERSION[0..2]}" if defined?(JRUBY_VERSION)
72
72
  version = "rbx-2.0" if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
73
73
 
74
- blacklist = BLACKLIST[version] || []
75
- blacklist.each do |blacklisted|
76
- dirs.delete_if {|d| File.basename(d) == blacklisted }
74
+ BLACKLIST.each do |check_version, blacklisted|
75
+ if version.start_with?(check_version)
76
+ dirs.reject! {|d| blacklisted.include?(File.basename(d)) }
77
+ end
77
78
  end
78
79
 
79
80
  dirs
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rake'
3
+ gem 'rake', '~>10.1.1'
4
4
 
5
5
  gem 'minitest', '~>4.7.5'
6
6
  gem 'mocha', :require => false