newrelic_rpm 3.6.6.147 → 3.6.7.152

Sign up to get free protection for your applications and to get access to all the features.
Files changed (265) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gitignore +0 -1
  3. data/CHANGELOG +55 -17
  4. data/Guardfile +7 -0
  5. data/Rakefile +6 -0
  6. data/bin/mongrel_rpm +33 -0
  7. data/bin/newrelic +13 -0
  8. data/bin/newrelic_cmd +5 -0
  9. data/bin/nrdebug +273 -0
  10. data/install.rb +3 -3
  11. data/lib/new_relic/agent.rb +4 -6
  12. data/lib/new_relic/agent/agent.rb +76 -72
  13. data/lib/new_relic/agent/autostart.rb +18 -5
  14. data/lib/new_relic/agent/browser_monitoring.rb +41 -35
  15. data/lib/new_relic/agent/browser_token.rb +38 -0
  16. data/lib/new_relic/agent/busy_calculator.rb +7 -5
  17. data/lib/new_relic/agent/commands/agent_command.rb +19 -0
  18. data/lib/new_relic/agent/commands/agent_command_router.rb +88 -0
  19. data/lib/new_relic/agent/commands/thread_profiler.rb +80 -0
  20. data/lib/new_relic/agent/configuration/default_source.rb +700 -0
  21. data/lib/new_relic/agent/configuration/environment_source.rb +83 -30
  22. data/lib/new_relic/agent/configuration/manager.rb +8 -8
  23. data/lib/new_relic/agent/configuration/mask_defaults.rb +2 -2
  24. data/lib/new_relic/agent/cross_app_monitor.rb +10 -21
  25. data/lib/new_relic/agent/cross_app_tracing.rb +3 -3
  26. data/lib/new_relic/agent/error_collector.rb +7 -10
  27. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -1
  28. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +5 -1
  29. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +5 -1
  30. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +5 -1
  31. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +5 -12
  33. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +4 -0
  34. data/lib/new_relic/agent/instrumentation/{rails4/active_record.rb → active_record_4.rb} +1 -1
  35. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +11 -11
  36. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -6
  37. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +12 -6
  38. data/lib/new_relic/agent/instrumentation/curb.rb +11 -2
  39. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -3
  40. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +11 -2
  41. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +13 -4
  42. data/lib/new_relic/agent/instrumentation/puma.rb +2 -1
  43. data/lib/new_relic/agent/instrumentation/rack.rb +15 -17
  44. data/lib/new_relic/agent/method_tracer.rb +181 -191
  45. data/lib/new_relic/agent/new_relic_service.rb +16 -14
  46. data/lib/new_relic/agent/pipe_channel_manager.rb +1 -1
  47. data/lib/new_relic/agent/request_sampler.rb +32 -165
  48. data/lib/new_relic/agent/sampled_buffer.rb +79 -0
  49. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +1 -8
  50. data/lib/new_relic/agent/sql_sampler.rb +3 -3
  51. data/lib/new_relic/agent/stats_engine.rb +1 -1
  52. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -1
  53. data/lib/new_relic/agent/stats_engine/metric_stats.rb +2 -3
  54. data/lib/new_relic/agent/stats_engine/transactions.rb +2 -22
  55. data/lib/new_relic/agent/threading/agent_thread.rb +41 -0
  56. data/lib/new_relic/agent/threading/backtrace_node.rb +71 -0
  57. data/lib/new_relic/agent/threading/thread_profile.rb +172 -0
  58. data/lib/new_relic/agent/transaction.rb +16 -4
  59. data/lib/new_relic/agent/transaction_sample_builder.rb +13 -3
  60. data/lib/new_relic/agent/transaction_sampler.rb +5 -8
  61. data/lib/new_relic/agent/transaction_state.rb +166 -0
  62. data/lib/new_relic/agent/transaction_timings.rb +53 -0
  63. data/lib/new_relic/cli/command.rb +91 -0
  64. data/lib/new_relic/{commands → cli}/deployments.rb +13 -9
  65. data/lib/new_relic/{commands → cli}/install.rb +2 -2
  66. data/lib/new_relic/control/frameworks/rails.rb +1 -8
  67. data/lib/new_relic/control/instance_methods.rb +1 -2
  68. data/lib/new_relic/helper.rb +9 -0
  69. data/lib/new_relic/local_environment.rb +16 -63
  70. data/lib/new_relic/rack/browser_monitoring.rb +8 -5
  71. data/lib/new_relic/recipes.rb +44 -31
  72. data/lib/new_relic/transaction_sample.rb +6 -2
  73. data/lib/new_relic/version.rb +1 -1
  74. data/lib/tasks/install.rake +21 -1
  75. data/newrelic_rpm.gemspec +5 -1
  76. data/test/agent_helper.rb +4 -9
  77. data/test/environments/.gitignore +16 -0
  78. data/test/environments/lib/environments/runner.rb +104 -0
  79. data/test/environments/norails/Gemfile +11 -0
  80. data/test/environments/norails/Rakefile +9 -0
  81. data/test/environments/rails21/Gemfile +24 -0
  82. data/test/environments/rails21/Rakefile +12 -0
  83. data/test/environments/rails21/app/controllers/application.rb +20 -0
  84. data/test/environments/rails21/config/boot.rb +113 -0
  85. data/test/environments/rails21/config/database.yml +31 -0
  86. data/test/environments/rails21/config/environment.rb +28 -0
  87. data/test/environments/rails21/config/environments/development.rb +16 -0
  88. data/test/environments/rails21/config/environments/production.rb +8 -0
  89. data/test/environments/rails21/config/environments/test.rb +10 -0
  90. data/test/environments/rails21/config/routes.rb +5 -0
  91. data/test/environments/rails21/db/schema.rb +5 -0
  92. data/test/environments/rails22/Gemfile +29 -0
  93. data/test/environments/rails22/Rakefile +12 -0
  94. data/test/environments/rails22/app/controllers/application.rb +20 -0
  95. data/test/environments/rails22/config/boot.rb +113 -0
  96. data/test/environments/rails22/config/database.yml +31 -0
  97. data/test/environments/rails22/config/environment.rb +27 -0
  98. data/test/environments/rails22/config/environments/development.rb +16 -0
  99. data/test/environments/rails22/config/environments/production.rb +8 -0
  100. data/test/environments/rails22/config/environments/test.rb +10 -0
  101. data/test/environments/rails22/config/routes.rb +5 -0
  102. data/test/environments/rails22/db/schema.rb +5 -0
  103. data/test/environments/rails23/Gemfile +22 -0
  104. data/test/environments/rails23/Rakefile +12 -0
  105. data/test/environments/rails23/app/controllers/application.rb +20 -0
  106. data/test/environments/rails23/config/boot.rb +127 -0
  107. data/test/environments/rails23/config/database.yml +31 -0
  108. data/test/environments/rails23/config/environment.rb +25 -0
  109. data/test/environments/rails23/config/environments/development.rb +16 -0
  110. data/test/environments/rails23/config/environments/production.rb +8 -0
  111. data/test/environments/rails23/config/environments/test.rb +10 -0
  112. data/test/environments/rails23/config/preinitializer.rb +25 -0
  113. data/test/environments/rails23/config/routes.rb +5 -0
  114. data/test/environments/rails23/db/schema.rb +5 -0
  115. data/test/environments/rails30/Gemfile +19 -0
  116. data/test/environments/rails30/Rakefile +9 -0
  117. data/test/environments/rails30/config/application.rb +17 -0
  118. data/test/environments/rails30/config/boot.rb +10 -0
  119. data/test/environments/rails30/config/database.yml +31 -0
  120. data/test/environments/rails30/config/environment.rb +6 -0
  121. data/test/environments/rails30/config/initializers/new_rails_defaults.rb +11 -0
  122. data/test/environments/rails30/db/schema.rb +5 -0
  123. data/test/environments/rails31/Gemfile +19 -0
  124. data/test/environments/rails31/Rakefile +9 -0
  125. data/test/environments/rails31/config/application.rb +18 -0
  126. data/test/environments/rails31/config/boot.rb +10 -0
  127. data/test/environments/rails31/config/database.yml +31 -0
  128. data/test/environments/rails31/config/environment.rb +6 -0
  129. data/test/environments/rails31/config/initializers/new_rails_defaults.rb +21 -0
  130. data/test/environments/rails31/db/schema.rb +5 -0
  131. data/test/environments/rails32/Gemfile +25 -0
  132. data/test/environments/rails32/Rakefile +9 -0
  133. data/test/environments/rails32/config/application.rb +19 -0
  134. data/test/environments/rails32/config/boot.rb +10 -0
  135. data/test/environments/rails32/config/database.yml +31 -0
  136. data/test/environments/rails32/config/environment.rb +6 -0
  137. data/test/environments/rails32/db/schema.rb +5 -0
  138. data/test/environments/rails40/Gemfile +25 -0
  139. data/test/environments/rails40/Rakefile +9 -0
  140. data/test/environments/rails40/config/application.rb +18 -0
  141. data/test/environments/rails40/config/boot.rb +10 -0
  142. data/test/environments/rails40/config/database.yml +31 -0
  143. data/test/environments/rails40/config/environment.rb +6 -0
  144. data/test/environments/rails40/db/schema.rb +5 -0
  145. data/test/multiverse/lib/multiverse/suite.rb +24 -12
  146. data/test/multiverse/suites/agent_only/logging_test.rb +18 -1
  147. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +1 -8
  148. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +10 -7
  149. data/test/multiverse/suites/curb/curb_test.rb +17 -3
  150. data/test/multiverse/suites/excon/Envfile +1 -1
  151. data/test/multiverse/suites/excon/excon_test.rb +18 -2
  152. data/test/multiverse/suites/httpclient/httpclient_test.rb +2 -2
  153. data/test/multiverse/suites/net_http/net_http_test.rb +2 -2
  154. data/test/multiverse/suites/rails/error_tracing_test.rb +35 -8
  155. data/test/multiverse/suites/rails/ignore_test.rb +48 -0
  156. data/test/multiverse/suites/rails/mongrel_queue_depth_test.rb +44 -0
  157. data/test/multiverse/suites/sequel/sequel_test.rb +11 -0
  158. data/test/multiverse/suites/sinatra/ignoring_test.rb +2 -2
  159. data/test/multiverse/suites/typhoeus/Envfile +9 -2
  160. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +3 -2
  161. data/test/new_relic/agent/agent/start_test.rb +3 -22
  162. data/test/new_relic/agent/agent_test.rb +6 -5
  163. data/test/new_relic/agent/autostart_test.rb +39 -1
  164. data/test/new_relic/agent/browser_monitoring_test.rb +43 -88
  165. data/test/new_relic/agent/browser_token_test.rb +52 -0
  166. data/test/new_relic/agent/busy_calculator_test.rb +1 -1
  167. data/test/new_relic/agent/commands/agent_command_router_test.rb +98 -0
  168. data/test/new_relic/agent/commands/agent_command_test.rb +37 -0
  169. data/test/new_relic/agent/commands/thread_profiler_test.rb +177 -0
  170. data/test/new_relic/agent/configuration/default_source_test.rb +81 -0
  171. data/test/new_relic/agent/configuration/environment_source_test.rb +81 -7
  172. data/test/new_relic/agent/configuration/manager_test.rb +16 -1
  173. data/test/new_relic/agent/cross_app_monitor_test.rb +3 -5
  174. data/test/new_relic/agent/error_collector_test.rb +14 -0
  175. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +1 -1
  176. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +2 -3
  177. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +29 -31
  178. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +22 -0
  179. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +2 -2
  180. data/test/new_relic/agent/method_tracer_test.rb +2 -2
  181. data/test/new_relic/agent/new_relic_service_test.rb +5 -49
  182. data/test/new_relic/agent/pipe_channel_manager_test.rb +1 -0
  183. data/test/new_relic/agent/request_sampler_test.rb +32 -95
  184. data/test/new_relic/agent/rpm_agent_test.rb +7 -5
  185. data/test/new_relic/agent/sampled_buffer_test.rb +178 -0
  186. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +0 -1
  187. data/test/new_relic/agent/stats_engine_test.rb +10 -17
  188. data/test/new_relic/agent/threading/agent_thread_test.rb +107 -0
  189. data/test/new_relic/agent/threading/backtrace_node_test.rb +96 -0
  190. data/test/new_relic/agent/{threaded_test.rb → threading/fake_thread.rb} +0 -25
  191. data/test/new_relic/agent/threading/thread_profile_test.rb +308 -0
  192. data/test/new_relic/agent/threading/threaded_test_case.rb +33 -0
  193. data/test/new_relic/agent/transaction/pop_test.rb +0 -16
  194. data/test/new_relic/agent/transaction_sample_builder_test.rb +23 -4
  195. data/test/new_relic/agent/transaction_sampler_test.rb +14 -15
  196. data/test/new_relic/agent/transaction_state_test.rb +75 -0
  197. data/test/new_relic/agent/transaction_test.rb +15 -0
  198. data/test/new_relic/agent/transaction_timings_test.rb +81 -0
  199. data/test/new_relic/agent_test.rb +12 -14
  200. data/test/new_relic/{command → cli}/deployments_test.rb +41 -13
  201. data/test/new_relic/control/frameworks/rails_test.rb +1 -2
  202. data/test/new_relic/control_test.rb +1 -2
  203. data/test/new_relic/dependency_detection_test.rb +14 -0
  204. data/test/new_relic/fake_collector.rb +1 -0
  205. data/test/new_relic/helper_test.rb +7 -2
  206. data/test/new_relic/http_client_test_cases.rb +33 -1
  207. data/test/new_relic/local_environment_test.rb +0 -23
  208. data/test/new_relic/metric_data_test.rb +4 -0
  209. data/test/new_relic/rack/browser_monitoring_test.rb +31 -30
  210. data/test/performance/lib/performance/result.rb +15 -4
  211. data/test/performance/lib/performance/timer.rb +7 -1
  212. data/test/performance/script/baselines +102 -0
  213. data/test/performance/suites/rum_autoinsertion.rb +57 -0
  214. data/test/rum/basic.result.html +10 -0
  215. data/test/rum/basic.source.html +10 -0
  216. data/test/rum/comments1.result.html +24 -0
  217. data/test/rum/comments1.source.html +24 -0
  218. data/test/rum/comments2.result.html +24 -0
  219. data/test/rum/comments2.source.html +24 -0
  220. data/test/rum/gt_in_quotes1.result.html +27 -0
  221. data/test/rum/gt_in_quotes1.source.html +27 -0
  222. data/test/rum/gt_in_quotes2.result.html +24 -0
  223. data/test/rum/gt_in_quotes2.source.html +24 -0
  224. data/test/rum/gt_in_quotes_mismatch.result.html +24 -0
  225. data/test/rum/gt_in_quotes_mismatch.source.html +24 -0
  226. data/test/rum/gt_in_single_quotes1.result.html +25 -0
  227. data/test/rum/gt_in_single_quotes1.source.html +25 -0
  228. data/test/rum/gt_in_single_quotes_mismatch.result.html +25 -0
  229. data/test/rum/gt_in_single_quotes_mismatch.source.html +25 -0
  230. data/test/rum/incomplete_non_meta_tags.result.html +10 -0
  231. data/test/rum/incomplete_non_meta_tags.source.html +10 -0
  232. data/test/rum/no_body.result.html +21 -0
  233. data/test/rum/no_body.source.html +21 -0
  234. data/test/rum/no_header.result.html +7 -0
  235. data/test/rum/no_header.source.html +7 -0
  236. data/test/rum/no_start_header.result.html +9 -0
  237. data/test/rum/no_start_header.source.html +9 -0
  238. data/test/rum/script1.result.html +19 -0
  239. data/test/rum/script1.source.html +19 -0
  240. data/test/rum/script2.result.html +17 -0
  241. data/test/rum/script2.source.html +17 -0
  242. data/test/rum/x_ua_meta_tag.result.html +10 -0
  243. data/test/rum/x_ua_meta_tag.source.html +10 -0
  244. data/test/rum/x_ua_meta_tag_multiline.result.html +11 -0
  245. data/test/rum/x_ua_meta_tag_multiline.source.html +11 -0
  246. data/test/rum/x_ua_meta_tag_with_others.result.html +11 -0
  247. data/test/rum/x_ua_meta_tag_with_others.source.html +11 -0
  248. data/test/rum/x_ua_meta_tag_with_spaces.result.html +10 -0
  249. data/test/rum/x_ua_meta_tag_with_spaces.source.html +10 -0
  250. data/test/script/ci.sh +1 -12
  251. data/test/test_helper.rb +1 -0
  252. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +11 -0
  253. metadata +225 -32
  254. metadata.gz.sig +0 -0
  255. data/lib/new_relic/agent/configuration/defaults.rb +0 -157
  256. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +0 -56
  257. data/lib/new_relic/agent/thread.rb +0 -37
  258. data/lib/new_relic/agent/thread_profiler.rb +0 -323
  259. data/lib/new_relic/agent/transaction_info.rb +0 -114
  260. data/lib/new_relic/command.rb +0 -89
  261. data/test/new_relic/agent/agent_test_controller_test.rb +0 -348
  262. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +0 -70
  263. data/test/new_relic/agent/thread_profiler_test.rb +0 -586
  264. data/test/new_relic/agent/thread_test.rb +0 -93
  265. data/test/new_relic/agent/transaction_info_test.rb +0 -99
