newrelic_rpm 2.13.4 → 2.13.5.beta1

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 (57) hide show
  1. data/CHANGELOG +9 -0
  2. data/lib/new_relic/agent.rb +2 -1
  3. data/lib/new_relic/agent/agent.rb +393 -204
  4. data/lib/new_relic/agent/error_collector.rb +113 -43
  5. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +14 -16
  6. data/lib/new_relic/agent/instrumentation/queue_time.rb +201 -0
  7. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  8. data/lib/new_relic/agent/instrumentation/sequel.rb +95 -0
  9. data/lib/new_relic/agent/method_tracer.rb +391 -313
  10. data/lib/new_relic/agent/samplers/cpu_sampler.rb +43 -41
  11. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +2 -0
  12. data/lib/new_relic/agent/samplers/memory_sampler.rb +122 -120
  13. data/lib/new_relic/agent/samplers/object_sampler.rb +2 -0
  14. data/lib/new_relic/agent/stats_engine/metric_stats.rb +0 -1
  15. data/lib/new_relic/agent/stats_engine/samplers.rb +20 -14
  16. data/lib/new_relic/agent/stats_engine/transactions.rb +35 -7
  17. data/lib/new_relic/control.rb +12 -17
  18. data/lib/new_relic/control/configuration.rb +1 -0
  19. data/lib/new_relic/control/frameworks/rails.rb +7 -4
  20. data/lib/new_relic/control/frameworks/rails3.rb +1 -1
  21. data/lib/new_relic/control/instrumentation.rb +2 -18
  22. data/lib/new_relic/local_environment.rb +117 -59
  23. data/lib/new_relic/rack/developer_mode.rb +212 -207
  24. data/lib/new_relic/recipes.rb +0 -9
  25. data/lib/new_relic/stats.rb +87 -81
  26. data/lib/new_relic/transaction_analysis.rb +1 -1
  27. data/lib/new_relic/version.rb +2 -2
  28. data/lib/newrelic_rpm.rb +2 -3
  29. data/lib/tasks/tests.rake +5 -1
  30. data/newrelic_rpm.gemspec +14 -5
  31. data/test/config/test_control.rb +14 -2
  32. data/test/new_relic/agent/active_record_instrumentation_test.rb +342 -119
  33. data/test/new_relic/agent/add_method_tracer_test.rb +158 -0
  34. data/test/new_relic/agent/agent_connect_test.rb +295 -0
  35. data/test/new_relic/agent/agent_controller_test.rb +86 -18
  36. data/test/new_relic/agent/agent_start_test.rb +326 -0
  37. data/test/new_relic/agent/agent_start_worker_thread_test.rb +157 -0
  38. data/test/new_relic/agent/apdex_from_server_test.rb +9 -0
  39. data/test/new_relic/agent/collection_helper_test.rb +3 -1
  40. data/test/new_relic/agent/error_collector_notice_error_test.rb +255 -0
  41. data/test/new_relic/agent/error_collector_test.rb +6 -0
  42. data/test/new_relic/agent/method_tracer_test.rb +2 -2
  43. data/test/new_relic/agent/method_tracer_trace_execution_scoped_test.rb +233 -0
  44. data/test/new_relic/agent/net_instrumentation_test.rb +17 -12
  45. data/test/new_relic/agent/queue_time_test.rb +333 -0
  46. data/test/new_relic/agent/rpm_agent_test.rb +4 -2
  47. data/test/new_relic/agent/stats_engine/samplers_test.rb +27 -1
  48. data/test/new_relic/agent/transaction_sample_subtest_test.rb +56 -0
  49. data/test/new_relic/agent/transaction_sample_test.rb +103 -174
  50. data/test/new_relic/agent/transaction_sampler_test.rb +9 -2
  51. data/test/new_relic/control_test.rb +7 -2
  52. data/test/new_relic/metric_spec_test.rb +1 -1
  53. data/test/new_relic/stats_test.rb +112 -15
  54. data/test/test_helper.rb +79 -16
  55. data/ui/helpers/developer_mode_helper.rb +2 -0
  56. metadata +19 -7
  57. data/lib/new_relic_api.rb +0 -276
@@ -1,5 +1,7 @@
1
1
  require 'yaml'
2
+ require 'conditional_vendored_metric_parser'
2
3
  require 'new_relic/local_environment'
4
+
3
5
  require 'singleton'
4
6
  require 'erb'
5
7
  require 'socket'
@@ -11,6 +13,9 @@ require 'new_relic/control/configuration'
11
13
  require 'new_relic/control/server_methods'
