newrelic_rpm 2.9.9 → 2.10.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

Files changed (120) hide show
  1. data/CHANGELOG +117 -49
  2. data/bin/mongrel_rpm +2 -2
  3. data/install.rb +42 -33
  4. data/lib/new_relic/agent.rb +149 -39
  5. data/lib/new_relic/agent/agent.rb +139 -122
  6. data/lib/new_relic/agent/busy_calculator.rb +91 -0
  7. data/lib/new_relic/agent/collection_helper.rb +11 -2
  8. data/lib/new_relic/agent/error_collector.rb +33 -27
  9. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
  10. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  11. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
  12. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
  13. data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
  14. data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
  16. data/lib/new_relic/agent/instrumentation/net.rb +7 -11
  17. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
  19. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
  20. data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
  21. data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
  22. data/lib/new_relic/agent/method_tracer.rb +305 -150
  23. data/lib/new_relic/agent/sampler.rb +34 -0
  24. data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
  25. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
  26. data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
  27. data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
  28. data/lib/new_relic/agent/shim_agent.rb +10 -0
  29. data/lib/new_relic/agent/stats_engine.rb +16 -278
  30. data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
  31. data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
  32. data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
  33. data/lib/new_relic/agent/transaction_sampler.rb +73 -67
  34. data/lib/new_relic/agent/worker_loop.rb +69 -68
  35. data/lib/new_relic/commands/deployments.rb +4 -6
  36. data/lib/new_relic/control.rb +121 -60
  37. data/lib/new_relic/control/external.rb +13 -0
  38. data/lib/new_relic/control/merb.rb +2 -0
  39. data/lib/new_relic/control/rails.rb +16 -6
  40. data/lib/new_relic/control/ruby.rb +8 -5
  41. data/lib/new_relic/control/sinatra.rb +18 -0
  42. data/lib/new_relic/delayed_job_injection.rb +25 -0
  43. data/lib/new_relic/histogram.rb +89 -0
  44. data/lib/new_relic/local_environment.rb +64 -30
  45. data/lib/new_relic/metric_data.rb +15 -6
  46. data/lib/new_relic/metric_parser.rb +14 -1
  47. data/lib/new_relic/metric_parser/active_record.rb +14 -0
  48. data/lib/new_relic/metric_parser/controller.rb +5 -2
  49. data/lib/new_relic/metric_parser/external.rb +50 -0
  50. data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
  51. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  52. data/lib/new_relic/metric_spec.rb +39 -20
  53. data/lib/new_relic/metrics.rb +9 -7
  54. data/lib/new_relic/noticed_error.rb +6 -8
  55. data/lib/new_relic/rack/metric_app.rb +5 -4
  56. data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
  57. data/lib/new_relic/rack/newrelic.yml +1 -0
  58. data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
  59. data/lib/new_relic/recipes.rb +1 -1
  60. data/lib/new_relic/stats.rb +40 -26
  61. data/lib/new_relic/transaction_analysis.rb +5 -2
  62. data/lib/new_relic/transaction_sample.rb +134 -55
  63. data/lib/new_relic/version.rb +27 -20
  64. data/lib/new_relic_api.rb +67 -47
  65. data/lib/newrelic_rpm.rb +5 -5
  66. data/lib/tasks/tests.rake +2 -0
  67. data/newrelic.yml +69 -29
  68. data/test/active_record_fixtures.rb +2 -2
  69. data/test/config/newrelic.yml +4 -7
  70. data/test/config/test_control.rb +1 -2
  71. data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
  72. data/test/new_relic/agent/agent_controller_test.rb +274 -0
  73. data/test/new_relic/agent/agent_test_controller.rb +42 -6
  74. data/test/new_relic/agent/busy_calculator_test.rb +79 -0
  75. data/test/new_relic/agent/collection_helper_test.rb +10 -3
  76. data/test/new_relic/agent/error_collector_test.rb +35 -17
  77. data/test/new_relic/agent/method_tracer_test.rb +60 -20
  78. data/test/new_relic/agent/metric_data_test.rb +2 -2
  79. data/test/new_relic/agent/metric_frame_test.rb +51 -0
  80. data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
  81. data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
  82. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  83. data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
  84. data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
  85. data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
  86. data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
  87. data/test/new_relic/agent/transaction_sample_test.rb +53 -38
  88. data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
  89. data/test/new_relic/agent/worker_loop_test.rb +16 -14
  90. data/test/new_relic/control_test.rb +26 -13
  91. data/test/new_relic/metric_parser_test.rb +31 -1
  92. data/test/new_relic/metric_spec_test.rb +2 -2
  93. data/test/new_relic/stats_test.rb +0 -8
  94. data/test/new_relic/version_number_test.rb +31 -1
  95. data/test/test_helper.rb +37 -1
  96. data/ui/controllers/newrelic_controller.rb +19 -11
  97. data/ui/helpers/google_pie_chart.rb +5 -11
  98. data/ui/helpers/newrelic_helper.rb +40 -35
  99. data/ui/views/layouts/newrelic_default.rhtml +7 -7
  100. data/ui/views/newrelic/_sample.rhtml +5 -1
  101. data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
  102. data/ui/views/newrelic/images/textmate.png +0 -0
  103. data/ui/views/newrelic/index.rhtml +13 -1
  104. data/ui/views/newrelic/show_sample.rhtml +5 -2
  105. data/ui/views/newrelic/stylesheets/style.css +54 -3
  106. metadata +65 -145
  107. data/Manifest +0 -143
  108. data/Rakefile +0 -22
  109. data/init.rb +0 -38
  110. data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
  111. data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
  112. data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
  113. data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
  114. data/lib/new_relic/agent/patch_const_missing.rb +0 -125
  115. data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
  116. data/lib/new_relic/metric_parser/database.rb +0 -23
  117. data/newrelic_rpm.gemspec +0 -35
  118. data/test/new_relic/agent/classloader_patch_test.rb +0 -56
  119. data/test/new_relic/agent/controller_test.rb +0 -107
  120. data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -0,0 +1,13 @@