@@ -17,6 +17,8 @@ module NewRelic
17
17
  event.scope = NewRelic::Agent.instance.stats_engine \
18
18
  .push_scope(:action_view, event.time)
19
19
  end
20
+ rescue => e
21
+ log_notification_error(e, name, 'start')
20
22
  end
21
23
 
22
24
  def finish(name, id, payload)
@@ -27,6 +29,8 @@ module NewRelic
27
29
  NewRelic::Agent.instance.stats_engine \
28
30
  .pop_scope(event.scope, event.metric_name, event.end)
29
31
  end
32
+ rescue => e
33
+ log_notification_error(e, name, 'finish')
30
34
  end
31
35
 
32
36
  def record_metrics(event)
@@ -4,7 +4,7 @@
4
4
  require 'new_relic/agent/instrumentation/active_record_subscriber'
5
5
 
6
6
  DependencyDetection.defer do
7
- @name = :active_record
7
+ named :active_record_4
8
8
 
9
9
  depends_on do
10
10
  defined?(::ActiveRecord) && defined?(::ActiveRecord::Base) &&
@@ -2,6 +2,7 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
  require 'new_relic/agent/instrumentation/active_record_helper'
5
+ require 'new_relic/agent/instrumentation/evented_subscriber'
5
6
 
6
7
  # Listen for ActiveSupport::Notifications events for ActiveRecord query