12
14
  require 'new_relic/control/instrumentation'
13
15
 
16
+ require 'new_relic/agent'
17
+ require 'new_relic/delayed_job_injection'
18
+
14
19
  module NewRelic
15
20
 
16
21
  # The Control is a singleton responsible for the startup and
@@ -42,21 +47,19 @@ module NewRelic
42
47
  def instance
43
48
  @instance ||= new_instance
44
49
  end
50
+
51
+ def mark_browser_request
52
+ Thread::current[:browser_request] = true
53
+ end
54
+
45
55
 
46
56
  # Create the concrete class for environment specific behavior:
47
57
  def new_instance
48
58
  @local_env = NewRelic::LocalEnvironment.new
49
59
  if @local_env.framework == :test
50
- # You can set this env var if you want to run the tests
51
- # without Rails.
52
60
  config = File.expand_path("../../../test/config/newrelic.yml", __FILE__)
53
- if ENV['SKIP_RAILS']
54
- require "new_relic/control/frameworks/ruby.rb"
55
- NewRelic::Control::Frameworks::Ruby.new @local_env, config
56
- else
57
- require "config/test_control"
58
- NewRelic::Control::Frameworks::Test.new @local_env, config
59
- end
61
+ require "config/test_control"
62
+ NewRelic::Control::Frameworks::Test.new @local_env, config
60
63
  else
61
64
  begin
62
65
  require "new_relic/control/frameworks/#{@local_env.framework}.rb"
@@ -93,16 +96,8 @@ module NewRelic
93
96
  # is called one or more times.
94
97
  #
95
98
  def init_plugin(options={})
96
- require 'conditional_vendored_metric_parser'
97
-
98
99
  options['app_name'] = ENV['NEWRELIC_APP_NAME'] if ENV['NEWRELIC_APP_NAME']
99
100
 
100
- require 'new_relic/agent'
101
-
102
- # Load the DJ injection now. If you do it sooner, DJ might not be loaded and
103
- # you'll miss it.
104
- require 'new_relic/delayed_job_injection'
105
-
106
101
  # Merge the stringified options into the config as overrides:
107
102
  logger_override = options.delete(:log)
108
103
  environment_name = options.delete(:env) and self.env = environment_name
@@ -63,6 +63,7 @@ module NewRelic
63
63
  # Always initialized with a default
64
64
  fetch('apdex_t').to_f
65
65
  end
66
+
66
67
  def license_key
67
68
  fetch('license_key')
68
69
  end
@@ -1,7 +1,8 @@
1
1
  # Control subclass instantiated when Rails is detected. Contains
2
2
  # Rails specific configuration, instrumentation, environment values,
3
3
  # etc.
4
- class NewRelic::Control::Frameworks::Rails < NewRelic::Control
4
+ require 'new_relic/control/frameworks/ruby'
5
+ class NewRelic::Control::Frameworks::Rails < NewRelic::Control::Frameworks::Ruby
5
6
 
6
7
  def env
7
8
  @env ||= RAILS_ENV.dup
@@ -120,11 +121,13 @@ class NewRelic::Control::Frameworks::Rails < NewRelic::Control
120
121
  end
121
122
  end
122
123
  end
123
-
124
+
124
125
  def install_shim
125
126
  super
126
127
  require 'new_relic/agent/instrumentation/controller_instrumentation'
127
- ActionController::Base.send :include, NewRelic::Agent::Instrumentation::ControllerInstrumentation::Shim
128
+ ::ActionController::Base.class_eval {
129
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation::Shim
130
+ }
128
131
  end
129
-
130
132
  end
133
+
@@ -9,7 +9,7 @@ class NewRelic::Control::Frameworks::Rails3 < NewRelic::Control::Frameworks::Rai
9
9
  end
10
10
 
11
11
  def root
12
- @root ||= Rails.root.to_s
12
+ @root ||= ::Rails.root.to_s
13
13
  end
14
14
 
15
15
  def logger
@@ -32,25 +32,9 @@ module NewRelic
32
32
  @instrumentation_files << pattern
33
33
  end
34
34
  end
35
-
36
- def _delayed_instrumentation
37
- Rails.configuration.after_initialize do
38
- _install_instrumentation
39
- end
40
- rescue
41
- _install_instrumentation
42
- end
43
-
35
+
44
36
  def install_instrumentation
