newrelic_rpm 2.13.5.beta4 → 2.13.6.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 (60) hide show
  1. data/CHANGELOG +8 -0
  2. data/cert/cacert.pem +21 -0
  3. data/lib/conditional_vendored_dependency_detection.rb +3 -0
  4. data/lib/new_relic/agent/agent.rb +14 -1
  5. data/lib/new_relic/agent/instrumentation/active_merchant.rb +15 -12
  6. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +38 -21
  7. data/lib/new_relic/agent/instrumentation/authlogic.rb +9 -4
  8. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +364 -364
  9. data/lib/new_relic/agent/instrumentation/data_mapper.rb +142 -121
  10. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +17 -16
  11. data/lib/new_relic/agent/instrumentation/memcache.rb +40 -26
  12. data/lib/new_relic/agent/instrumentation/net.rb +19 -13
  13. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +27 -15
  14. data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +80 -71
  15. data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +84 -72
  16. data/lib/new_relic/agent/instrumentation/sequel.rb +84 -70
  17. data/lib/new_relic/agent/instrumentation/sinatra.rb +44 -37
  18. data/lib/new_relic/agent/instrumentation/sunspot.rb +18 -12
  19. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +13 -7
  20. data/lib/new_relic/agent/method_tracer.rb +1 -1
  21. data/lib/new_relic/agent/samplers/cpu_sampler.rb +2 -0
  22. data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -1
  23. data/lib/new_relic/control.rb +1 -0
  24. data/lib/new_relic/control/instrumentation.rb +1 -0
  25. data/lib/new_relic/delayed_job_injection.rb +23 -14
  26. data/lib/new_relic/version.rb +2 -2
  27. data/lib/newrelic_rpm.rb +5 -0
  28. data/newrelic_rpm.gemspec +25 -23
  29. data/test/new_relic/agent/{agent_connect_test.rb → agent/connect_test.rb} +2 -2
  30. data/test/new_relic/agent/{agent_start_test.rb → agent/start_test.rb} +17 -3
  31. data/test/new_relic/agent/{agent_start_worker_thread_test.rb → agent/start_worker_thread_test.rb} +2 -2
  32. data/test/new_relic/agent/{agent_controller_test.rb → agent_test_controller_test.rb} +6 -3
  33. data/test/new_relic/agent/{error_collector_notice_error_test.rb → error_collector/notice_error_test.rb} +2 -2
  34. data/test/new_relic/agent/{active_record_instrumentation_test.rb → instrumentation/active_record_instrumentation_test.rb} +2 -2
  35. data/test/new_relic/agent/{metric_frame_test.rb → instrumentation/metric_frame_test.rb} +2 -3
  36. data/test/new_relic/agent/{net_instrumentation_test.rb → instrumentation/net_instrumentation_test.rb} +4 -4
  37. data/test/new_relic/agent/{queue_time_test.rb → instrumentation/queue_time_test.rb} +1 -1
  38. data/test/new_relic/agent/{task_instrumentation_test.rb → instrumentation/task_instrumentation_test.rb} +29 -32
  39. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +165 -0
  40. data/test/new_relic/agent/{method_tracer_trace_execution_scoped_test.rb → method_tracer/instance_methods/trace_execution_scoped_test.rb} +2 -2
  41. data/test/new_relic/agent/method_tracer_test.rb +31 -3
  42. data/test/new_relic/agent/rpm_agent_test.rb +8 -3
  43. data/test/new_relic/{agent/collection_helper_test.rb → collection_helper_test.rb} +4 -4
  44. data/test/new_relic/{deployments_api_test.rb → command/deployments_test.rb} +3 -5
  45. data/test/new_relic/control_test.rb +3 -3
  46. data/test/new_relic/{environment_test.rb → local_environment_test.rb} +2 -5
  47. data/test/new_relic/metric_spec_test.rb +32 -122
  48. data/test/new_relic/stats_test.rb +0 -1
  49. data/test/new_relic/{agent/transaction_sample_subtest_test.rb → transaction_sample_subtest_test.rb} +0 -0
  50. data/test/new_relic/{agent/transaction_sample_test.rb → transaction_sample_test.rb} +1 -2
  51. data/test/test_helper.rb +1 -0
  52. data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +19 -0
  53. data/vendor/gems/dependency_detection-0.0.1.build/README +0 -0
  54. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +57 -0
  55. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection/version.rb +3 -0
  56. metadata +29 -27
  57. data/test/new_relic/agent/add_method_tracer_test.rb +0 -158
  58. data/test/new_relic/agent/metric_data_test.rb +0 -53
  59. data/test/new_relic/agent/testable_agent.rb +0 -13
  60. data/test/new_relic/shim_agent_test.rb +0 -9
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ v2.13.6
2
+ * Dependency detection framework to prevent multi-loading or early-loading
3
+ of instrumentation files
4
+
1
5
  v2.13.5
2
6
  * Moved the API helper to the github newrelic_api gem.
3
7
  * Revamped queue time to include server, queue, and middleware time
@@ -7,6 +11,10 @@ v2.13.5
7
11
  * patches to 1.9 compatibility from dkastner on github
8
12
  * Support for 1.9.2's garbage collection instrumentation from Justin Weiss
9
13
  * On Heroku, existing queue time headers will be detected
14
+ * Fix rack constant scoping in dev mode for 1.9 (Rack != ::Rack)
15
+ * Fixes for instrumentation loading failing on Exception classes that
16
+ are not subclasses of StandardError
17
+ * Fix active record instrumentation load order for Rails 3
10
18
 
11
19
  v2.13.4
12
20
  * Update DNS lookup code to remove hardcoded IP addresses