7
8
  # events. Write metric data, transaction trace segments and slow sql
@@ -9,22 +10,21 @@ require 'new_relic/agent/instrumentation/active_record_helper'
9
10
  module NewRelic
10
11
  module Agent
11
12
  module Instrumentation
12
- class ActiveRecordSubscriber
13
- include NewRelic::Agent::Instrumentation
14
-
15
- def self.subscribed?
16
- # TODO: need to talk to Rails core about an API for this,
17
- # rather than digging through Listener ivars
18
- ActiveSupport::Notifications.notifier.listeners_for('sql.active_record') \
19
- .find{|l| l.instance_variable_get(:@delegate).class == self }
13
+ class ActiveRecordSubscriber < EventedSubscriber
14
+ def start(name, id, payload)
15
+ return unless NewRelic::Agent.is_execution_traced?
16
+ super
17
+ rescue => e
18
+ log_notification_error(e, name, 'start')
20
19
  end
21
20
 
22
- def call(*args)
21
+ def finish(name, id, payload)
23
22
  return unless NewRelic::Agent.is_execution_traced?
24
-
25
- event = ActiveSupport::Notifications::Event.new(*args)
23
+ event = pop_event(id)
26
24
  record_metrics(event)
27
25
  notice_sql(event)
26
+ rescue => e
27
+ log_notification_error(e, name, 'finish')
28
28
  end