1
+ # This is the control used when starting up in the context of
2
+ # The New Relic Infrastructure Agent. We want to call this
3
+ # out specifically because in this context we are not monitoring
4
+ # the running process, but actually external things.
5
+ require 'new_relic/control/ruby'
6
+
7
+ class NewRelic::Control::External < NewRelic::Control::Ruby
8
+
9
+ def init_config(options={})
10
+ super
11
+ end
12
+
13
+ end
@@ -8,6 +8,8 @@ class NewRelic::Control::Merb < NewRelic::Control
8
8
  end
9
9
 
10
10
  def to_stdout(msg)
11
+ Merb.logger.info("NewRelic ~ " + msg)
12
+ rescue Exception => e
11
13
  STDOUT.puts "NewRelic ~ " + msg
12
14
  end
13
15
 
@@ -21,9 +21,11 @@ class NewRelic::Control::Rails < NewRelic::Control
21
21
  def init_config(options={})
22
22
  rails_config=options[:config]
23
23
  if !agent_enabled?
24
- RAILS_DEFAULT_LOGGER.info "New Relic Agent not running"
24
+ # Might not be running if it does not think mongrel, thin, passenger, etc
25
+ # is running, if it things it's a rake task, or if the agent_enabled is false.
26
+ ::RAILS_DEFAULT_LOGGER.info "New Relic Agent not running."
25
27
  else
26
- RAILS_DEFAULT_LOGGER.info "Starting the New Relic Agent"
28
+ ::RAILS_DEFAULT_LOGGER.info "Starting the New Relic Agent."
27
29
  install_developer_mode rails_config if developer_mode?
28
30
  end
29
31
  end
@@ -41,7 +43,7 @@ class NewRelic::Control::Rails < NewRelic::Control
41
43
  Dependencies.load_paths << controller_path
42
44
  Dependencies.load_paths << helper_path
43
45
  else
44
- to_stdout "ERROR: Rails version #{Rails::VERSION::STRING} too old for developer mode to work."
46
+ to_stdout "ERROR: Rails version #{::Rails::VERSION::STRING} too old for developer mode to work."
45
47
  return