45
- if defined?(Rails) && !Rails.initialized?
46
- _delayed_instrumentation
47
- else
48
- _install_instrumentation
49
- end
50
- rescue NameError
51
- # needed in the rails 3 case, where Rails.initialized? raises
52
- # an error if rails has not been initialised. which is totally sane.
53
- _delayed_instrumentation
37
+ _install_instrumentation
54
38
  end
55
39
 
56
40
  def load_samplers
@@ -42,7 +42,7 @@ module NewRelic
42
42
  # settings. Must pass either a value or a block. Block
43
43
  # is called to get the value and any raised errors are
44
44
  # silently ignored.
45
- def append_environment_value name, value = nil
45
+ def append_environment_value(name, value = nil)
46
46
  value = yield if block_given?
47
47
  @config[name] = value if value
48
48
  rescue Exception
@@ -73,35 +73,49 @@ module NewRelic
73
73
  @dispatcher_instance_id
74
74
  end
75
75
 
76
- # Collect base statistics about the environment and record them for
77
- # comparison and change detection.
78
- def gather_environment_info
79
- append_environment_value 'Framework', @framework.to_s
80
- append_environment_value 'Dispatcher', @dispatcher.to_s if @dispatcher
81
- append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
82
- # This just creates a lot of keys
83
- # append_environment_value('Application root') { File.expand_path(NewRelic::Control.instance.root) }
76
+ def gather_ruby_info
84
77
  append_environment_value('Ruby version'){ RUBY_VERSION }
85
78
  append_environment_value('Ruby description'){ RUBY_DESCRIPTION } if defined? ::RUBY_DESCRIPTION
86
79
  append_environment_value('Ruby platform') { RUBY_PLATFORM }
87
80
  append_environment_value('Ruby patchlevel') { RUBY_PATCHLEVEL }
81
+ # room here for other ruby implementations, when.
88
82
  if defined? ::JRUBY_VERSION
89
- append_environment_value('JRuby version') { JRUBY_VERSION }
90
- append_environment_value('Java VM version') { ENV_JAVA['java.vm.version']}
83
+ gather_jruby_info
91
84
  end
92
- append_environment_value('OS version') { `uname -v` }
93
- append_environment_value('OS') { `uname -s` } ||
94
- append_environment_value('OS') { ENV['OS'] }
95
- append_environment_value('Arch') { `uname -p` } ||
96
- append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
97
- # See what the number of cpus is, works only on linux.
85
+ end
86
+
87
+ def gather_jruby_info
88
+ append_environment_value('JRuby version') { JRUBY_VERSION }
89
+ append_environment_value('Java VM version') { ENV_JAVA['java.vm.version']}
90
+ end
91
+
92
+ # See what the number of cpus is, works only on linux.
93
+ def gather_cpu_info
94
+ return unless File.readable? '/proc/cpuinfo'
98
95
  @processors = append_environment_value('Processors') do
99
96
  processors = File.readlines('/proc/cpuinfo').select { |line| line =~ /^processor\s*:/ }.size
100
97
  raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
101
98
  processors
102
- end if File.readable? '/proc/cpuinfo'
103
- # The current Rails environment (development, test, or production).
104
- append_environment_value('Environment') { NewRelic::Control.instance.env }
99
+ end
100
+ end
101
+
102
+ def gather_architecture_info
103
+ append_environment_value('Arch') { `uname -p` } ||
104
+ append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
105
+ end
106
+
107
+ def gather_os_info
108
+ append_environment_value('OS version') { `uname -v` }
109
+ append_environment_value('OS') { `uname -s` } ||
110
+ append_environment_value('OS') { ENV['OS'] }
111
+ end
112
+
113
+ def gather_system_info
114
+ gather_architecture_info
115
+ gather_cpu_info
116
+ end
117
+
118
+ def gather_revision_info
105
119
  # Look for a capistrano file indicating the current revision:
106
120
  rev_file = File.join(NewRelic::Control.instance.root, "REVISION")
107
121
  if File.readable?(rev_file) && File.size(rev_file) < 64
@@ -109,22 +123,56 @@ module NewRelic
109
123
  File.open(rev_file) { | file | file.readline.strip }
110
124
  end
111
125
  end
112
- # The name of the database adapter for the current environment.
113
- if defined? ::ActiveRecord
114
- append_environment_value 'Database adapter' do
115
- ActiveRecord::Base.configurations[RAILS_ENV]['adapter']
116
- end
117
- append_environment_value 'Database schema version' do
118
- ActiveRecord::Migrator.current_version
126
+ end
127
+
128
+ def gather_ar_adapter_info
129
+ # The name of the database adapter for the current environment.
130
+ append_environment_value 'Database adapter' do
131
+ if defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
132
+ ActiveRecord::Base.respond_to?(:configurations)
133
+ config = ActiveRecord::Base.configurations[NewRelic::Control.instance.env]
134
+ if config
135
+ config['adapter']
136
+ end
119
137
  end