29
29
 
30
30
  def get_explain_plan( config, query )
@@ -6,18 +6,20 @@ DependencyDetection.defer do
6
6
  @name = :authlogic
7
7
 
8
8
  depends_on do
9
- defined?(AuthLogic) &&
10
- defined?(AuthLogic::Session) &&
11
- defined?(AuthLogic::Session::Base)
9
+ defined?(Authlogic) &&
10
+ defined?(Authlogic::Session) &&
11
+ defined?(Authlogic::Session::Base)
12
12
  end
13
13
 
14
14
  executes do
15
- ::NewRelic::Agent.logger.info 'Installing AuthLogic instrumentation'
15
+ ::NewRelic::Agent.logger.info 'Installing Authlogic instrumentation'
16
16
  end
17
17
 
18
18
  executes do
19
- AuthLogic::Session::Base.class_eval do
20
- add_method_tracer :find, 'Custom/Authlogic/find'
19
+ Authlogic::Session::Base.class_eval do
20
+ class << self
21
+ add_method_tracer :find, 'Custom/Authlogic/find'
22
+ end
21
23
  end
22
24
  end
23
25
  end
@@ -150,6 +150,14 @@ module NewRelic
150
150
  traced_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
151
151
  visibility = NewRelic::Helper.instance_method_visibility self, method
152
152
 
153
+ without_method_name = "#{traced_method.to_s}_without_newrelic_transaction_trace#{punctuation}"
154
+ with_method_name = "#{traced_method.to_s}_with_newrelic_transaction_trace#{punctuation}"
155
+
156
+ if NewRelic::Helper.instance_methods_include?(self, with_method_name)
157
+ ::NewRelic::Agent.logger.warn("Transaction tracer already in place for class = #{self.name}, method = #{method.to_s}, skipping")
158
+ return
159
+ end
160
+
153
161
  class_eval <<-EOC
154
162
  def #{traced_method.to_s}_with_newrelic_transaction_trace#{punctuation}(*args, &block)