data/cert/cacert.pem CHANGED
@@ -32,3 +32,24 @@ UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8
32
32
  W9ViH0Pd
33
33
  -----END CERTIFICATE-----
34
34
 
35
+ -----BEGIN CERTIFICATE-----
36
+ MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
37
+ MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
38
+ R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
39
+ MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
40
+ Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
41
+ ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
42
+ AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
43
+ AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
44
+ ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
45
+ 7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
46
+ kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
47
+ mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
48
+ A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
49
+ KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
50
+ 6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
51
+ 4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
52
+ oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
53
+ UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
54
+ AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
55
+ -----END CERTIFICATE-----
@@ -0,0 +1,3 @@
1
+ path = File.expand_path('../vendor/gems/dependency_detection-0.0.1.build/lib', File.dirname(__FILE__))
2
+ $LOAD_PATH << path unless $LOAD_PATH.include?(path)
3
+ require 'dependency_detection'
@@ -256,7 +256,20 @@ module NewRelic
256
256
  end
257
257
 
258
258
  def set_sql_recording!
259
- @record_sql = sampler_config.fetch('record_sql', :obfuscated).to_sym
259
+ record_sql_config = sampler_config.fetch('record_sql', :obfuscated)
260
+ case record_sql_config.to_s
261
+ when 'off'
262
+ @record_sql = :off
263
+ when 'none'
264
+ @record_sql = :off
265
+ when 'false'
266
+ @record_sql = :off
267
+ when 'raw'
268
+ @record_sql = :raw
269
+ else
270
+ @record_sql = :obfuscated
271
+ end
272
+
260
273
  log_sql_transmission_warning?
261
274
  end
262
275
 
@@ -1,16 +1,19 @@
1
- # ActiveMerchant Instrumentation.
2
-
3
- if defined? ActiveMerchant
1
+ DependencyDetection.defer do
2
+ depends_on do
3
+ defined?(ActiveMerchant)
4
+ end
4
5
 
5
- ActiveMerchant::Billing::Gateway.implementations.each do |gateway|
6
- gateway.class_eval do
7
- implemented_methods = public_instance_methods(false)
8
- gateway_name = self.name.split('::').last
9
- [:authorize, :purchase, :credit, :void, :capture, :recurring].each do |operation|
10
- if implemented_methods.include?(operation.to_s)
11
- add_method_tracer operation, "ActiveMerchant/gateway/#{gateway_name}/#{operation}", :scoped_metric_only => true
12
- add_method_tracer operation, "ActiveMerchant/gateway/#{gateway_name}", :push_scope => false
13
- add_method_tracer operation, "ActiveMerchant/operation/#{operation}", :push_scope => false
6
+ executes do
7
+ ActiveMerchant::Billing::Gateway.implementations.each do |gateway|
8
+ gateway.class_eval do
9
+ implemented_methods = public_instance_methods(false)
10
+ gateway_name = self.name.split('::').last
11
+ [:authorize, :purchase, :credit, :void, :capture, :recurring].each do |operation|
12
+ if implemented_methods.include?(operation.to_s)
13
+ add_method_tracer operation, "ActiveMerchant/gateway/#{gateway_name}/#{operation}", :scoped_metric_only => true
14
+ add_method_tracer operation, "ActiveMerchant/gateway/#{gateway_name}", :push_scope => false
15
+ add_method_tracer operation, "ActiveMerchant/operation/#{operation}", :push_scope => false
16
+ end
14
17
  end
15
18
  end
16
19
  end
@@ -1,40 +1,58 @@
1
- if defined?(::ActsAsSolr)
2
-
3
- module NewRelic
4
- module Instrumentation
5
- module ActsAsSolrInstrumentation
6
- module ParserMethodsInstrumentation
7
- def parse_query_with_newrelic(*args)
8
- self.class.trace_execution_scoped(["SolrClient/ActsAsSolr/query"]) do
9
- t0 = Time.now
10
- begin
11
- parse_query_without_newrelic(*args)
12
- ensure
13
- NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil
14
- end
1
+ module NewRelic
2
+ module Instrumentation
3
+ module ActsAsSolrInstrumentation
4
+ module ParserMethodsInstrumentation
5
+ def parse_query_with_newrelic(*args)
6
+ self.class.trace_execution_scoped(["SolrClient/ActsAsSolr/query"]) do
7
+ t0 = Time.now
8
+ begin
9
+ parse_query_without_newrelic(*args)
10
+ ensure
11
+ NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil
15
12
  end
16
-
17
13
  end
18
14
  end
19
15
  end
20
16
  end
21
17
  end
18
+ end
22
19
 
23
- module ActsAsSolr
24
- module ParserMethods #:nodoc
20
+ DependencyDetection.defer do
21
+ depends_on do
22
+ defined?(ActsAsSolr)
23
+ end
24
+
25
+ depends_on do
26
+ defined?(ActsAsSolr::ParserMethods)
27
+ end
28
+
29
+ depends_on do
30
+ defined?(ActsAsSolr::ClassMethods)
31
+ end
32
+
33
+ depends_on do
34
+ defined?(ActsAsSolr::CommonMethods)
35
+ end
36
+
37
+ executes do
38
+ ActsAsSolr::ParserMethods.module_eval do
25
39
  include NewRelic::Instrumentation::ActsAsSolrInstrumentation::ParserMethodsInstrumentation
26
40
  alias :parse_query_without_newrelic :parse_query
27
41
  alias :parse_query :parse_query_with_newrelic
28
42
  end
29
-
30
- module ClassMethods #:nodoc
43
+ end
44
+
45
+ executes do
46
+ ActsAsSolr::ClassMethods.module_eval do
31
47
  %w[find_by_solr find_id_by_solr multi_solr_search count_by_solr].each do |method|