120
138
  end
139
+ append_environment_value 'Database schema version' do
140
+ ActiveRecord::Migrator.current_version
141
+ end
142
+ end
143
+
144
+ def gather_dm_adapter_info
145
+ append_environment_value 'DataMapper version' do
146
+ require 'dm-core/version'
147
+ DataMapper::VERSION
148
+ end
149
+ end
150
+
151
+ def gather_db_info
152
+ # room here for more database adapters, when.
153
+ if defined? ::ActiveRecord
154
+ gather_ar_adapter_info
155
+ end
121
156
  if defined? ::DataMapper
122
- append_environment_value 'DataMapper version' do
123
- require 'dm-core/version'
124
- DataMapper::VERSION
125
- end
157
+ gather_dm_adapter_info
126
158
  end
127
159
  end
160
+
161
+ # Collect base statistics about the environment and record them for
162
+ # comparison and change detection.
163
+ def gather_environment_info
164
+ append_environment_value 'Framework', @framework.to_s
165
+ append_environment_value 'Dispatcher', @dispatcher.to_s if @dispatcher
166
+ append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
167
+ append_environment_value('Environment') { NewRelic::Control.instance.env }
168
+
169
+ # miscellaneous other helpful debugging information
170
+ gather_ruby_info
171
+ gather_system_info
172
+ gather_revision_info
173
+ gather_db_info
174
+ end
175
+
128
176
  # Take a snapshot of the environment information for this application
129
177
  # Returns an associative array
130
178
  def snapshot
@@ -134,30 +182,32 @@ module NewRelic
134
182
  i
135
183
  end
136
184
 
185
+ def working_juby?
186
+ !(defined?(::JRuby) && Jruby.respond_to?(:runtime) && !JRuby.runtime.is_object_space_enabled)
187
+ end
188
+
189
+ def find_class_in_object_space(klass)
190
+ ObjectSpace.each_object(klass) do |x|
191
+ return x
192
+ end
193
+ end
194
+
137
195
  def mongrel
138
- # Note that the odd defined? sequence is necessary to work around a bug in an older version
139
- # of JRuby.
140
- return @mongrel if @mongrel || ! (defined?(::Mongrel) && defined?(::Mongrel::HttpServer))
141
- ObjectSpace.each_object(Mongrel::HttpServer) do |mongrel|
142
- @mongrel = mongrel
143
- end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
196
+ return @mongrel if @mongrel
197
+ if defined?(::Mongrel) && defined?(::Mongrel::HttpServer) && working_jruby?
198
+ @mongrel = find_class_in_object_space(::Mongrel::HttpServer)
199
+ end
144
200
  @mongrel
145
201
  end
146
202
 
147
203
  def unicorn
148
- return @unicorn if @unicorn || ! (defined?(::Unicorn) && defined?(::Unicorn::HttpServer))
149
- ObjectSpace.each_object(Unicorn::HttpServer) do |unicorn|
150
- @unicorn = unicorn
151
- end unless defined?(::JRuby) && !JRuby.runtime.is_object_space_enabled
204
+ return @unicorn if @unicorn
205
+ if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && working_jruby?
206
+ @unicorn = find_class_in_object_space(::Unicorn::HttpServer)
207
+ end
152
208
  @unicorn
153
209
  end
154
210
 
155
- # Obsolete method for DelayedJob instrumentation support. Now all DJ instrumentation
156
- # is bundled in the newrelic_rpm gem and nobody should be invoking this method.
157
- def delayed_worker=(worker)
158
- $stderr.puts "WARNING: obsolete call to delayed_worker=(worker). Please remove custom DJ instrumentation."
159
- end
160
-
161
211
  private
162
212
 
163
213
  # Although you can override the framework with NEWRELIC_DISPATCHER this
@@ -177,14 +227,14 @@ module NewRelic
177
227
  # Note that the odd defined? sequence is necessary to work around a bug in an older version
178
228
  # of JRuby.
179
229
  @framework ||= case