155
163
  perform_action_with_newrelic_trace(#{options_arg.join(',')}) do
@@ -157,8 +165,6 @@ module NewRelic
157
165
  end
158
166
  end
159
167
  EOC
160
- without_method_name = "#{traced_method.to_s}_without_newrelic_transaction_trace#{punctuation}"
161
- with_method_name = "#{traced_method.to_s}_with_newrelic_transaction_trace#{punctuation}"
162
168
  alias_method without_method_name, method.to_s
163
169
  alias_method method.to_s, with_method_name
164
170
  send visibility, method
@@ -290,7 +296,7 @@ module NewRelic
290
296
  # path. This form is deprecated.
291
297
  def perform_action_with_newrelic_trace(*args, &block)
292
298
  request = newrelic_request(args)
293
- NewRelic::Agent::TransactionInfo.reset(request)
299
+ NewRelic::Agent::TransactionState.reset(request)
294
300
 
295
301
  # Skip instrumentation based on the value of 'do_not_trace' and if
296
302
  # we aren't calling directly with a block.
@@ -310,7 +316,7 @@ module NewRelic
310
316
  return yield if !(NewRelic::Agent.is_execution_traced? || options[:force])
311
317
  options[:metric] = true if options[:metric].nil?
312
318
  options[:deduct_call_time_from_parent] = true if options[:deduct_call_time_from_parent].nil?
313
- _, expected_scope = NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScoped.trace_execution_scoped_header(options, txn.start_time.to_f)
319
+ _, expected_scope = NewRelic::Agent::MethodTracer::TraceExecutionScoped.trace_execution_scoped_header(options, txn.start_time.to_f)
314
320
 
315
321
  begin
316
322
  NewRelic::Agent::BusyCalculator.dispatcher_start txn.start_time
@@ -337,12 +343,12 @@ module NewRelic
337
343
  metric_names = Array(recorded_metrics(txn))
338
344
  txn_name = metric_names.shift
339
345
 
340
- NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScoped.trace_execution_scoped_footer(txn.start_time.to_f, txn_name, metric_names, expected_scope, options, end_time.to_f)
346
+ NewRelic::Agent::MethodTracer::TraceExecutionScoped.trace_execution_scoped_footer(txn.start_time.to_f, txn_name, metric_names, expected_scope, options, end_time.to_f)
341
347
  NewRelic::Agent::BusyCalculator.dispatcher_finish(end_time)
342
348
  txn.record_apdex(end_time) unless ignore_apdex?
343
349
  txn = Transaction.stop(txn_name, end_time)
344
350
 
345
- NewRelic::Agent::TransactionInfo.get.ignore_end_user = true if ignore_enduser?
351
+ NewRelic::Agent::TransactionState.get.request_ignore_enduser = true if ignore_enduser?
346
352
  end
347
353
  end
348
354
 
@@ -73,9 +73,18 @@ DependencyDetection.defer do
73
73
 
74
74
  # We override this method in order to ensure access to header_str even
75
75
  # though we use an on_header callback
76
- def header_str
77
- self._nr_header_str
76
+ def header_str_with_newrelic
77
+ if self._nr_serial
78
+ self._nr_header_str
79
+ else
80
+ # Since we didn't install a header callback for a non-serial request,
81
+ # just fall back to the original implementation.
82
+ header_str_without_newrelic
83
+ end
78
84
  end
85
+
86
+ alias_method :header_str_without_newrelic, :header_str
87
+ alias_method :header_str, :header_str_with_newrelic
79
88
  end # class Curl::Easy
80
89
 
81
90
 
@@ -32,9 +32,7 @@ DependencyDetection.defer do
32
32
  if defined?(::Delayed::Job) && ::Delayed::Job.method_defined?(:invoke_job)
33
33
  ::NewRelic::Agent.logger.info 'Installing DelayedJob instrumentation [part 2/2]'
34
34
  install_newrelic_job_tracer
35
-
36
- dispatcher_instance_id = worker_name || "host:#{Socket.gethostname} pid:#{Process.pid}" rescue "pid:#{Process.pid}"
37
- NewRelic::Control.instance.init_plugin :dispatcher => :delayed_job, :dispatcher_instance_id => dispatcher_instance_id
35
+ NewRelic::Control.instance.init_plugin :dispatcher => :delayed_job
38
36
  else
39
37
  NewRelic::Agent.logger.warn("Did not find a Delayed::Job class responding to invoke_job, aborting DJ instrumentation")
40
38
  end
@@ -33,10 +33,19 @@ module NewRelic
33
33
  pop_event(id)
34
34
  end
35
35
 
36
+ def log_notification_error(error, name, event_type)
37
+ # These are important enough failures that we want the backtraces
38
+ # logged at error level, hence the explicit log_exception call.
39
+ NewRelic::Agent.logger.error("Error during #{event_type} callback for event '#{name}':")
40
+ NewRelic::Agent.logger.log_exception(:error, error)
41
+ end
42
+
36
43
  def push_event(event)
37
44
  parent = event_stack[event.transaction_id].last
38
- event.parent = parent
39
- parent << event if parent
45
+ if parent && event.respond_to?(:parent=)
46
+ event.parent = parent
47
+ parent << event
48
+ end
40
49
  event_stack[event.transaction_id].push event
41
50
  end
42
51
 
@@ -5,15 +5,23 @@
5
5
  module ::Excon
6
6
  module Middleware
7
7
  class NewRelicCrossAppTracing
8
+ TRACE_DATA_IVAR = :@newrelic_trace_data
9
+
8
10
  def initialize(stack)
9
11
  @stack = stack
10
12
  end
11
13
 
12
14
  def request_call(datum)
13
15
  begin
14
- wrapped_request = ::NewRelic::Agent::HTTPClients::ExconHTTPRequest.new(datum)
15
- t0, segment = ::NewRelic::Agent::CrossAppTracing.start_trace(wrapped_request)
16
- datum[:newrelic_trace_data] = [t0, segment, wrapped_request]
16
+ # Only instrument this request if we haven't already done so, because
17
+ # we can get request_call multiple times for requests marked as
18
+ # :idempotent in the options, but there will be only a single
19
+ # accompanying response_call/error_call.
20
+ if datum[:connection] && !datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
21
+ wrapped_request = ::NewRelic::Agent::HTTPClients::ExconHTTPRequest.new(datum)
22
+ t0, segment = ::NewRelic::Agent::CrossAppTracing.start_trace(wrapped_request)
23
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, [t0, segment, wrapped_request])
24
+ end
17
25
  rescue => e
18
26
  NewRelic::Agent.logger.debug(e)
19
27
  end
@@ -31,8 +39,9 @@ module ::Excon
31
39
  end
32
40
 
33
41
  def finish_trace(datum)
34
- trace_data = datum.delete(:newrelic_trace_data)
42
+ trace_data = datum[:connection] && datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
35
43
  if trace_data
44
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, nil)
36
45
  t0, segment, wrapped_request = trace_data
37
46
  if datum[:response]
38
47
  wrapped_response = ::NewRelic::Agent::HTTPClients::ExconHTTPResponse.new(datum[:response])
@@ -8,7 +8,8 @@ DependencyDetection.defer do
8
8
  depends_on do
9
9
  defined?(::Puma) &&
10
10
  defined?(::Puma::Const::VERSION) &&
11
- NewRelic::VersionNumber.new(::Puma::Const::VERSION) > NewRelic::VersionNumber.new("2.0.0")
11
+ NewRelic::VersionNumber.new(::Puma::Const::VERSION) > NewRelic::VersionNumber.new("2.0.0") &&
12
+ ::Puma.respond_to?(:cli_config)
12
13
  end
13
14
 
14
15
  executes do
@@ -114,28 +114,26 @@ DependencyDetection.defer do
114
114
  end
115
115
 
116
116
  executes do
117
- unless ::Rack::Builder.respond_to?(:_nr_deferred_detection_ran)
118
- class ::Rack::Builder
117
+ class ::Rack::Builder
119
118
 
120
- class << self
121
- attr_accessor :_nr_deferred_detection_ran
122
- end
123
- self._nr_deferred_detection_ran = false
124
-
125
- def to_app_with_newrelic_deferred_dependency_detection
126
- unless Rack::Builder._nr_deferred_detection_ran
127
- NewRelic::Agent.logger.info "Doing deferred dependency-detection before Rack startup"
128
- DependencyDetection.detect!
129
- Rack::Builder._nr_deferred_detection_ran = true
130
- end
119
+ class << self
120
+ attr_accessor :_nr_deferred_detection_ran
121
+ end
122
+ self._nr_deferred_detection_ran = false
131
123
 
132
- to_app_without_newrelic
124
+ def to_app_with_newrelic_deferred_dependency_detection
125
+ unless Rack::Builder._nr_deferred_detection_ran
126
+ NewRelic::Agent.logger.info "Doing deferred dependency-detection before Rack startup"
127
+ DependencyDetection.detect!
128
+ Rack::Builder._nr_deferred_detection_ran = true
133
129
  end
134
130
 
135
- alias_method :to_app_without_newrelic, :to_app
136
- alias_method :to_app, :to_app_with_newrelic_deferred_dependency_detection
137
-
131
+ to_app_without_newrelic
138
132
  end
133
+
134
+ alias_method :to_app_without_newrelic, :to_app
135
+ alias_method :to_app, :to_app_with_newrelic_deferred_dependency_detection
136
+
139
137
  end
140
138
  end
141
139
  end
@@ -41,240 +41,230 @@ module NewRelic
41
41
 