32
48
  add_method_tracer method, 'SolrClient/ActsAsSolr/query'
33
49
  end
34
50
  add_method_tracer :rebuild_solr_index, 'SolrClient/ActsAsSolr/index'
35
51
  end
52
+ end
36
53
 
37
- module CommonMethods #:nodoc
54
+ executes do
55
+ ActsAsSolr::CommonMethods.module_eval do
38
56
  add_method_tracer :solr_add, 'SolrClient/ActsAsSolr/add'
39
57
  add_method_tracer :solr_delete, 'SolrClient/ActsAsSolr/delete'
40
58
  add_method_tracer :solr_commit, 'SolrClient/ActsAsSolr/commit'
@@ -42,4 +60,3 @@ if defined?(::ActsAsSolr)
42
60
  end
43
61
  end
44
62
  end
45
-
@@ -1,7 +1,12 @@
1
- if defined? Authlogic::Session::Base
2
- Authlogic::Session::Base.class_eval do
3
- # add_method_tracer :record, 'Custom/Authlogic/record'
4
- class << self
1
+ DependencyDetection.defer do
2
+ depends_on do
3
+ defined?(AuthLogic) &&
4
+ defined?(AuthLogic::Session) &&
5
+ defined?(AuthLogic::Session::Base)
6
+ end
7
+
8
+ executes do
9
+ AuthLogic::Session::Base.class_eval do
5
10
  add_method_tracer :find, 'Custom/Authlogic/find'
6
11
  end
7
12
  end
@@ -3,405 +3,405 @@ require 'new_relic/agent/instrumentation/queue_time'
3
3
  module NewRelic
4
4
  module Agent
5
5
  module Instrumentation
6
- # == NewRelic instrumentation for controller actions and tasks
7
- #
8
- # This instrumentation is applied to the action controller to collect
9
- # metrics for every web request.
10
- #
11
- # It can also be used to capture performance information for
12
- # background tasks and other non-web transactions, including
13
- # detailed transaction traces and traced errors.
14
- #
15
- # For details on how to instrument background tasks see
16
- # ClassMethods#add_transaction_tracer and
17
- # #perform_action_with_newrelic_trace
18
- #
19
- module ControllerInstrumentation
20
-
21
- def self.included(clazz) # :nodoc:
22
- clazz.extend(ClassMethods)
23
- end
24
-
25
- # This module is for importing stubs when the agent is disabled
26
- module ClassMethodsShim # :nodoc:
27
- def newrelic_ignore(*args); end
28
- def newrelic_ignore_apdex(*args); end
29
- end
6
+ # == NewRelic instrumentation for controller actions and tasks
7
+ #
8
+ # This instrumentation is applied to the action controller to collect
9
+ # metrics for every web request.
10
+ #
11
+ # It can also be used to capture performance information for
12
+ # background tasks and other non-web transactions, including
13
+ # detailed transaction traces and traced errors.
14
+ #
15
+ # For details on how to instrument background tasks see
16
+ # ClassMethods#add_transaction_tracer and
17
+ # #perform_action_with_newrelic_trace
18
+ #
19
+ module ControllerInstrumentation
30
20
 
31
- module Shim # :nodoc:
32
- def self.included(clazz)
33
- clazz.extend(ClassMethodsShim)
34
- end
35
- def newrelic_notice_error(*args); end
36
- def new_relic_trace_controller_action(*args); yield; end
37
- def newrelic_metric_path; end
38
- def perform_action_with_newrelic_trace(*args); yield; end
39
- end
21
+ def self.included(clazz) # :nodoc:
22
+ clazz.extend(ClassMethods)
23
+ end
40
24
 
41
- module ClassMethods
42
- # Have NewRelic ignore actions in this controller. Specify the actions as hash options
43
- # using :except and :only. If no actions are specified, all actions are ignored.
44
- def newrelic_ignore(specifiers={})
45
- newrelic_ignore_aspect('do_not_trace', specifiers)
46
- end
47
- # Have NewRelic omit apdex measurements on the given actions. Typically used for
48
- # actions that are not user facing or that skew your overall apdex measurement.
49
- # Accepts :except and :only options, as with #newrelic_ignore.
50
- def newrelic_ignore_apdex(specifiers={})
51
- newrelic_ignore_aspect('ignore_apdex', specifiers)
52
- end
25
+ # This module is for importing stubs when the agent is disabled
26
+ module ClassMethodsShim # :nodoc:
27
+ def newrelic_ignore(*args); end
28
+ def newrelic_ignore_apdex(*args); end
29
+ end
53
30
 
54
- def newrelic_ignore_aspect(property, specifiers={}) # :nodoc:
55
- if specifiers.empty?
56
- self.newrelic_write_attr property, true
57
- elsif ! (Hash === specifiers)
58
- logger.error "newrelic_#{property} takes an optional hash with :only and :except lists of actions (illegal argument type '#{specifiers.class}')"
59
- else
60
- self.newrelic_write_attr property, specifiers
31
+ module Shim # :nodoc:
32
+ def self.included(clazz)
33
+ clazz.extend(ClassMethodsShim)
34
+ end
35
+ def newrelic_notice_error(*args); end
36
+ def new_relic_trace_controller_action(*args); yield; end
37
+ def newrelic_metric_path; end
38
+ def perform_action_with_newrelic_trace(*args); yield; end
61
39
  end
62
- end
63
40
 