180
- when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
181
- when defined?(::NewRelic::TEST) then :test
182
- when defined?(::Merb) && defined?(::Merb::Plugins) then :merb
183
- when defined?(::Rails) then check_rails_version
184
- when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
185
- when defined?(::NewRelic::IA) then :external
186
- else :ruby
187
- end
230
+ when ENV['NEWRELIC_FRAMEWORK'] then ENV['NEWRELIC_FRAMEWORK'].to_sym
231
+ when defined?(::NewRelic::TEST) then :test
232
+ when defined?(::Merb) && defined?(::Merb::Plugins) then :merb
233
+ when defined?(::Rails) then check_rails_version
234
+ when defined?(::Sinatra) && defined?(::Sinatra::Base) then :sinatra
235
+ when defined?(::NewRelic::IA) then :external
236
+ else :ruby
237
+ end
188
238
  end
189
239
 
190
240
  def check_rails_version
@@ -197,7 +247,7 @@ module NewRelic
197
247
 
198
248
  def check_for_torquebox
199
249
  return unless defined?(::JRuby) &&
200
- ( Java::OrgTorqueboxRailsWebDeployers::RailsRackDeployer rescue nil)
250
+ ( Java::OrgTorqueboxRailsWebDeployers::RailsRackDeployer rescue nil)
201
251
  @dispatcher = :torquebox
202
252
  end
203
253
 
@@ -205,12 +255,20 @@ module NewRelic
205
255
  return unless defined?(::JRuby) &&