42
42
  def self.included clazz #:nodoc:
43
43
  clazz.extend ClassMethods
44
- clazz.send :include, InstanceMethods
45
44
  end
46
45
 
47
46
  def self.extended clazz #:nodoc:
48
47
  clazz.extend ClassMethods
49
- clazz.extend InstanceMethods
50
48
  end
51
49
 
52
- # Defines modules used at instrumentation runtime, to do the
53
- # actual tracing of time spent
54
- module InstanceMethods
55
- # Deprecated: original method preserved for API backward compatibility.
56
- # Use either #trace_execution_scoped or #trace_execution_unscoped
57
- def trace_method_execution(metric_names, push_scope, produce_metric, deduct_call_time_from_parent, &block) #:nodoc:
58
- if push_scope
59
- trace_execution_scoped(metric_names, :metric => produce_metric,
60
- :deduct_call_time_from_parent => deduct_call_time_from_parent, &block)
61
- else
62
- trace_execution_unscoped(metric_names, &block)
63
- end
50
+ # Deprecated: original method preserved for API backward compatibility.
51
+ # Use either #trace_execution_scoped or #trace_execution_unscoped
52
+ def trace_method_execution(metric_names, push_scope, produce_metric, deduct_call_time_from_parent, &block) #:nodoc:
53
+ if push_scope
54
+ trace_execution_scoped(metric_names, :metric => produce_metric,
55
+ :deduct_call_time_from_parent => deduct_call_time_from_parent, &block)
56
+ else
57
+ trace_execution_unscoped(metric_names, &block)
64
58
  end
59
+ end
65
60
 
66
- # Trace a given block with stats assigned to the given metric_name. It does not
67
- # provide scoped measurements, meaning whatever is being traced will not 'blame the
68
- # Controller'--that is to say appear in the breakdown chart.
69
- # This is code is inlined in #add_method_tracer.
70
- # * <tt>metric_names</tt> is a single name or an array of names of metrics
71
- # * <tt>:force => true</tt> will force the metric to be captured even when
72
- # tracing is disabled with NewRelic::Agent#disable_all_tracing
73
- #
74
- def trace_execution_unscoped(metric_names, options={})
75
- return yield unless NewRelic::Agent.is_execution_traced?
76
- t0 = Time.now
77
- begin
78
- NewRelic::Agent.instance.push_trace_execution_flag(true) if options[:force]
79
- yield
80
- ensure
81
- NewRelic::Agent.instance.pop_trace_execution_flag if options[:force]
82
- duration = (Time.now - t0).to_f # for some reason this is 3 usec faster than Time - Time
83
- stat_engine.record_metrics(metric_names, duration)
84
- end
61
+ # Trace a given block with stats assigned to the given metric_name. It does not
62
+ # provide scoped measurements, meaning whatever is being traced will not 'blame the
63
+ # Controller'--that is to say appear in the breakdown chart.
64
+ # This is code is inlined in #add_method_tracer.
65
+ # * <tt>metric_names</tt> is a single name or an array of names of metrics
66
+ # * <tt>:force => true</tt> will force the metric to be captured even when
67
+ # tracing is disabled with NewRelic::Agent#disable_all_tracing
68
+ #
69
+ def trace_execution_unscoped(metric_names, options={})
70
+ return yield unless NewRelic::Agent.is_execution_traced?
71
+ t0 = Time.now
72
+ begin
73
+ NewRelic::Agent.instance.push_trace_execution_flag(true) if options[:force]
74
+ yield
75
+ ensure
76
+ NewRelic::Agent.instance.pop_trace_execution_flag if options[:force]
77
+ duration = (Time.now - t0).to_f # for some reason this is 3 usec faster than Time - Time
78
+ stat_engine.record_metrics(metric_names, duration)
85
79
  end
80
+ end
86
81
 
87
- # Deprecated. Use #trace_execution_scoped, a version with an options hash.
88
- def trace_method_execution_with_scope(metric_names, produce_metric, deduct_call_time_from_parent, scoped_metric_only=false, &block) #:nodoc:
89
- trace_execution_scoped(metric_names,
90
- :metric => produce_metric,
91
- :deduct_call_time_from_parent => deduct_call_time_from_parent,
92
- :scoped_metric_only => scoped_metric_only, &block)
93
- end
82
+ # Deprecated. Use #trace_execution_scoped, a version with an options hash.
83
+ def trace_method_execution_with_scope(metric_names, produce_metric, deduct_call_time_from_parent, scoped_metric_only=false, &block) #:nodoc:
84
+ trace_execution_scoped(metric_names,
85
+ :metric => produce_metric,
86
+ :deduct_call_time_from_parent => deduct_call_time_from_parent,
87
+ :scoped_metric_only => scoped_metric_only, &block)
88
+ end
94
89
 
95
- alias trace_method_execution_no_scope trace_execution_unscoped #:nodoc:
90
+ alias trace_method_execution_no_scope trace_execution_unscoped #:nodoc:
96
91
 
97
- # Refactored out of the previous trace_execution_scoped
98
- # method, most methods in this module relate to code used in
99
- # the #trace_execution_scoped method in this module
100
- module TraceExecutionScoped
101
- extend self
92
+ # Refactored out of the previous trace_execution_scoped
93
+ # method, most methods in this module relate to code used in
94
+ # the #trace_execution_scoped method in this module
95
+ module TraceExecutionScoped
96
+ extend self
102
97
 
103
- # Shorthand to return the NewRelic::Agent.instance
104
- def agent_instance
105
- NewRelic::Agent.instance
106
- end
98
+ # Shorthand to return the NewRelic::Agent.instance
99
+ def agent_instance
100
+ NewRelic::Agent.instance
101
+ end
107
102
 
108
- # Shorthand to return the status of tracing
109
- def traced?
110
- NewRelic::Agent.is_execution_traced?
111
- end
103
+ # Shorthand to return the status of tracing
104
+ def traced?
105
+ NewRelic::Agent.is_execution_traced?
106
+ end
112
107
 
113
- # Tracing is disabled if we are not in a traced context and
114
- # no force option is supplied
115
- def trace_disabled?(options)
116
- !(traced? || options[:force])
117
- end
108
+ # Tracing is disabled if we are not in a traced context and
109
+ # no force option is supplied
110
+ def trace_disabled?(options)
111
+ !(traced? || options[:force])
112
+ end
118
113
 