64
- # Should be monkey patched into the controller class implemented
65
- # with the inheritable attribute mechanism.
66
- def newrelic_write_attr(attr_name, value) # :nodoc:
67
- instance_variable_set "@#{attr_name}", value
68
- end
69
- def newrelic_read_attr(attr_name) # :nodoc:
70
- instance_variable_get "@#{attr_name}"
71
- end
41
+ module ClassMethods
42
+ # Have NewRelic ignore actions in this controller. Specify the actions as hash options
43
+ # using :except and :only. If no actions are specified, all actions are ignored.
44
+ def newrelic_ignore(specifiers={})
45
+ newrelic_ignore_aspect('do_not_trace', specifiers)
46
+ end
47
+ # Have NewRelic omit apdex measurements on the given actions. Typically used for
48
+ # actions that are not user facing or that skew your overall apdex measurement.
49
+ # Accepts :except and :only options, as with #newrelic_ignore.
50
+ def newrelic_ignore_apdex(specifiers={})
51
+ newrelic_ignore_aspect('ignore_apdex', specifiers)
52
+ end
72
53
 
73
- # Add transaction tracing to the given method. This will treat
74
- # the given method as a main entrypoint for instrumentation, just
75
- # like controller actions are treated by default. Useful especially
76
- # for background tasks.
77
- #
78
- # Example for background job:
79
- # class Job
80
- # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
81
- # def run(task)
82
- # ...
83
- # end
84
- # # Instrument run so tasks show up under task.name. Note single
85
- # # quoting to defer eval to runtime.
86
- # add_transaction_tracer :run, :name => '#{args[0].name}'
87
- # end
88
- #
89
- # Here's an example of a controller that uses a dispatcher
90
- # action to invoke operations which you want treated as top
91
- # level actions, so they aren't all lumped into the invoker
92
- # action.
93
- #
94
- # MyController < ActionController::Base
95
- # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
96
- # # dispatch the given op to the method given by the service parameter.
97
- # def invoke_operation
98
- # op = params['operation']
99
- # send op
100
- # end
101
- # # Ignore the invoker to avoid double counting
102
- # newrelic_ignore :only => 'invoke_operation'
103
- # # Instrument the operations:
104
- # add_transaction_tracer :print
105
- # add_transaction_tracer :show
106
- # add_transaction_tracer :forward
107
- # end
108
- #
109
- # Here's an example of how to pass contextual information into the transaction
110
- # so it will appear in transaction traces:
111
- #
112
- # class Job
113
- # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
114
- # def process(account)
115
- # ...
116
- # end
117
- # # Include the account name in the transaction details. Note the single
118
- # # quotes to defer eval until call time.
119
- # add_transaction_tracer :process, :params => '{ :account_name => args[0].name }'
120
- # end
121
- #
122
- # See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace
123
- # for the full list of available options.
124
- #
125
- def add_transaction_tracer(method, options={})
126
- # The metric path:
127
- options[:name] ||= method.to_s
128
- # create the argument list:
129
- options_arg = []
130
- options.each do |key, value|
131
- valuestr = case
132
- when value.is_a?(Symbol)
133
- value.inspect
134
- when key == :params
135
- value.to_s
136
- else
137
- %Q["#{value.to_s}"]
54
+ def newrelic_ignore_aspect(property, specifiers={}) # :nodoc:
55
+ if specifiers.empty?
56
+ self.newrelic_write_attr property, true
57
+ elsif ! (Hash === specifiers)
58
+ logger.error "newrelic_#{property} takes an optional hash with :only and :except lists of actions (illegal argument type '#{specifiers.class}')"
59
+ else
60
+ self.newrelic_write_attr property, specifiers
61
+ end
138
62
  end