46
48
  end
47
49
  install_devmode_route
@@ -60,6 +62,12 @@ class NewRelic::Control::Rails < NewRelic::Control
60
62
  current_paths << controller_path
61
63
  end
62
64
 
65
+ def to_stdout(message)
66
+ ::RAILS_DEFAULT_LOGGER.info(message)
67
+ rescue Exception => e
68
+ STDOUT.puts(message)
69
+ end
70
+
63
71
  #ActionController::Routing::Routes.reload! unless NewRelic::Control.instance['skip_developer_route']
64
72
 
65
73
  # inform user that the dev edition is available if we are running inside
@@ -86,7 +94,10 @@ class NewRelic::Control::Rails < NewRelic::Control
86
94
  next if self.instance_methods.include? 'draw_with_newrelic_map'
87
95
  def draw_with_newrelic_map
88
96
  draw_without_newrelic_map do | map |
89
- map.named_route 'newrelic_developer', '/newrelic/:action/:id', :controller => 'newrelic' unless NewRelic::Control.instance['skip_developer_route']
97
+ unless NewRelic::Control.instance['skip_developer_route']
98
+ map.named_route 'newrelic_developer', '/newrelic/:action/:id', :controller => 'newrelic'
99
+ map.named_route 'newrelic_file', '/newrelic/file/*file', :controller => 'newrelic', :action=>'file'
100
+ end
90
101
  yield map
91
102
  end
92
103
  end
@@ -106,6 +117,7 @@ class NewRelic::Control::Rails < NewRelic::Control
106
117
  ::Rails.configuration.action_controller.allow_concurrency == true
107
118
  end
108
119
  end
120
+ local_env.append_environment_value('Rails Env') { ENV['RAILS_ENV'] }
109
121
  if rails_version >= NewRelic::VersionNumber.new('2.1.0')
110
122
  local_env.append_gem_list do
111
123
  ::Rails.configuration.gems.map do | gem |
@@ -133,9 +145,7 @@ class NewRelic::Control::Rails < NewRelic::Control
133
145
  def install_shim
134
146
  super
135
147
  require 'new_relic/agent/instrumentation/controller_instrumentation'
136
- require 'new_relic/agent/instrumentation/error_instrumentation'
137
148
  ActionController::Base.send :include, NewRelic::Agent::Instrumentation::ControllerInstrumentation::Shim
138
- Object.send :include, NewRelic::Agent::Instrumentation::ErrorInstrumentation::Shim
139
149
  end
140
150
 
141
151
  end
@@ -4,20 +4,23 @@
4
4
  # It loads the settings from the newrelic.yml section
5
5
  # based on the value of RUBY_ENV or RAILS_ENV.
6
6
  class NewRelic::Control::Ruby < NewRelic::Control
7
-
7
+
8
8
  def env