119
- # Shorthand to return the current statistics engine
120
- def stat_engine
121
- agent_instance.stats_engine
122
- end
114
+ # Shorthand to return the current statistics engine
115
+ def stat_engine
116
+ agent_instance.stats_engine
117
+ end
123
118
 
124
- # returns a scoped metric stat for the specified name
125
- def get_stats_scoped(first_name, scoped_metric_only)
126
- stat_engine.get_stats(first_name, true, scoped_metric_only)
127
- end
128
- # Shorthand method to get stats from the stat engine
129
- def get_stats_unscoped(name)
130
- stat_engine.get_stats_no_scope(name)
131
- end
119
+ # returns a scoped metric stat for the specified name
120
+ def get_stats_scoped(first_name, scoped_metric_only)
121
+ stat_engine.get_stats(first_name, true, scoped_metric_only)
122
+ end
123
+ # Shorthand method to get stats from the stat engine
124
+ def get_stats_unscoped(name)
125
+ stat_engine.get_stats_no_scope(name)
126
+ end
132
127
 
133
- # Helper for setting a hash key if the hash key is nil,
134
- # instead of the default ||= behavior which sets if it is
135
- # false as well
136
- def set_if_nil(hash, key)
137
- hash[key] = true if hash[key].nil?
138
- end
128
+ # Helper for setting a hash key if the hash key is nil,
129
+ # instead of the default ||= behavior which sets if it is
130
+ # false as well
131
+ def set_if_nil(hash, key)
132
+ hash[key] = true if hash[key].nil?
133
+ end
139
134
 
140
- # delegates to #agent_instance to push a trace execution
141
- # flag, only if execution of this metric is forced.
142
- #
143
- # This causes everything scoped inside this metric to be
144
- # recorded, even if the parent transaction is generally not.
145
- def push_flag!(forced)
146
- agent_instance.push_trace_execution_flag(true) if forced
147
- end
135
+ # delegates to #agent_instance to push a trace execution
136
+ # flag, only if execution of this metric is forced.
137
+ #
138
+ # This causes everything scoped inside this metric to be
139
+ # recorded, even if the parent transaction is generally not.
140
+ def push_flag!(forced)
141
+ agent_instance.push_trace_execution_flag(true) if forced
142
+ end
148
143
 
149
- # delegates to #agent_instance to pop the trace execution
150
- # flag, only if execution of this metric is
151
- # forced. otherwise this is taken care of for us
152
- # automatically.
153
- #
154
- # This ends the forced recording of metrics within the
155
- # #trace_execution_scoped block
156
- def pop_flag!(forced)
157
- agent_instance.pop_trace_execution_flag if forced
158
- end
144
+ # delegates to #agent_instance to pop the trace execution
145
+ # flag, only if execution of this metric is
146
+ # forced. otherwise this is taken care of for us
147
+ # automatically.
148
+ #
149
+ # This ends the forced recording of metrics within the
150
+ # #trace_execution_scoped block
151
+ def pop_flag!(forced)
152
+ agent_instance.pop_trace_execution_flag if forced
153
+ end
159
154
 
160
- # helper for logging errors to the newrelic_agent.log
161
- # properly. Logs the error at error level
162
- def log_errors(code_area)
163
- yield
164
- rescue => e
165
- ::NewRelic::Agent.logger.error("Caught exception in #{code_area}.", e)
166
- end
155
+ # helper for logging errors to the newrelic_agent.log
156
+ # properly. Logs the error at error level
157
+ def log_errors(code_area)
158
+ yield
159
+ rescue => e
160
+ ::NewRelic::Agent.logger.error("Caught exception in #{code_area}.", e)
161
+ end
167
162
 
168
- # provides the header for our traced execution scoped
169
- # method - gets the initial time, sets the tracing flag if
170
- # needed, and pushes the scope onto the metric stack
171
- # logs any errors that occur and returns the start time and
172
- # the scope so that we can check for it later, to maintain
173
- # sanity. If the scope stack becomes unbalanced, this
174
- # transaction loses meaning.
175
- def trace_execution_scoped_header(options, t0=Time.now.to_f)
176
- scope = log_errors("trace_execution_scoped header") do
177
- push_flag!(options[:force])
178
- scope = stat_engine.push_scope(:method_tracer, t0, options[:deduct_call_time_from_parent])
179
- end
180
- # needed in case we have an error, above, to always return
181
- # the start time.
182
- [t0, scope]
183
- end
163
+ # provides the header for our traced execution scoped
164
+ # method - gets the initial time, sets the tracing flag if
165
+ # needed, and pushes the scope onto the metric stack
166
+ # logs any errors that occur and returns the start time and
167
+ # the scope so that we can check for it later, to maintain
168
+ # sanity. If the scope stack becomes unbalanced, this
169
+ # transaction loses meaning.
170
+ def trace_execution_scoped_header(options, t0=Time.now.to_f)
171
+ scope = log_errors("trace_execution_scoped header") do
172
+ push_flag!(options[:force])
173
+ scope = stat_engine.push_scope(:method_tracer, t0, options[:deduct_call_time_from_parent])
174
+ end
175
+ # needed in case we have an error, above, to always return
176
+ # the start time.
177
+ [t0, scope]
178
+ end
184
179
 
185
- def metrics_for_current_transaction(first_name, other_names, options)
186
- metrics = []
180
+ def metrics_for_current_transaction(first_name, other_names, options)
181
+ metrics = []
187
182
 
183
+ if !options[:scoped_metric_only]
184
+ metrics += other_names.map { |n| NewRelic::MetricSpec.new(n) }
185
+ end
186
+
187
+ if options[:metric]
188
188
  if !options[:scoped_metric_only]
189
- metrics += other_names.map { |n| NewRelic::MetricSpec.new(n) }
189
+ metrics << NewRelic::MetricSpec.new(first_name)
190
190
  end
191
-
192
- if options[:metric]
193
- if !options[:scoped_metric_only]
194
- metrics << NewRelic::MetricSpec.new(first_name)
195
- end
196
- if in_transaction? && !options[:transaction]
197
- metrics << NewRelic::MetricSpec.new(first_name, StatsEngine::MetricStats::SCOPE_PLACEHOLDER)
198
- end
191
+ if NewRelic::Agent::Transaction.in_transaction? && !options[:transaction]
192
+ metrics << NewRelic::MetricSpec.new(first_name, StatsEngine::MetricStats::SCOPE_PLACEHOLDER)
199
193
  end