139
- options_arg << %Q[:#{key} => #{valuestr}]
140
- end
141
- class_eval <<-EOC
142
- def #{method.to_s}_with_newrelic_transaction_trace(*args, &block)
143
- perform_action_with_newrelic_trace(#{options_arg.join(',')}) do
144
- #{method.to_s}_without_newrelic_transaction_trace(*args, &block)
63
+
64
+ # Should be monkey patched into the controller class implemented
65
+ # with the inheritable attribute mechanism.
66
+ def newrelic_write_attr(attr_name, value) # :nodoc:
67
+ instance_variable_set "@#{attr_name}", value
68
+ end
69
+ def newrelic_read_attr(attr_name) # :nodoc:
70
+ instance_variable_get "@#{attr_name}"
71
+ end
72
+
73
+ # Add transaction tracing to the given method. This will treat
74
+ # the given method as a main entrypoint for instrumentation, just
75
+ # like controller actions are treated by default. Useful especially
76
+ # for background tasks.
77
+ #
78
+ # Example for background job:
79
+ # class Job
80
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
81
+ # def run(task)
82
+ # ...
83
+ # end
84
+ # # Instrument run so tasks show up under task.name. Note single
85
+ # # quoting to defer eval to runtime.
86
+ # add_transaction_tracer :run, :name => '#{args[0].name}'
87
+ # end
88
+ #
89
+ # Here's an example of a controller that uses a dispatcher
90
+ # action to invoke operations which you want treated as top
91
+ # level actions, so they aren't all lumped into the invoker
92
+ # action.
93
+ #
94
+ # MyController < ActionController::Base
95
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
96
+ # # dispatch the given op to the method given by the service parameter.
97
+ # def invoke_operation
98
+ # op = params['operation']
99
+ # send op
100
+ # end
101
+ # # Ignore the invoker to avoid double counting
102
+ # newrelic_ignore :only => 'invoke_operation'
103
+ # # Instrument the operations:
104
+ # add_transaction_tracer :print
105
+ # add_transaction_tracer :show
106
+ # add_transaction_tracer :forward
107
+ # end
108
+ #
109
+ # Here's an example of how to pass contextual information into the transaction
110
+ # so it will appear in transaction traces:
111
+ #
112
+ # class Job
113
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
114
+ # def process(account)
115
+ # ...
116
+ # end
117
+ # # Include the account name in the transaction details. Note the single
118
+ # # quotes to defer eval until call time.
119
+ # add_transaction_tracer :process, :params => '{ :account_name => args[0].name }'
120
+ # end
121
+ #
122
+ # See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace
123
+ # for the full list of available options.
124
+ #
125
+ def add_transaction_tracer(method, options={})
126
+ # The metric path:
127
+ options[:name] ||= method.to_s
128
+ # create the argument list:
129
+ options_arg = []
130
+ options.each do |key, value|
131
+ valuestr = case
132
+ when value.is_a?(Symbol)
133
+ value.inspect
134
+ when key == :params
135
+ value.to_s
136
+ else
137
+ %Q["#{value.to_s}"]
138
+ end
139
+ options_arg << %Q[:#{key} => #{valuestr}]
140
+ end
141
+ class_eval <<-EOC
142
+ def #{method.to_s}_with_newrelic_transaction_trace(*args, &block)
143
+ perform_action_with_newrelic_trace(#{options_arg.join(',')}) do
144
+ #{method.to_s}_without_newrelic_transaction_trace(*args, &block)
145
+ end
146
+ end
147
+ EOC
148
+ alias_method "#{method.to_s}_without_newrelic_transaction_trace", method.to_s
149
+ alias_method method.to_s, "#{method.to_s}_with_newrelic_transaction_trace"
150
+ NewRelic::Control.instance.log.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{options.inspect}")
145
151
  end
146
152
  end
147
- EOC
148
- alias_method "#{method.to_s}_without_newrelic_transaction_trace", method.to_s
149
- alias_method method.to_s, "#{method.to_s}_with_newrelic_transaction_trace"
150
- NewRelic::Control.instance.log.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{options.inspect}")
151
- end
152
- end
153
153
 
154
- # Must be implemented in the controller class:
155
- # Determine the path that is used in the metric name for
156
- # the called controller action. Of the form controller_path/action_name
157
- #
158
- def newrelic_metric_path(action_name_override = nil) # :nodoc:
159
- raise "Not implemented!"
160
- end
154
+ # Must be implemented in the controller class:
155
+ # Determine the path that is used in the metric name for
156
+ # the called controller action. Of the form controller_path/action_name
157
+ #
158
+ def newrelic_metric_path(action_name_override = nil) # :nodoc:
159
+ raise "Not implemented!"
160
+ end
161
161
 
162
- # Yield to the given block with NewRelic tracing. Used by
163
- # default instrumentation on controller actions in Rails and Merb.
164
- # But it can also be used in custom instrumentation of controller
165
- # methods and background tasks.
166
- #
167
- # This is the method invoked by instrumentation added by the
168
- # <tt>ClassMethods#add_transaction_tracer</tt>.
169
- #
170
- # Here's a more verbose version of the example shown in
171
- # <tt>ClassMethods#add_transaction_tracer</tt> using this method instead of
172
- # #add_transaction_tracer.
173
- #
174
- # Below is a controller with an +invoke_operation+ action which
175
- # dispatches to more specific operation methods based on a
176
- # parameter (very dangerous, btw!). With this instrumentation,
177
- # the +invoke_operation+ action is ignored but the operation
178
- # methods show up in RPM as if they were first class controller
179
- # actions
180
- #
181
- # MyController < ActionController::Base
182
- # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
183
- # # dispatch the given op to the method given by the service parameter.
184
- # def invoke_operation
185
- # op = params['operation']
186
- # perform_action_with_newrelic_trace(:name => op) do
187
- # send op, params['message']
188
- # end
189
- # end
190
- # # Ignore the invoker to avoid double counting
191
- # newrelic_ignore :only => 'invoke_operation'
192
- # end
193
- #
194
- #
195
- # When invoking this method explicitly as in the example above, pass in a
196
- # block to measure with some combination of options:
197
- #
198
- # * <tt>:category => :controller</tt> indicates that this is a
199
- # controller action and will appear with all the other actions. This
200
- # is the default.
201
- # * <tt>:category => :task</tt> indicates that this is a
202
- # background task and will show up in RPM with other background
203
- # tasks instead of in the controllers list
204
- # * <tt>:category => :rack</tt> if you are instrumenting a rack
205
- # middleware call. The <tt>:name</tt> is optional, useful if you
206
- # have more than one potential transaction in the #call.
207
- # * <tt>:category => :uri</tt> indicates that this is a
208
- # web transaction whose name is a normalized URI, where 'normalized'
209
- # means the URI does not have any elements with data in them such
210
- # as in many REST URIs.
211
- # * <tt>:name => action_name</tt> is used to specify the action
212
- # name used as part of the metric name
213
- # * <tt>:params => {...}</tt> to provide information about the context
214
- # of the call, used in transaction trace display, for example:
215
- # <tt>:params => { :account => @account.name, :file => file.name }</tt>
216
- # These are treated similarly to request parameters in web transactions.
217
- #
218
- # Seldomly used options:
219
- #
220
- # * <tt>:force => true</tt> indicates you should capture all
221
- # metrics even if the #newrelic_ignore directive was specified
222
- # * <tt>:class_name => aClass.name</tt> is used to override the name
223
- # of the class when used inside the metric name. Default is the
224
- # current class.
225
- # * <tt>:path => metric_path</tt> is *deprecated* in the public API. It
226
- # allows you to set the entire metric after the category part. Overrides
227
- # all the other options.
228
- # * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
229
- # request object that may respond to uri and referer.
230
- #
231
- # If a single argument is passed in, it is treated as a metric
232
- # path. This form is deprecated.
233
- def perform_action_with_newrelic_trace(*args, &block)
162
+ # Yield to the given block with NewRelic tracing. Used by
163
+ # default instrumentation on controller actions in Rails and Merb.
164
+ # But it can also be used in custom instrumentation of controller
165
+ # methods and background tasks.
166
+ #
167
+ # This is the method invoked by instrumentation added by the
168
+ # <tt>ClassMethods#add_transaction_tracer</tt>.
169
+ #
170
+ # Here's a more verbose version of the example shown in
171
+ # <tt>ClassMethods#add_transaction_tracer</tt> using this method instead of
172
+ # #add_transaction_tracer.
173
+ #
174
+ # Below is a controller with an +invoke_operation+ action which
175
+ # dispatches to more specific operation methods based on a
176
+ # parameter (very dangerous, btw!). With this instrumentation,
177
+ # the +invoke_operation+ action is ignored but the operation
178
+ # methods show up in RPM as if they were first class controller
179
+ # actions
180
+ #
181
+ # MyController < ActionController::Base
182
+ # include NewRelic::Agent::Instrumentation::ControllerInstrumentation
183
+ # # dispatch the given op to the method given by the service parameter.
184
+ # def invoke_operation
185
+ # op = params['operation']
186
+ # perform_action_with_newrelic_trace(:name => op) do
187
+ # send op, params['message']
188
+ # end
189
+ # end
190
+ # # Ignore the invoker to avoid double counting
191
+ # newrelic_ignore :only => 'invoke_operation'
192
+ # end
193
+ #
194
+ #
195
+ # When invoking this method explicitly as in the example above, pass in a
196
+ # block to measure with some combination of options:
197
+ #
198
+ # * <tt>:category => :controller</tt> indicates that this is a
199
+ # controller action and will appear with all the other actions. This
200
+ # is the default.
201
+ # * <tt>:category => :task</tt> indicates that this is a
202
+ # background task and will show up in RPM with other background
203
+ # tasks instead of in the controllers list
204
+ # * <tt>:category => :rack</tt> if you are instrumenting a rack
205
+ # middleware call. The <tt>:name</tt> is optional, useful if you
206
+ # have more than one potential transaction in the #call.
207
+ # * <tt>:category => :uri</tt> indicates that this is a
208
+ # web transaction whose name is a normalized URI, where 'normalized'
209
+ # means the URI does not have any elements with data in them such
210
+ # as in many REST URIs.
211
+ # * <tt>:name => action_name</tt> is used to specify the action
212
+ # name used as part of the metric name
213
+ # * <tt>:params => {...}</tt> to provide information about the context
214
+ # of the call, used in transaction trace display, for example:
215
+ # <tt>:params => { :account => @account.name, :file => file.name }</tt>
216
+ # These are treated similarly to request parameters in web transactions.
217
+ #
218
+ # Seldomly used options:
219
+ #
220
+ # * <tt>:force => true</tt> indicates you should capture all
221
+ # metrics even if the #newrelic_ignore directive was specified
222
+ # * <tt>:class_name => aClass.name</tt> is used to override the name
223
+ # of the class when used inside the metric name. Default is the
224
+ # current class.
225
+ # * <tt>:path => metric_path</tt> is *deprecated* in the public API. It
226
+ # allows you to set the entire metric after the category part. Overrides
227
+ # all the other options.
228
+ # * <tt>:request => Rack::Request#new(env)</tt> is used to pass in a
229
+ # request object that may respond to uri and referer.
230
+ #
231
+ # If a single argument is passed in, it is treated as a metric
232
+ # path. This form is deprecated.
233
+ def perform_action_with_newrelic_trace(*args, &block)
234
234
 
235
- # Skip instrumentation based on the value of 'do_not_trace' and if
236
- # we aren't calling directly with a block.
237
- if !block_given? && _is_filtered?('do_not_trace')
238
- # Also ignore all instrumentation in the call sequence
239
- NewRelic::Agent.disable_all_tracing do
240
- return perform_action_without_newrelic_trace(*args)
241
- end
242
- end
235
+ # Skip instrumentation based on the value of 'do_not_trace' and if
236
+ # we aren't calling directly with a block.
237
+ if !block_given? && _is_filtered?('do_not_trace')
238
+ # Also ignore all instrumentation in the call sequence
239
+ NewRelic::Agent.disable_all_tracing do
240
+ return perform_action_without_newrelic_trace(*args)
241
+ end
242
+ end
243
243
 
244
- return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
244
+ return perform_action_with_newrelic_profile(args, &block) if NewRelic::Control.instance.profiling?
245
245
 
246
- frame_data = _push_metric_frame(block_given? ? args : [])
247
- begin
248
- NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
249
- frame_data.start_transaction
246
+ frame_data = _push_metric_frame(block_given? ? args : [])
250
247
  begin
251
- NewRelic::Agent::BusyCalculator.dispatcher_start frame_data.start
252
- if block_given?
253
- yield
254
- else
255
- perform_action_without_newrelic_trace(*args)
248
+ NewRelic::Agent.trace_execution_scoped frame_data.recorded_metrics, :force => frame_data.force_flag do
249
+ frame_data.start_transaction
250
+ begin
251
+ NewRelic::Agent::BusyCalculator.dispatcher_start frame_data.start
252
+ if block_given?
253
+ yield
254
+ else
255
+ perform_action_without_newrelic_trace(*args)
256
+ end
257
+ rescue Exception => e
258
+ frame_data.notice_error(e)
259
+ raise
260
+ end
261
+ end
262
+ ensure
263
+ NewRelic::Agent::BusyCalculator.dispatcher_finish
264
+ # Look for a metric frame in the thread local and process it.
265
+ # Clear the thread local when finished to ensure it only gets called once.
266
+ frame_data.record_apdex unless _is_filtered?('ignore_apdex')
267
+
268
+ if Thread::current[:browser_request]
269
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope("HttpDispatcherWithBrowser").record_data_point(Time.now - frame_data.start)
256
270
  end
257
- rescue Exception => e
258
- frame_data.notice_error(e)
259
- raise
271
+
272
+ frame_data.pop
260
273
  end
261
274
  end
262
- ensure
263
- NewRelic::Agent::BusyCalculator.dispatcher_finish
264
- # Look for a metric frame in the thread local and process it.
265
- # Clear the thread local when finished to ensure it only gets called once.
266
- frame_data.record_apdex unless _is_filtered?('ignore_apdex')
267
-
268
- if Thread::current[:browser_request]
269
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope("HttpDispatcherWithBrowser").record_data_point(Time.now - frame_data.start)
275
+
276
+ protected
277
+ # Should be implemented in the dispatcher class
278
+ def newrelic_response_code; end
279
+
280
+ def newrelic_request_headers
281
+ self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
270
282
  end
271
-
272
- frame_data.pop
273
- end
274
- end
275
283
 
276
- protected
277
- # Should be implemented in the dispatcher class
278
- def newrelic_response_code; end
284
+ private
279
285
 
280
- def newrelic_request_headers
281
- self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
282
- end
286
+ # Profile the instrumented call. Dev mode only. Experimental.
287
+ def perform_action_with_newrelic_profile(args)
288
+ frame_data = _push_metric_frame(block_given? ? args : [])
289
+ val = nil
290
+ NewRelic::Agent.trace_execution_scoped frame_data.metric_name do
291
+ MetricFrame.current(true).start_transaction
292
+ NewRelic::Agent.disable_all_tracing do
293
+ # turn on profiling
294
+ profile = RubyProf.profile do
295
+ if block_given?
296
+ val = yield
297
+ else
298
+ val = perform_action_without_newrelic_trace(*args)
299
+ end
300
+ end
301
+ NewRelic::Agent.instance.transaction_sampler.notice_profile profile
302
+ end
303
+ end
304
+ return val
305
+ ensure
306
+ frame_data.pop
307
+ end
283
308
 
284
- private
309
+ # Write a metric frame onto a thread local if there isn't already one there.
310
+ # If there is one, just update it.
311
+ def _push_metric_frame(args) # :nodoc:
312
+ frame_data = NewRelic::Agent::Instrumentation::MetricFrame.current(true)
285
313
 
286
- # Profile the instrumented call. Dev mode only. Experimental.
287
- def perform_action_with_newrelic_profile(args)
288
- frame_data = _push_metric_frame(block_given? ? args : [])
289
- val = nil
290
- NewRelic::Agent.trace_execution_scoped frame_data.metric_name do
291
- MetricFrame.current(true).start_transaction
292
- NewRelic::Agent.disable_all_tracing do
293
- # turn on profiling
294
- profile = RubyProf.profile do
295
- if block_given?
296
- val = yield
297
- else
298
- val = perform_action_without_newrelic_trace(*args)
314
+ frame_data.apdex_start ||= _detect_upstream_wait(frame_data.start)
315
+ _record_queue_length
316
+ # If a block was passed in, then the arguments represent options for the instrumentation,
317
+ # not app method arguments.
318
+ if args.any?
319
+ if args.last.is_a?(Hash)
320
+ options = args.last
321
+ frame_data.force_flag = options[:force]
322
+ frame_data.request = options[:request] if options[:request]
299
323
  end
324
+ category, path, available_params = _convert_args_to_path(args)
325
+ else
326
+ category = 'Controller'
327
+ path = newrelic_metric_path
328
+ available_params = self.respond_to?(:params) ? self.params : {}
300
329
  end
301
- NewRelic::Agent.instance.transaction_sampler.notice_profile profile
330
+ frame_data.request ||= self.request if self.respond_to? :request
331
+ frame_data.push(category + '/'+ path)
332
+ frame_data.filtered_params = (respond_to? :filter_parameters) ? filter_parameters(available_params) : available_params
333
+ frame_data
302
334
  end
303
- end
304
- return val
305
- ensure
306
- frame_data.pop
307
- end
308
335
 
309
- # Write a metric frame onto a thread local if there isn't already one there.
310
- # If there is one, just update it.
311
- def _push_metric_frame(args) # :nodoc:
312
- frame_data = NewRelic::Agent::Instrumentation::MetricFrame.current(true)
336
+ def _convert_args_to_path(args)
337
+ options = args.last.is_a?(Hash) ? args.pop : {}
338
+ params = options[:params] || {}
339
+ category = case options[:category]
340
+ when :controller, nil then 'Controller'
341
+ when :task then 'OtherTransaction/Background' # 'Task'
342
+ when :rack then 'Controller/Rack' #'WebTransaction/Rack'
343
+ when :uri then 'Controller' #'WebTransaction/Uri'
344
+ when :sinatra then 'Controller/Sinatra' #'WebTransaction/Uri'
345
+ # for internal use only
346
+ else options[:category].to_s
347
+ end
348
+ unless path = options[:path]
349
+ action = options[:name] || args.first
350
+ metric_class = options[:class_name] || (self.is_a?(Class) ? self.name : self.class.name)
351
+ path = metric_class
352
+ path += ('/' + action) if action
353
+ end
354
+ [category, path, params]
355
+ end
313
356
 
314
- frame_data.apdex_start ||= _detect_upstream_wait(frame_data.start)
315
- _record_queue_length
316
- # If a block was passed in, then the arguments represent options for the instrumentation,
317
- # not app method arguments.
318
- if args.any?
319
- if args.last.is_a?(Hash)
320
- options = args.last
321
- frame_data.force_flag = options[:force]
322
- frame_data.request = options[:request] if options[:request]
357
+ # Filter out
358
+ def _is_filtered?(key)
359
+ ignore_actions = self.class.newrelic_read_attr(key) if self.class.respond_to? :newrelic_read_attr
360
+ case ignore_actions
361
+ when nil; false
362
+ when Hash
363
+ only_actions = Array(ignore_actions[:only])
364
+ except_actions = Array(ignore_actions[:except])
365
+ only_actions.include?(action_name.to_sym) || (except_actions.any? && !except_actions.include?(action_name.to_sym))
366
+ else
367
+ true
368
+ end
369
+ end
370
+ # Take a guess at a measure representing the number of requests waiting in mongrel
371
+ # or heroku.
372
+ def _record_queue_length
373
+ if newrelic_request_headers
374
+ if queue_depth = newrelic_request_headers['HTTP_X_HEROKU_QUEUE_DEPTH']
375
+ queue_depth = queue_depth.to_i rescue nil
376
+ elsif mongrel = NewRelic::Control.instance.local_env.mongrel
377
+ # Always subtrace 1 for the active mongrel
378
+ queue_depth = [mongrel.workers.list.length.to_i - 1, 0].max rescue nil
379
+ end
380
+ NewRelic::Agent.agent.stats_engine.get_stats_no_scope('Mongrel/Queue Length').trace_call(queue_depth) if queue_depth
381
+ end
323
382
  end
324
- category, path, available_params = _convert_args_to_path(args)
325
- else
326
- category = 'Controller'
327
- path = newrelic_metric_path
328
- available_params = self.respond_to?(:params) ? self.params : {}
329
- end
330
- frame_data.request ||= self.request if self.respond_to? :request
331
- frame_data.push(category + '/'+ path)
332
- frame_data.filtered_params = (respond_to? :filter_parameters) ? filter_parameters(available_params) : available_params
333
- frame_data
334
- end
335
383
 
336
- def _convert_args_to_path(args)
337
- options = args.last.is_a?(Hash) ? args.pop : {}
338
- params = options[:params] || {}
339
- category = case options[:category]
340
- when :controller, nil then 'Controller'
341
- when :task then 'OtherTransaction/Background' # 'Task'
342
- when :rack then 'Controller/Rack' #'WebTransaction/Rack'
343
- when :uri then 'Controller' #'WebTransaction/Uri'
344
- when :sinatra then 'Controller/Sinatra' #'WebTransaction/Uri'
345
- # for internal use only
346
- else options[:category].to_s
347
- end
348
- unless path = options[:path]
349
- action = options[:name] || args.first
350
- metric_class = options[:class_name] || (self.is_a?(Class) ? self.name : self.class.name)
351
- path = metric_class
352
- path += ('/' + action) if action
353
- end
354
- [category, path, params]
355
- end
384
+ include NewRelic::Agent::Instrumentation::QueueTime
356
385
 
357
- # Filter out
358
- def _is_filtered?(key)
359
- ignore_actions = self.class.newrelic_read_attr(key) if self.class.respond_to? :newrelic_read_attr
360
- case ignore_actions
361
- when nil; false
362
- when Hash
363
- only_actions = Array(ignore_actions[:only])
364
- except_actions = Array(ignore_actions[:except])
365
- only_actions.include?(action_name.to_sym) || (except_actions.any? && !except_actions.include?(action_name.to_sym))
366
- else
367
- true
368
- end
369
- end
370
- # Take a guess at a measure representing the number of requests waiting in mongrel
371
- # or heroku.
372
- def _record_queue_length
373
- if newrelic_request_headers
374
- if queue_depth = newrelic_request_headers['HTTP_X_HEROKU_QUEUE_DEPTH']
375
- queue_depth = queue_depth.to_i rescue nil
376
- elsif mongrel = NewRelic::Control.instance.local_env.mongrel
377
- # Always subtrace 1 for the active mongrel
378
- queue_depth = [mongrel.workers.list.length.to_i - 1, 0].max rescue nil
386
+ # Return a Time instance representing the upstream start time.
387
+ # now is a Time instance to fall back on if no other candidate
388
+ # for the start time is found.
389
+ def _detect_upstream_wait(now)
390
+ if newrelic_request_headers
391
+ parse_frontend_headers(newrelic_request_headers)
392
+ end
393
+ now
394
+ rescue Exception => e
395
+ NewRelic::Control.instance.log.error("Error detecting upstream wait time: #{e}")
396
+ NewRelic::Control.instance.log.debug("#{e.backtrace[0..20]}")
397
+ now
379
398
  end
380
- NewRelic::Agent.agent.stats_engine.get_stats_no_scope('Mongrel/Queue Length').trace_call(queue_depth) if queue_depth
381
- end
382
- end
383
399
 
384
- include NewRelic::Agent::Instrumentation::QueueTime
400
+ def _dispatch_stat
401
+ NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
402
+ end
385
403
 
386
- # Return a Time instance representing the upstream start time.
387
- # now is a Time instance to fall back on if no other candidate
388
- # for the start time is found.
389
- def _detect_upstream_wait(now)
390
- if newrelic_request_headers
391
- parse_frontend_headers(newrelic_request_headers)
392
404
  end
393
- now
394
- rescue Exception => e
395
- NewRelic::Control.instance.log.error("Error detecting upstream wait time: #{e}")
396
- NewRelic::Control.instance.log.debug("#{e.backtrace[0..20]}")
397
- now
398
405
  end
399
-
400
- def _dispatch_stat
401
- NewRelic::Agent.agent.stats_engine.get_stats_no_scope 'HttpDispatcher'
402
- end
403
-
404
406
  end
405
407
  end
406
- end
407
- end