9
- @env ||= ENV['RUBY_ENV'] || ENV['RAILS_ENV'] || 'development'
9
+ @env ||= ENV['RUBY_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
10
10
  end
11
11
  def root
12
- Dir['.']
12
+ @root ||= ENV['APP_ROOT'] || Dir['.']
13
13
  end
14
14
  # Check a sequence of file locations for newrelic.yml
15
15
  def config_file
16
16
  files = []
17
17
  files << File.join(root,"config","newrelic.yml")
18
18
  files << File.join(root,"newrelic.yml")
19
- files << File.join(ENV["HOME"], ".newrelic", "newrelic.yml")
20
- files << File.join(ENV["HOME"], "newrelic.yml")
19
+ if ENV["HOME"]
20
+ files << File.join(ENV["HOME"], ".newrelic", "newrelic.yml")
21
+ files << File.join(ENV["HOME"], "newrelic.yml")
22
+ end
23
+ files << File.expand_path(ENV["NRCONFIG"]) if ENV["NRCONFIG"]
21
24
  files.each do | file |
22
25
  return File.expand_path(file) if File.exists? file
23
26
  end
@@ -0,0 +1,18 @@
1
+
2
+ require 'new_relic/control/ruby'
3
+
4
+ class NewRelic::Control::Sinatra < NewRelic::Control::Ruby
5
+
6
+ def env
7
+ @env ||= ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
8
+ end
9
+
10
+ # This is the control used when starting up in the context of
11
+ # The New Relic Infrastructure Agent. We want to call this
12
+ # out specifically because in this context we are not monitoring
13
+ # the running process, but actually external things.
14
+ def init_config(options={})
15
+ super
16
+ end
17
+
18
+ end
@@ -0,0 +1,25 @@
1
+ # This installs some code to manually start the agent when a delayed job worker starts.
2
+
3
+ module NewRelic
4
+ module DelayedJobInjection
5
+ extend self
6
+ attr_accessor :worker_name
7
+ end
8
+ end
9
+
10
+ Delayed::Worker.class_eval do
11
+ def initialize_with_new_relic(*args)
12
+ initialize_without_new_relic(*args)
13
+ worker_name = case
14
+ when self.respond_to?(:name) then self.name
15
+ when self.class.respond_to?(:default_name) then self.class.default_name
16
+ end
17
+ dispatcher_instance_id = worker_name || "host:#{Socket.gethostname} pid:#{Process.pid}" rescue "pid:#{Process.pid}"
18
+ self.class.logger.info "RPM Monitoring DJ worker #{dispatcher_instance_id}"
19
+ NewRelic::Agent.manual_start :dispatcher => :delayed_job, :dispatcher_instance_id => dispatcher_instance_id
20
+ NewRelic::DelayedJobInjection.worker_name = worker_name
21
+ end
22
+
23
+ alias initialize_without_new_relic initialize
24
+ alias initialize initialize_with_new_relic
25
+ end if defined?(::Delayed::Worker) and not NewRelic::Control.instance['disable_dj']
@@ -0,0 +1,89 @@
1
+ # Histogram is used for organizing response times
2
+ # into an 'Exponential Histogram'. Feature based in part on DHH proposal:
3
+ # http://37signals.com/svn/posts/1836-the-problem-with-averages
4
+ #
5
+ # Histogram builds a set of buckets of geometrically growing size, with the assumption that most
6
+ # apps have long-tail response times, and therefore you need the most granularity at the lowest
7
+ # r/t level.
8
+ class NewRelic::Histogram
9
+
10
+ # Used to stub out API methods when the agent is not enabled
11
+ module Shim
12
+ def process(response_time); end
13
+ end
14
+ # Stores statistics for response times falling in a particular range.
15
+ # A bucket has a min and max response time. A response time event
16
+ # falls in a bucket if min <= r/t < max. A bucket also
17
+ # has an associated metric for reporting data to RPM. The
18
+ # bucket range is encoded in the metic name
19
+ class Bucket
20
+
21
+ attr_reader :min, :max, :stats
22
+
23
+ def initialize(min, max = nil)
24
+ @min = min
25
+ @max = max
26
+ end
27
+
28
+ def stats
29
+ NewRelic::Agent.get_stats("Response Times/#{min_millis}/#{max_millis}")
30
+ end
31
+
32
+ # This has return value like <=> but does something more
33
+ # than simply compare. If the value falls within range for
34
+ # the bucket, increment count and return 0; otherwise return
35
+ # a value < 0 if the value belongs in a bucket with a lower range
36
+ # you can guess what it returns if the value belongs in a bucket
37
+ # with a higher range. (Hint: it's not 0, and it's not less than zero.)
38
+ def process(value)
39
+ if value < min
40
+ return -1
41
+
42
+ # max == nil means unlimited max (last bucket)
43
+ elsif max && value >= max
44
+ return 1
45
+
46
+ else
47
+ stats.record_data_point(value)
48
+ return 0
49
+ end
50
+ end
51
+
52
+ def min_millis
53
+ (min * 1000).round
54
+ end
55
+
56
+ def max_millis
57
+ max.nil? ? nil : (max * 1000).round
58
+ end
59
+
60
+ def to_s
61
+ "#{min_millis} - #{max_millis}: #{stats.call_count}"
62
+ end
63
+ end
64
+
65
+ attr_reader :buckets
66
+
67
+ # Histogram uses apdex T / 10 as its minimum bucket size, and grows from there.
68
+ # 30 data points should be adequate resolution.
69
+ def initialize(first_bucket_max = 0.010, bucket_count = 30, multiplier = 1.3)
70
+ @buckets = []
71
+
72
+ min = 0
73
+ max = first_bucket_max
74
+
75
+ (bucket_count - 1).times do
76
+ @buckets << Bucket.new(min, max)
77
+ min = max
78
+ max *= multiplier
79
+ end
80
+ @buckets << Bucket.new(max)
81
+ end
82
+
83
+ def process(response_time)
84
+ buckets.each do |bucket|
85
+ found = bucket.process(response_time)
86
+ return if found == 0
87
+ end
88
+ end
89
+ end
@@ -1,10 +1,11 @@
1
1
  require 'set'
2
+ require 'new_relic/version'
2
3
 
3
4
  module NewRelic
4
5
  # An instance of LocalEnvironment is responsible for determining
5
6
  # three things:
6
7
  #
7
- # * Framework - :rails, :merb, :ruby, :test
8
+ # * Framework - :rails, :merb, :ruby, :external, :test
8
9
  # * Dispatcher - A supported dispatcher, or nil (:mongrel, :thin, :passenger, :webrick, etc)
9
10
  # * Dispatcher Instance ID, which distinguishes agents on a single host from each other
10
11
  #
@@ -16,7 +17,7 @@ module NewRelic
16
17
 
17
18
  attr_accessor :dispatcher # mongrel, thin, webrick, or possibly nil
18
19
  attr_accessor :dispatcher_instance_id # used to distinguish instances of a dispatcher from each other, may be nil
19
- attr_accessor :framework # rails, merb, :ruby, test
20
+ attr_accessor :framework # rails, merb, external, ruby, test
20
21
  attr_reader :mongrel # The mongrel instance, if there is one, captured as a convenience
21
22
  attr_reader :processors # The number of cpus, if detected, or nil
22
23
  alias environment dispatcher
@@ -73,6 +74,7 @@ module NewRelic
73
74
  append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
74
75
  append_environment_value('Application root') { File.expand_path(NewRelic::Control.instance.root) }
75
76
  append_environment_value('Ruby version'){ RUBY_VERSION }
77
+ append_environment_value('Ruby description'){ RUBY_DESCRIPTION } if defined? ::RUBY_DESCRIPTION
76
78
  append_environment_value('Ruby platform') { RUBY_PLATFORM }
77
79
  append_environment_value('Ruby patchlevel') { RUBY_PATCHLEVEL }
78
80
  if defined? ::JRUBY_VERSION
@@ -86,11 +88,8 @@ module NewRelic
86
88
  append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
87
89
  # See what the number of cpus is, works only on linux.
88
90
  @processors = append_environment_value('Processors') do
89
- processors = 0
90
- File.read('/proc/cpuinfo').each_line do | line |
91
- processors += 1 if line =~ /^processor\s*:/
92
- end
93
- raise unless processors > 0
91
+ processors = File.readlines('/proc/cpuinfo').select { |line| line =~ /^processor\s*:/ }.size
92
+ raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
94
93
  processors
95
94
  end if File.readable? '/proc/cpuinfo'
96
95
  # The current Rails environment (development, test, or production).
@@ -103,7 +102,7 @@ module NewRelic
103
102
  end
104
103
  end
105
104
  # The name of the database adapter for the current environment.
106
- if defined? ActiveRecord
105
+ if defined? ::ActiveRecord
107
106
  append_environment_value 'Database adapter' do
108
107
  ActiveRecord::Base.configurations[RAILS_ENV]['adapter']
109
108
  end
@@ -111,7 +110,7 @@ module NewRelic
111
110
  ActiveRecord::Migrator.current_version
112
111
  end
113
112
  end
114
- if defined? DataMapper
113
+ if defined? ::DataMapper
115
114
  append_environment_value 'DataMapper version' do
116
115
  require 'dm-core/version'
117
116
  DataMapper::VERSION
@@ -128,28 +127,36 @@ module NewRelic
128
127
  end
129
128
 
130
129
  def mongrel
131
- return @mongrel if @mongrel || ! defined? Mongrel::HttpServer
130
+ # Note that the odd defined? sequence is necessary to work around a bug in an older version
131
+ # of JRuby.
132
+ return @mongrel if @mongrel || ! (defined?(::Mongrel) && defined?(::Mongrel::HttpServer))
132
133
  ObjectSpace.each_object(Mongrel::HttpServer) do |mongrel|
133
134
  @mongrel = mongrel
134
- end unless defined?(JRuby) && !JRuby.runtime.is_object_space_enabled
135
+ end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
135
136
  @mongrel
136
137
  end
137
138
 
138
139
  def unicorn
139
- return @unicorn if @unicorn || ! defined? Unicorn::HttpServer
140
+ return @unicorn if @unicorn || ! (defined?(::Unicorn) && defined?(::Unicorn::HttpServer))
140
141
  ObjectSpace.each_object(Unicorn::HttpServer) do |unicorn|
141
142
  @unicorn = unicorn
142
- end unless defined?(JRuby) && !JRuby.runtime.is_object_space_enabled
143
+ end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
143
144
  @unicorn
144
145
  end
145
146
 
147
+ # Obsolete method for DelayedJob instrumentation support, which is
148
+ # now in the rpm_contrib gem.
149
+ def delayed_worker=(worker)
150
+ $stderr.puts "WARNING: DelayedJob instrumentation has been moved to the rpm_contrib gem."
151
+ end
152
+
146
153
  private
147
154
 
148
155
  # Although you can override the framework with NEWRELIC_DISPATCHER this
149
156
  # is not advisable since it implies certain api's being available.
150
157
  def discover_dispatcher
151
158
  @dispatcher = ENV['NEWRELIC_DISPATCHER'] && ENV['NEWRELIC_DISPATCHER'].to_sym
152
- dispatchers = %w[passenger glassfish thin mongrel litespeed webrick fastcgi unicorn]
159
+ dispatchers = %w[passenger torquebox glassfish thin mongrel litespeed webrick fastcgi unicorn sinatra]
153
160
  while dispatchers.any? && @dispatcher.nil?
154
161
  send 'check_for_'+(dispatchers.shift)
155
162
  end
@@ -158,17 +165,28 @@ module NewRelic
158
165
  def discover_framework
159
166
  # Although you can override the framework with NEWRELIC_FRAMEWORK this
160
167
  # is not advisable since it implies certain api's being available.
168
+ #
169
+ # Note that the odd defined? sequence is necessary to work around a bug in an older version
170
+ # of JRuby.
161
171
  @framework = case
162
- when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
163
- when defined? NewRelic::TEST then :test
164
- when defined? Merb::Plugins then :merb
165
- when defined? Rails then :rails
172
+ when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
173
+ when defined?(::NewRelic::TEST) then :test
174
+ when defined?(::Merb) && defined?(::Merb::Plugins) then :merb
175
+ when defined?(::Rails) then :rails
176
+ when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
177
+ when defined?(::NewRelic::IA) then :external
166
178
  else :ruby
167
179
  end
168
180
  end
169
181
 
182
+ def check_for_torquebox
183
+ return unless defined?(::JRuby) &&
184
+ ( Java::OrgTorqueboxRailsWebDeployers::RailsRackDeployer rescue nil)
185
+ @dispatcher = :torquebox
186
+ end
187
+
170
188
  def check_for_glassfish
171
- return unless defined?(::Java) &&
189
+ return unless defined?(::JRuby) &&
172
190
  (((com.sun.grizzly.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
173
191
  defined?(com::sun::grizzly::jruby::rack::DefaultRackApplicationFactory)) ||
174
192
  ((org.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
@@ -177,9 +195,9 @@ module NewRelic
177
195
  end
178
196
 
179
197
  def check_for_webrick
180
- return unless defined?(WEBrick::VERSION)
198
+ return unless defined?(::WEBrick) && defined?(::WEBrick::VERSION)
181
199
  @dispatcher = :webrick
182
- if defined?(OPTIONS) && OPTIONS.respond_to?(:fetch)
200
+ if defined?(::OPTIONS) && OPTIONS.respond_to?(:fetch)
183
201
  # OPTIONS is set by script/server
184
202
  @dispatcher_instance_id = OPTIONS.fetch(:port)
185
203
  end
@@ -187,13 +205,13 @@ module NewRelic
187
205
  end
188
206
 
189
207
  def check_for_fastcgi
190
- return unless defined? FCGI
208
+ return unless defined?(::FCGI)
191
209
  @dispatcher = :fastcgi
192
210
  end
193
211
 
194
212
  # this case covers starting by mongrel_rails
195
213
  def check_for_mongrel
196
- return unless defined?(Mongrel::HttpServer)
214
+ return unless defined?(::Mongrel) && defined?(::Mongrel::HttpServer)
197
215
  @dispatcher = :mongrel
198
216
 
199
217
  # Get the port from the server if it's started
@@ -203,10 +221,10 @@ module NewRelic
203
221
  end
204
222
 
205
223
  # Get the port from the configurator if one was created
206
- if @dispatcher_instance_id.nil? && defined?(Mongrel::Configurator)
224
+ if @dispatcher_instance_id.nil? && defined?(::Mongrel::Configurator)
207
225
  ObjectSpace.each_object(Mongrel::Configurator) do |mongrel|
208
226
  @dispatcher_instance_id = mongrel.defaults[:port] && mongrel.defaults[:port].to_s
209
- end unless defined?(JRuby) && !JRuby.runtime.is_object_space_enabled
227
+ end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
210
228
  end
211
229
 
212
230
  # Still can't find the port. Let's look at ARGV to fall back
@@ -214,16 +232,31 @@ module NewRelic
214
232
  end
215
233
 
216
234
  def check_for_unicorn
217
- return unless defined?(Unicorn::HttpServer)
235
+ return unless defined?(::Unicorn) && defined?(::Unicorn::HttpServer)
218
236
 
219
237
  # unlike mongrel, unicorn manages muliple threads and ports, so we
220
238
  # have to map multiple processes into one instance, as we do with passenger
221
239
  @dispatcher = :unicorn
222
240
  end
223
241
 
242
+ def check_for_sinatra
243
+ return unless defined?(::Sinatra) && defined?(::Sinatra::Base)
244
+
245
+ begin
246
+ version = ::Sinatra::VERSION
247
+ rescue
248
+ $stderr.puts("Error determining Sinatra version")
249
+ end
250
+
251
+ if ::NewRelic::VersionNumber.new('0.9.2') > version
252
+ $stderr.puts("Your Sinatra version is #{version}, we highly recommend upgrading to >=0.9.2")
253
+ end
254
+
255
+ @dispatcher = :sinatra
256
+ end
224
257
 
225
258
  def check_for_thin
226
- if defined? Thin::Server
259
+ if defined?(::Thin) && defined?(::Thin::Server)
227
260
  # This case covers the thin web dispatcher
228
261
  # Same issue as above- we assume only one instance per process
229
262
  ObjectSpace.each_object(Thin::Server) do |thin_dispatcher|
@@ -240,7 +273,7 @@ module NewRelic
240
273
  end
241
274
  end # each thin instance
242
275
  end
243
- if defined?(Thin::VERSION) && !@dispatcher
276
+ if defined?(::Thin) && defined?(::Thin::VERSION) && !@dispatcher
244
277
  @dispatcher = :thin
245
278
  @dispatcher_instance_id = default_port
246
279
  end
@@ -253,11 +286,12 @@ module NewRelic
253
286
  end
254
287
 
255
288
  def check_for_passenger
256
- if defined?(Passenger::AbstractServer) || defined?(IN_PHUSION_PASSENGER)
289
+ if (defined?(::Passenger) && defined?(::Passenger::AbstractServer)) || defined?(::IN_PHUSION_PASSENGER)
257
290
  @dispatcher = :passenger
258
291
  end
259
292
  end
260
-
293
+
294
+
261
295
  def default_port
262
296
  require 'optparse'
263
297
  # If nothing else is found, use the 3000 default