206
256
  (((com.sun.grizzly.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
207
257
  defined?(com::sun::grizzly::jruby::rack::DefaultRackApplicationFactory)) ||
208
- ((org.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
209
- defined?(org::jruby::rack::DefaultRackApplicationFactory)) ||
210
- defined?(::GlassFish::Server))
258
+ (jruby_rack? && defined?(::GlassFish::Server)))
211
259
  @dispatcher = :glassfish
212
260
  end
213
261
 
262
+ def check_for_trinidad
263
+ return unless defined?(::JRuby) && jruby_rack? && defined?(::Trinidad::Server)
264
+ @dispatcher = :trinidad
265
+ end
266
+
267
+ def jruby_rack?
268
+ ((org.jruby.rack.DefaultRackApplicationFactory rescue nil) &&
269
+ defined?(org::jruby::rack::DefaultRackApplicationFactory))
270
+ end
271
+
214
272
  def check_for_webrick
215
273
  return unless defined?(::WEBrick) && defined?(::WEBrick::VERSION)
216
274
  @dispatcher = :webrick
@@ -2,256 +2,261 @@ require 'rack'
2
2
  require 'rack/request'
3
3
  require 'rack/response'
4
4
  require 'rack/file'
5
+ require 'new_relic/metric_parser/metric_parser'
6
+ require 'new_relic/collection_helper'
5
7
 
6
- module NewRelic::Rack
7
- class DeveloperMode
8
+ module NewRelic
9
+ module Rack
10
+ class DeveloperMode
8
11
 
9
- VIEW_PATH = File.expand_path('../../../../ui/views/', __FILE__)
10
- HELPER_PATH = File.expand_path('../../../../ui/helpers/', __FILE__)
11
- require File.join(HELPER_PATH, 'developer_mode_helper.rb')
12
+ VIEW_PATH = File.expand_path('../../../../ui/views/', __FILE__)
13
+ HELPER_PATH = File.expand_path('../../../../ui/helpers/', __FILE__)
14
+ require File.join(HELPER_PATH, 'developer_mode_helper.rb')
12
15
 
13
- include NewRelic::DeveloperModeHelper
14
16
 
15
- def initialize(app)
16
- @app = app
17
- end
17
+ include NewRelic::DeveloperModeHelper
18
18
 
19
- def call(env)
20
- return @app.call(env) unless /^\/newrelic/ =~ Rack::Request.new(env).path_info
21
- dup._call(env)
22
- end
19
+ def initialize(app)
20
+ @app = app
21
+ end
23
22
 
24
- protected
25
-
26
- def _call(env)
27
- @req = Rack::Request.new(env)
28
- @rendered = false
29
- case @req.path_info
30
- when /profile/
31
- profile
32
- when /file/
33
- Rack::File.new(VIEW_PATH).call(env)
34
- when /index/
35
- index
36
- when /threads/
37
- threads
38
- when /reset/
39
- reset
40
- when /show_sample_detail/
41
- show_sample_data
42
- when /show_sample_summary/
43
- show_sample_data
44
- when /show_sample_sql/
45
- show_sample_data
46
- when /explain_sql/
47
- explain_sql
48
- when /show_source/
49
- show_source
50
- when /^\/newrelic\/?$/
51
- index
52
- else
53
- @app.call(env)
54
- end
55
- end
23
+ def call(env)
24
+ return @app.call(env) unless /^\/newrelic/ =~ Rack::Request.new(env).path_info
25
+ dup._call(env)
26
+ end
56
27
 
57
- private
28
+ protected
29
+
30
+ def _call(env)
31
+ @req = Rack::Request.new(env)
32
+ @rendered = false
33
+ case @req.path_info
34
+ when /profile/
35
+ profile
36
+ when /file/
37
+ Rack::File.new(VIEW_PATH).call(env)
38
+ when /index/
39
+ index
40
+ when /threads/
41
+ threads
42
+ when /reset/
43
+ reset
44
+ when /show_sample_detail/
45
+ show_sample_data
46
+ when /show_sample_summary/
47
+ show_sample_data
48
+ when /show_sample_sql/
49
+ show_sample_data
50
+ when /explain_sql/
51
+ explain_sql
52
+ when /show_source/
53
+ show_source
54
+ when /^\/newrelic\/?$/
55
+ index
56
+ else
57
+ @app.call(env)
58
+ end
59
+ end
58
60
 
59
- def index
60
- get_samples
61
- render(:index)
62
- end
61
+ private
63
62
 
64
- def reset
65
- NewRelic::Agent.instance.transaction_sampler.reset!
66
- Rack::Response.new{|r| r.redirect('/newrelic/')}.finish
67
- end
63
+ def index
64
+ get_samples
65
+ render(:index)
66
+ end
68
67
 
69
- def explain_sql
70
- get_segment
68
+ def reset
69
+ NewRelic::Agent.instance.transaction_sampler.reset!
70
+ Rack::Response.new{|r| r.redirect('/newrelic/')}.finish
71
+ end
71
72
 
72
- return render(:sample_not_found) unless @sample
73
+ def explain_sql
74
+ get_segment
73
75
 
74
- @sql = @segment[:sql]
75
- @trace = @segment[:backtrace]
76
+ return render(:sample_not_found) unless @sample
76
77
 
77
- if NewRelic::Agent.agent.record_sql == :obfuscated
78
- @obfuscated_sql = @segment.obfuscated_sql
79
- end
78
+ @sql = @segment[:sql]
79
+ @trace = @segment[:backtrace]
80
80
 
81
- explanations = @segment.explain_sql
82
- if explanations
83
- @explanation = explanations.first
84
- if !@explanation.blank?
85
- first_row = @explanation.first
86
- # Show the standard headers if it looks like a mysql explain plan
87
- # Otherwise show blank headers
88
- if first_row.length < NewRelic::MYSQL_EXPLAIN_COLUMNS.length
89
- @row_headers = nil
90
- else
91
- @row_headers = NewRelic::MYSQL_EXPLAIN_COLUMNS
81
+ if NewRelic::Agent.agent.record_sql == :obfuscated
82
+ @obfuscated_sql = @segment.obfuscated_sql
92
83
  end
93
- end
94
- end
95
- render(:explain_sql)
96
- end
97
-
98
- def profile
99
- NewRelic::Control.instance.profiling = params['start'] == 'true'
100
- index
101
- end
102
84
 
103
- def threads
104
- render(:threads)
105
- end
106
-
107
- def render(view, layout=true)
108
- add_rack_array = true
109
- if view.is_a? Hash
110
- layout = false
111
- if view[:object]
112
- object = view[:object]
85
+ explanations = @segment.explain_sql
86
+ if explanations
87
+ @explanation = explanations.first
88
+ if !@explanation.blank?
89
+ first_row = @explanation.first
90
+ # Show the standard headers if it looks like a mysql explain plan
91
+ # Otherwise show blank headers
92
+ if first_row.length < NewRelic::MYSQL_EXPLAIN_COLUMNS.length
93
+ @row_headers = nil
94
+ else
95
+ @row_headers = NewRelic::MYSQL_EXPLAIN_COLUMNS
96
+ end
97
+ end
98
+ end
99
+ render(:explain_sql)
113
100
  end
114
101
 
115
- if view[:collection]
116
- return view[:collection].map do |object|
117
- render({:partial => view[:partial], :object => object})
118
- end.join(' ')
102
+ def profile
103
+ NewRelic::Control.instance.profiling = params['start'] == 'true'
104
+ index
119
105
  end
120
106
 
121
- if view[:partial]
122
- add_rack_array = false
123
- view = "_#{view[:partial]}"
107
+ def threads
108
+ render(:threads)
124
109
  end
125
- end
126
- binding = Proc.new {}.binding
127
- if layout
128
- body = render_with_layout(view) do
129
- render_without_layout(view, binding)
110
+
111
+ def render(view, layout=true)
112
+ add_rack_array = true
113
+ if view.is_a? Hash
114
+ layout = false
115
+ if view[:object]
116
+ object = view[:object]
117
+ end
118
+
119
+ if view[:collection]
120
+ return view[:collection].map do |object|
121
+ render({:partial => view[:partial], :object => object})
122
+ end.join(' ')
123
+ end
124
+
125
+ if view[:partial]
126
+ add_rack_array = false
127
+ view = "_#{view[:partial]}"
128
+ end
129
+ end
130
+ binding = Proc.new {}.binding
131
+ if layout
132
+ body = render_with_layout(view) do
133
+ render_without_layout(view, binding)
134
+ end
135
+ else
136
+ body = render_without_layout(view, binding)
137
+ end
138
+ if add_rack_array
139
+ Rack::Response.new(body).finish
140
+ else
141
+ body
142
+ end
130
143
  end
131
- else
132
- body = render_without_layout(view, binding)
133
- end
134
- if add_rack_array
135
- Rack::Response.new(body).finish
136
- else
137
- body
138
- end
139
- end
140
144
 
141
- # You have to call this with a block - the contents returned from
142
- # that block are interpolated into the layout
143
- def render_with_layout(view)
144
- body = ERB.new(File.read(File.join(VIEW_PATH, 'layouts/newrelic_default.rhtml')))
145
- body.result(Proc.new {}.binding)
146
- end
145
+ # You have to call this with a block - the contents returned from
146
+ # that block are interpolated into the layout
147
+ def render_with_layout(view)
148
+ body = ERB.new(File.read(File.join(VIEW_PATH, 'layouts/newrelic_default.rhtml')))
149
+ body.result(Proc.new {}.binding)
150
+ end
147
151
 
148
- # you have to pass a binding to this (a proc) so that ERB can have
149
- # access to helper functions and local variables
150
- def render_without_layout(view, binding)
151
- ERB.new(File.read(File.join(VIEW_PATH, 'newrelic', view.to_s + '.rhtml')), nil, nil, 'frobnitz').result(binding)
152
- end
152
+ # you have to pass a binding to this (a proc) so that ERB can have
153
+ # access to helper functions and local variables
154
+ def render_without_layout(view, binding)
155
+ ERB.new(File.read(File.join(VIEW_PATH, 'newrelic', view.to_s + '.rhtml')), nil, nil, 'frobnitz').result(binding)
156
+ end
153
157
 
154
- def content_tag(tag, contents, opts={})
155
- opt_values = opts.map {|k, v| "#{k}=\"#{v}\"" }.join(' ')
156
- "<#{tag} #{opt_values}>#{contents}</#{tag}>"
157
- end
158
+ def content_tag(tag, contents, opts={})
159
+ opt_values = opts.map {|k, v| "#{k}=\"#{v}\"" }.join(' ')
160
+ "<#{tag} #{opt_values}>#{contents}</#{tag}>"
161
+ end
158
162
 
159
- def sample
160
- @sample || @samples[0]
161
- end
163
+ def sample
164
+ @sample || @samples[0]
165
+ end
162
166
 
163
- def params
164
- @req.params
165
- end
167
+ def params
168
+ @req.params
169
+ end
166
170
 
167
- def segment
168
- @segment
169
- end
171
+ def segment
172
+ @segment
173
+ end
170
174
 
171
175
 
172
- # show the selected source file with the highlighted selected line
173
- def show_source
174
- @filename = params['file']
175
- line_number = params['line'].to_i
176
+ # show the selected source file with the highlighted selected line
177
+ def show_source
178
+ @filename = params['file']
179
+ line_number = params['line'].to_i
176
180
 
177
- if !File.readable?(@filename)
178
- @source="<p>Unable to read #{@filename}.</p>"
179
- return
180
- end
181
- begin
182
- file = File.new(@filename, 'r')
183
- rescue => e
184
- @source="<p>Unable to access the source file #{@filename} (#{e.message}).</p>"
185
- return
186
- end
187
- @source = ""
188
-
189
- @source << "<pre>"
190
- file.each_line do |line|
191
- # place an anchor 6 lines above the selected line (if the line # < 6)
192
- if file.lineno == line_number - 6
193
- @source << "</pre><pre id = 'selected_line'>"
194
- @source << line.rstrip
195
- @source << "</pre><pre>"
196
-
197
- # highlight the selected line
198
- elsif file.lineno == line_number
199
- @source << "</pre><pre class = 'selected_source_line'>"
200
- @source << line.rstrip
201
- @source << "</pre><pre>"
202
- else
203
- @source << line
181
+ if !File.readable?(@filename)
182
+ @source="<p>Unable to read #{@filename}.</p>"
183
+ return
184
+ end
185
+ begin
186
+ file = File.new(@filename, 'r')
187
+ rescue => e
188
+ @source="<p>Unable to access the source file #{@filename} (#{e.message}).</p>"
189
+ return
190
+ end
191
+ @source = ""
192
+
193
+ @source << "<pre>"
194
+ file.each_line do |line|
195
+ # place an anchor 6 lines above the selected line (if the line # < 6)
196
+ if file.lineno == line_number - 6
197
+ @source << "</pre><pre id = 'selected_line'>"
198
+ @source << line.rstrip
199
+ @source << "</pre><pre>"
200
+
201
+ # highlight the selected line
202
+ elsif file.lineno == line_number
203
+ @source << "</pre><pre class = 'selected_source_line'>"
204
+ @source << line.rstrip
205
+ @source << "</pre><pre>"
206
+ else
207
+ @source << line
208
+ end
209
+ end
210
+ render(:show_source)
204
211
  end
205
- end
206
- render(:show_source)
207
- end
208
212
 
209
- def show_sample_data
210
- get_sample
213
+ def show_sample_data
214
+ get_sample
211
215
 
212
- return render(:sample_not_found) unless @sample
216
+ return render(:sample_not_found) unless @sample
213
217
 
214
- @request_params = @sample.params['request_params'] || {}
215
- @custom_params = @sample.params['custom_params'] || {}
218
+ @request_params = @sample.params['request_params'] || {}
219
+ @custom_params = @sample.params['custom_params'] || {}
216
220
 
217
- controller_metric = @sample.root_segment.called_segments.first.metric_name
221
+ controller_metric = @sample.root_segment.called_segments.first.metric_name
218
222
 
219
- metric_parser = NewRelic::MetricParser::MetricParser.for_metric_named controller_metric
220
- @sample_controller_name = metric_parser.controller_name
221
- @sample_action_name = metric_parser.action_name
223
+ metric_parser = NewRelic::MetricParser::MetricParser.for_metric_named controller_metric
224
+ @sample_controller_name = metric_parser.controller_name
225
+ @sample_action_name = metric_parser.action_name
222
226
 
223
- render(:show_sample)
224
- end
227
+ render(:show_sample)
228
+ end
225
229
 
226
- def get_samples
227
- @samples = NewRelic::Agent.instance.transaction_sampler.samples.select do |sample|
228
- sample.params[:path] != nil
229
- end
230
+ def get_samples
231
+ @samples = NewRelic::Agent.instance.transaction_sampler.samples.select do |sample|
232
+ sample.params[:path] != nil
233
+ end
230
234
 
231
- return @samples = @samples.sort{|x,y| y.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)').duration <=>
232
- x.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)').duration} if params['h']
233
- return @samples = @samples.sort{|x,y| x.params[:uri] <=> y.params[:uri]} if params['u']
234
- @samples = @samples.reverse
235
- end
235
+ return @samples = @samples.sort{|x,y| y.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)').duration <=>
236
+ x.omit_segments_with('(Rails/Application Code Loading)|(Database/.*/.+ Columns)').duration} if params['h']
237
+ return @samples = @samples.sort{|x,y| x.params[:uri] <=> y.params[:uri]} if params['u']
238
+ @samples = @samples.reverse
239
+ end
236
240
 
237
- def get_sample
238
- get_samples
239
- id = params['id']
240
- sample_id = id.to_i
241
- @samples.each do |s|
242
- if s.sample_id == sample_id
243
- @sample = stripped_sample(s)
244
- return
241
+ def get_sample
242
+ get_samples
243
+ id = params['id']
244
+ sample_id = id.to_i
245
+ @samples.each do |s|
246
+ if s.sample_id == sample_id
247
+ @sample = stripped_sample(s)
248
+ return
249
+ end
250
+ end
245
251
  end
246
- end
247
- end
248
252
 
249
- def get_segment
250
- get_sample
251
- return unless @sample
253
+ def get_segment
254
+ get_sample
255
+ return unless @sample
252
256
 
253
- segment_id = params['segment'].to_i
254
- @segment = @sample.find_segment(segment_id)
257
+ segment_id = params['segment'].to_i
258
+ @segment = @sample.find_segment(segment_id)
259
+ end
260
+ end
255
261
  end
256
262
  end
257
- end