200
-
201
- metrics
202
194
  end
203
195
 
204
- def in_transaction?
205
- NewRelic::Agent::Transaction.in_transaction?
206
- end
196
+ metrics
197
+ end
207
198
 
208
- def has_parent?
209
- !NewRelic::Agent::Transaction.parent.nil?
210
- end
199
+ def has_parent?
200
+ !NewRelic::Agent::Transaction.parent.nil?
201
+ end
211
202
 
212
- def metrics_for_parent_transaction(first_name, options)
213
- if has_parent? && options[:metric] && options[:transaction]
214
- [NewRelic::MetricSpec.new(first_name, StatsEngine::MetricStats::SCOPE_PLACEHOLDER)]
215
- else
216
- []
217
- end
203
+ def metrics_for_parent_transaction(first_name, options)
204
+ if has_parent? && options[:metric] && options[:transaction]
205
+ [NewRelic::MetricSpec.new(first_name, StatsEngine::MetricStats::SCOPE_PLACEHOLDER)]
206
+ else
207
+ []
218
208
  end
209
+ end
219
210
 
220
- def record_metrics(first_name, other_names, duration, exclusive, options)
221
- metrics = metrics_for_current_transaction(first_name, other_names, options)
222
- stat_engine.record_metrics_internal(metrics, duration, exclusive)
211
+ def record_metrics(first_name, other_names, duration, exclusive, options)
212
+ metrics = metrics_for_current_transaction(first_name, other_names, options)
213
+ stat_engine.record_metrics_internal(metrics, duration, exclusive)
223
214
 
224
- parent_metrics = metrics_for_parent_transaction(first_name, options)
225
- parent_metrics.each do |metric|
226
- parent_txn = NewRelic::Agent::Transaction.parent
227
- parent_txn.stats_hash.record(metric, duration, exclusive)
228
- end
215
+ parent_metrics = metrics_for_parent_transaction(first_name, options)
216
+ parent_metrics.each do |metric|
217
+ parent_txn = NewRelic::Agent::Transaction.parent
218
+ parent_txn.stats_hash.record(metric, duration, exclusive)
229
219
  end
220
+ end
230
221
 
231
- # Handles the end of the #trace_execution_scoped method -
232
- # calculating the time taken, popping the tracing flag if
233
- # needed, deducting time taken by children, and tracing the
234
- # subsidiary unscoped metrics if any
235
- #
236
- # this method fails safely if the header does not manage to
237
- # push the scope onto the stack - it simply does not trace
238
- # any metrics.
239
- def trace_execution_scoped_footer(t0, first_name, metric_names, expected_scope, options, t1=Time.now.to_f)
240
- log_errors("trace_method_execution footer") do
241
- pop_flag!(options[:force])
242
- if expected_scope
243
- scope = stat_engine.pop_scope(expected_scope, first_name, t1)
244
- duration = t1 - t0
245
- exclusive = duration - scope.children_time
246
- record_metrics(first_name, metric_names, duration, exclusive, options)
247
- end
222
+ # Handles the end of the #trace_execution_scoped method -
223
+ # calculating the time taken, popping the tracing flag if
224
+ # needed, deducting time taken by children, and tracing the
225
+ # subsidiary unscoped metrics if any
226
+ #
227
+ # this method fails safely if the header does not manage to
228
+ # push the scope onto the stack - it simply does not trace
229
+ # any metrics.
230
+ def trace_execution_scoped_footer(t0, first_name, metric_names, expected_scope, options, t1=Time.now.to_f)
231
+ log_errors("trace_method_execution footer") do
232
+ pop_flag!(options[:force])
233
+ if expected_scope
234
+ scope = stat_engine.pop_scope(expected_scope, first_name, t1)
235
+ duration = t1 - t0
236
+ exclusive = duration - scope.children_time
237
+ record_metrics(first_name, metric_names, duration, exclusive, options)
248
238
  end
249
239
  end
240
+ end
250
241
 
251
- # Trace a given block with stats and keep track of the caller.
252
- # See NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer for a description of the arguments.
253
- # +metric_names+ is either a single name or an array of metric names.
254
- # If more than one metric is passed, the +produce_metric+ option only applies to the first. The
255
- # others are always recorded. Only the first metric is pushed onto the scope stack.
256
- #
257
- # Generally you pass an array of metric names if you want to record the metric under additional
258
- # categories, but generally this *should never ever be done*. Most of the time you can aggregate
259
- # on the server.
260
- def trace_execution_scoped(metric_names, options={})
261
- return yield if trace_disabled?(options)
262
- set_if_nil(options, :metric)
263
- set_if_nil(options, :deduct_call_time_from_parent)
264
- metric_names = Array(metric_names)
265
- first_name = metric_names.shift
266
- start_time, expected_scope = trace_execution_scoped_header(options)
267
- begin
268
- yield
269
- ensure
270
- trace_execution_scoped_footer(start_time, first_name, metric_names, expected_scope, options)
271
- end
242
+ # Trace a given block with stats and keep track of the caller.
243
+ # See NewRelic::Agent::MethodTracer::ClassMethods#add_method_tracer for a description of the arguments.
244
+ # +metric_names+ is either a single name or an array of metric names.
245
+ # If more than one metric is passed, the +produce_metric+ option only applies to the first. The
246
+ # others are always recorded. Only the first metric is pushed onto the scope stack.
247
+ #
248
+ # Generally you pass an array of metric names if you want to record the metric under additional
249
+ # categories, but generally this *should never ever be done*. Most of the time you can aggregate
250
+ # on the server.
251
+ def trace_execution_scoped(metric_names, options={})
252
+ return yield if trace_disabled?(options)
253
+ set_if_nil(options, :metric)
254
+ set_if_nil(options, :deduct_call_time_from_parent)
255
+ metric_names = Array(metric_names)
256
+ first_name = metric_names.shift
257
+ start_time, expected_scope = trace_execution_scoped_header(options)
258
+ begin
259
+ yield
260
+ ensure
261
+ trace_execution_scoped_footer(start_time, first_name, metric_names, expected_scope, options)
272
262
  end
273
-
274
263
  end
275
- include TraceExecutionScoped
276
264
 
277
265
  end
266
+ include TraceExecutionScoped
267
+
278
268
 
279
269
  # Defines methods used at the class level, for adding instrumentation
280
270
  module ClassMethods