newrelic_rpm 3.6.4.122 → 3.6.5.130

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +14 -1
  3. data/lib/new_relic/agent.rb +8 -7
  4. data/lib/new_relic/agent/agent.rb +2 -0
  5. data/lib/new_relic/agent/configuration/defaults.rb +1 -1
  6. data/lib/new_relic/agent/configuration/server_source.rb +2 -1
  7. data/lib/new_relic/agent/cross_app_tracing.rb +52 -26
  8. data/lib/new_relic/agent/event_listener.rb +1 -1
  9. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +61 -0
  10. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +46 -0
  11. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +72 -0
  12. data/lib/new_relic/agent/{uri_util.rb → http_clients/uri_util.rb} +11 -17
  13. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +4 -11
  14. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +2 -2
  16. data/lib/new_relic/agent/instrumentation/excon.rb +72 -0
  17. data/lib/new_relic/agent/instrumentation/excon/connection.rb +33 -0
  18. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +45 -0
  19. data/lib/new_relic/agent/instrumentation/net.rb +3 -1
  20. data/lib/new_relic/agent/instrumentation/typhoeus.rb +73 -0
  21. data/lib/new_relic/agent/method_tracer.rb +3 -6
  22. data/lib/new_relic/agent/new_relic_service.rb +1 -1
  23. data/lib/new_relic/agent/samplers/object_sampler.rb +1 -1
  24. data/lib/new_relic/agent/stats.rb +12 -10
  25. data/lib/new_relic/agent/stats_engine/metric_stats.rb +24 -6
  26. data/lib/new_relic/agent/stats_engine/stats_hash.rb +9 -11
  27. data/lib/new_relic/agent/transaction.rb +34 -33
  28. data/lib/new_relic/agent/transaction_sampler.rb +15 -6
  29. data/lib/new_relic/language_support.rb +8 -0
  30. data/lib/new_relic/local_environment.rb +10 -14
  31. data/lib/new_relic/version.rb +1 -1
  32. data/test/agent_helper.rb +43 -0
  33. data/test/config/test.cert.crt +14 -0
  34. data/test/config/test.cert.csr +11 -0
  35. data/test/config/test.cert.key +15 -0
  36. data/test/config/testing-privkey.pem +18 -0
  37. data/test/multiverse/lib/multiverse/color.rb +9 -3
  38. data/test/multiverse/lib/multiverse/suite.rb +11 -1
  39. data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -0
  40. data/test/multiverse/suites/agent_only/config/newrelic.yml +4 -0
  41. data/test/multiverse/suites/agent_only/http_response_code_test.rb +1 -1
  42. data/test/multiverse/suites/agent_only/rename_rule_test.rb +2 -1
  43. data/test/multiverse/suites/agent_only/start_up_test.rb +3 -2
  44. data/test/multiverse/suites/config_file_loading/Envfile +2 -0
  45. data/test/multiverse/suites/excon/Envfile +15 -0
  46. data/test/multiverse/suites/excon/config/newrelic.yml +21 -0
  47. data/test/multiverse/suites/excon/excon_test.rb +60 -0
  48. data/test/multiverse/suites/net_http/Envfile +6 -0
  49. data/test/multiverse/suites/net_http/config/newrelic.yml +21 -0
  50. data/test/multiverse/suites/net_http/net_http_test.rb +102 -0
  51. data/test/multiverse/suites/rails/Envfile +1 -1
  52. data/test/multiverse/suites/rails/view_instrumentation_test.rb +6 -0
  53. data/test/multiverse/suites/resque/Envfile +0 -9
  54. data/test/multiverse/suites/resque/instrumentation_test.rb +21 -6
  55. data/test/multiverse/suites/typhoeus/Envfile +46 -0
  56. data/test/multiverse/suites/typhoeus/config/newrelic.yml +21 -0
  57. data/test/multiverse/suites/typhoeus/typhoeus_test.rb +77 -0
  58. data/test/new_relic/agent/agent_test_controller_test.rb +11 -10
  59. data/test/new_relic/agent/configuration/server_source_test.rb +23 -9
  60. data/test/new_relic/agent/database_test.rb +6 -0
  61. data/test/new_relic/agent/http_clients/uri_util_test.rb +64 -0
  62. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +0 -406
  63. data/test/new_relic/agent/new_relic_service_test.rb +23 -19
  64. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +29 -12
  65. data/test/new_relic/agent/stats_hash_test.rb +24 -3
  66. data/test/new_relic/agent/stats_test.rb +4 -4
  67. data/test/new_relic/agent/transaction/pop_test.rb +1 -1
  68. data/test/new_relic/agent/transaction_sampler_test.rb +18 -0
  69. data/test/new_relic/agent/transaction_test.rb +64 -69
  70. data/test/new_relic/agent_test.rb +20 -0
  71. data/test/new_relic/dependency_detection_test.rb +99 -0
  72. data/test/new_relic/evil_server.rb +56 -0
  73. data/test/new_relic/fake_collector.rb +12 -96
  74. data/test/new_relic/fake_external_server.rb +55 -0
  75. data/test/new_relic/fake_server.rb +97 -0
  76. data/test/new_relic/http_client_test_cases.rb +444 -0
  77. data/test/new_relic/language_support_test.rb +45 -0
  78. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +25 -4
  79. metadata +37 -35
  80. metadata.gz.sig +0 -0
  81. data/test/multiverse/suites/resque/resque_setup.rb +0 -19
  82. data/test/new_relic/agent/uri_util_test.rb +0 -75
@@ -11,25 +11,19 @@
11
11
 
12
12
  module NewRelic
13
13
  module Agent
14
- module URIUtil
15
- def self.uri_from_connection_and_request(http, request)
16
- parsed = case request.path
17
- when /^https?:\/\//
18
- URI(request.path)
19
- else
20
- scheme = http.use_ssl? ? 'https' : 'http'
21
- URI("#{scheme}://#{http.address}:#{http.port}#{request.path}")
14
+ module HTTPClients
15
+ module URIUtil
16
+
17
+ def self.filter_uri(original)
18
+ filtered = original.dup
19
+ filtered.user = nil
20
+ filtered.password = nil
21
+ filtered.query = nil
22
+ filtered.fragment = nil
23
+ filtered.to_s
22
24
  end
23
- end
24
25
 
25
- def self.filtered_uri_for(http, request)
26
- parsed = uri_from_connection_and_request(http, request)
27
- parsed.user = nil
28
- parsed.password = nil
29
- parsed.query = nil
30
- parsed.fragment = nil
31
- parsed.to_s
32
26
  end
33
27
  end
34
28
  end
35
- end
29
+ end
@@ -63,8 +63,8 @@ module NewRelic
63
63
  txn = Transaction.current
64
64
  metrics = [ 'HttpDispatcher']
65
65
  if txn.has_parent?
66
- controller_metric.scope = StatsEngine::MetricStats::SCOPE_PLACEHOLDER
67
- record_metric_on_parent_transaction(controller_metric, event.duration)
66
+ parent_metric = MetricSpec.new(event.metric_name, StatsEngine::MetricStats::SCOPE_PLACEHOLDER)
67
+ record_metric_on_parent_transaction(parent_metric, event.duration)
68
68
  end
69
69
  metrics << controller_metric.dup
70
70
 
@@ -72,19 +72,12 @@ module NewRelic
72
72
  end
73
73
 
74
74
  def record_metric_on_parent_transaction(metric, time)
75
- txn = NewRelic::Agent::Transaction.current
76
- txn.parent.stats_hash.record(metric, time)
75
+ NewRelic::Agent::Transaction.parent.stats_hash.record(metric, time)
77
76
  end
78
77
 
79
78
  def record_apdex(event)
80
79
  return if event.apdex_ignored?
81
- metric_parser = MetricParser::MetricParser \
82
- .for_metric_named(event.metric_name)
83
- duration_plus_queue_time = event.end - (event.queue_start || event.time)
84
- Transaction.record_apdex(metric_parser,
85
- event.duration,
86
- duration_plus_queue_time,
87
- event.exception_encountered?)
80
+ Transaction.record_apdex(event.end, event.exception_encountered?)
88
81
  end
89
82
 
90
83
  def record_instance_busy(event)
@@ -82,7 +82,7 @@ module NewRelic
82
82
  end
83
83
 
84
84
  def active_record_config_for_event(event)
85
- return unless event.payload[:connection_id]
85
+ return unless event.payload[:connection_id] && NewRelic::LanguageSupport.object_space_enabled?
86
86
 
87
87
  # TODO: This will not work for JRuby and in any case we want
88
88
  # this to be part of the event meta data so it doesn't have
@@ -339,7 +339,7 @@ module NewRelic
339
339
 
340
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)
341
341
  NewRelic::Agent::BusyCalculator.dispatcher_finish(end_time)
342
- txn.record_apdex(txn_name, end_time) unless ignore_apdex?
342
+ txn.record_apdex(end_time) unless ignore_apdex?
343
343
  txn = Transaction.stop(txn_name, end_time)
344
344
 
345
345
  NewRelic::Agent::TransactionInfo.get.ignore_end_user = true if ignore_enduser?
@@ -443,7 +443,7 @@ module NewRelic
443
443
  txn = Transaction.start(category, options)
444
444
  txn.name = TransactionNamer.new(self).name(options)
445
445
 
446
- txn.apdex_start ||= _detect_upstream_wait(txn.start_time)
446
+ txn.apdex_start = _detect_upstream_wait(txn.start_time)
447
447
  _record_queue_length
448
448
 
449
449
  return txn
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ DependencyDetection.defer do
6
+ named :excon
7
+
8
+ # We have two ways of instrumenting Excon:
9
+ # - For newer versions, use the middleware mechanism Excon exposes
10
+ # - For older versions, monkey-patch Excon::Connection#request
11
+ #
12
+ # EXCON_MIN_VERSION is the minimum version we attempt to instrument at all.
13
+ # EXCON_MIDDLEWARE_MIN_VERSION is the min version we use the newer
14
+ # instrumentation for.
15
+ #
16
+ # Note that middlewares were added to Excon prior to 0.19, but we don't
17
+ # use middleware-based instrumentation prior to that version because it didn't
18
+ # expose a way for middlewares to know about request failures.
19
+ #
20
+ # Why don't we use Excon.defaults[:instrumentor]?
21
+ # While this might seem a perfect fit, it unfortunately isn't suitable in
22
+ # current form. Someone might reasonably set the default instrumentor to
23
+ # something else after we install our instrumentation. Ideally, excon would
24
+ # itself conform to the #subscribe interface of ActiveSupport::Notifications,
25
+ # so we could safely subscribe and not be clobbered by future subscribers,
26
+ # but alas, it does not yet.
27
+
28
+ EXCON_MIN_VERSION = ::NewRelic::VersionNumber.new("0.10.1")
29
+ EXCON_MIDDLEWARE_MIN_VERSION = ::NewRelic::VersionNumber.new("0.19.0")
30
+
31
+ depends_on do
32
+ defined?(::Excon) && defined?(::Excon::VERSION)
33
+ end
34
+
35
+ executes do
36
+ excon_version = NewRelic::VersionNumber.new(::Excon::VERSION)
37
+ if excon_version >= EXCON_MIN_VERSION
38
+ install_excon_instrumentation(excon_version)
39
+ else
40
+ ::NewRelic::Agent.logger.warn("Excon instrumentation requires at least version #{EXCON_MIN_VERSION}")
41
+ end
42
+ end
43
+
44
+ def install_excon_instrumentation(excon_version)
45
+ require 'new_relic/agent/cross_app_tracing'
46
+ require 'new_relic/agent/http_clients/excon_wrappers'
47
+
48
+ if excon_version >= EXCON_MIDDLEWARE_MIN_VERSION
49
+ install_middleware_excon_instrumentation
50
+ else
51
+ install_legacy_excon_instrumentation
52
+ end
53
+ end
54
+
55
+ def install_middleware_excon_instrumentation
56
+ ::NewRelic::Agent.logger.info 'Installing middleware-based Excon instrumentation'
57
+ require 'new_relic/agent/instrumentation/excon/middleware'
58
+ defaults = Excon.defaults
59
+
60
+ if defaults[:middlewares]
61
+ defaults[:middlewares] << ::Excon::Middleware::NewRelicCrossAppTracing
62
+ else
63
+ ::NewRelic::Agent.logger.warn("Did not find :middlewares key in Excon.defaults, skipping Excon instrumentation")
64
+ end
65
+ end
66
+
67
+ def install_legacy_excon_instrumentation
68
+ ::NewRelic::Agent.logger.info 'Installing legacy Excon instrumentation'
69
+ require 'new_relic/agent/instrumentation/excon/connection'
70
+ ::Excon::Connection.install_newrelic_instrumentation
71
+ end
72
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module ::Excon
6
+ class Connection
7
+ def newrelic_connection_params
8
+ (@connection || @data)
9
+ end
10
+
11
+ def newrelic_resolved_request_params(request_params)
12
+ resolved = newrelic_connection_params.merge(request_params)
13
+ resolved[:headers] = resolved[:headers].merge(request_params[:headers] || {})
14
+ resolved
15
+ end
16
+
17
+ def request_with_newrelic_trace(params, &block)
18
+ orig_response = nil
19
+ resolved_params = newrelic_resolved_request_params(params)
20
+ wrapped_request = ::NewRelic::Agent::HTTPClients::ExconHTTPRequest.new(resolved_params)
21
+ ::NewRelic::Agent::CrossAppTracing.trace_http_request(wrapped_request) do
22
+ orig_response = request_without_newrelic_trace(resolved_params, &block)
23
+ ::NewRelic::Agent::HTTPClients::ExconHTTPResponse.new(orig_response)
24
+ end
25
+ orig_response
26
+ end
27
+
28
+ def self.install_newrelic_instrumentation
29
+ alias request_without_newrelic_trace request
30
+ alias request request_with_newrelic_trace
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ module ::Excon
6
+ module Middleware
7
+ class NewRelicCrossAppTracing
8
+ def initialize(stack)
9
+ @stack = stack
10
+ end
11
+
12
+ def request_call(datum)
13
+ 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]
17
+ rescue => e
18
+ NewRelic::Agent.logger.debug(e)
19
+ end
20
+ @stack.request_call(datum)
21
+ end
22
+
23
+ def response_call(datum)
24
+ finish_trace(datum)
25
+ @stack.response_call(datum)
26
+ end
27
+
28
+ def error_call(datum)
29
+ finish_trace(datum)
30
+ @stack.error_call(datum)
31
+ end
32
+
33
+ def finish_trace(datum)
34
+ trace_data = datum.delete(:newrelic_trace_data)
35
+ if trace_data
36
+ t0, segment, wrapped_request = trace_data
37
+ if datum[:response]
38
+ wrapped_response = ::NewRelic::Agent::HTTPClients::ExconHTTPResponse.new(datum[:response])
39
+ end
40
+ ::NewRelic::Agent::CrossAppTracing.finish_trace(t0, segment, wrapped_request, wrapped_response)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -12,6 +12,7 @@ DependencyDetection.defer do
12
12
  executes do
13
13
  ::NewRelic::Agent.logger.info 'Installing Net instrumentation'
14
14
  require 'new_relic/agent/cross_app_tracing'
15
+ require 'new_relic/agent/http_clients/net_http_wrappers'
15
16
  end
16
17
 
17
18
  executes do
@@ -24,7 +25,8 @@ DependencyDetection.defer do
24
25
  # Don't tracing until the inner call then to avoid double-counting.
25
26
  def request_with_newrelic_trace(request, *args, &block)
26
27
  if started?
27
- NewRelic::Agent::CrossAppTracing.trace_http_request( self, request ) do
28
+ wrapped_request = NewRelic::Agent::HTTPClients::NetHTTPRequest.new(self, request)
29
+ NewRelic::Agent::CrossAppTracing.trace_http_request( wrapped_request ) do
28
30
  request_without_newrelic_trace( request, *args, &block )
29
31
  end
30
32
  else
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ DependencyDetection.defer do
6
+ named :typhoeus
7
+
8
+ depends_on do
9
+ defined?(Typhoeus) && defined?(Typhoeus::VERSION)
10
+ end
11
+
12
+ depends_on do
13
+ NewRelic::Agent::Instrumentation::TyphoeusTracing.is_supported_version?
14
+ end
15
+
16
+ executes do
17
+ ::NewRelic::Agent.logger.info 'Installing Typhoeus instrumentation'
18
+ require 'new_relic/agent/cross_app_tracing'
19
+ require 'new_relic/agent/http_clients/typhoeus_wrappers'
20
+ end
21
+
22
+ # Basic request tracing
23
+ executes do
24
+ Typhoeus.before do |request|
25
+ NewRelic::Agent::Instrumentation::TyphoeusTracing.trace(request)
26
+
27
+ # Ensure that we always return a truthy value from the before block,
28
+ # otherwise Typhoeus will bail out of the instrumentation.
29
+ true
30
+ end
31
+ end
32
+
33
+ # Apply single TT node for Hydra requests until async support
34
+ executes do
35
+ class Typhoeus::Hydra
36
+ include NewRelic::Agent::MethodTracer
37
+
38
+ def run_with_newrelic(*args)
39
+ trace_execution_scoped("External/Multiple/Typhoeus::Hydra/run") do
40
+ run_without_newrelic(*args)
41
+ end
42
+ end
43
+
44
+ alias run_without_newrelic run
45
+ alias run run_with_newrelic
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ module NewRelic::Agent::Instrumentation::TyphoeusTracing
52
+
53
+ EARLIEST_VERSION = NewRelic::VersionNumber.new("0.5.3")
54
+
55
+ def self.is_supported_version?
56
+ NewRelic::VersionNumber.new(Typhoeus::VERSION) >= NewRelic::Agent::Instrumentation::TyphoeusTracing::EARLIEST_VERSION
57
+ end
58
+
59
+ def self.request_is_hydra_enabled?(request)
60
+ request.respond_to?(:hydra) && request.hydra
61
+ end
62
+
63
+ def self.trace(request)
64
+ if NewRelic::Agent.is_execution_traced? && !request_is_hydra_enabled?(request)
65
+ wrapped_request = ::NewRelic::Agent::HTTPClients::TyphoeusHTTPRequest.new(request)
66
+ t0, segment = ::NewRelic::Agent::CrossAppTracing.start_trace(wrapped_request)
67
+ request.on_complete do
68
+ wrapped_response = ::NewRelic::Agent::HTTPClients::TyphoeusHTTPResponse.new(request.response)
69
+ ::NewRelic::Agent::CrossAppTracing.finish_trace(t0, segment, wrapped_request, wrapped_response)
70
+ end if t0
71
+ end
72
+ end
73
+ end
@@ -219,15 +219,12 @@ module NewRelic
219
219
 
220
220
  def record_metrics(first_name, other_names, duration, exclusive, options)
221
221
  metrics = metrics_for_current_transaction(first_name, other_names, options)
222
- stat_engine.record_metrics(metrics) do |stat|
223
- stat.record_data_point(duration, exclusive)
224
- end
222
+ stat_engine.record_metrics_internal(metrics, duration, exclusive)
225
223
 
226
224
  parent_metrics = metrics_for_parent_transaction(first_name, options)
227
225
  parent_metrics.each do |metric|
228
- NewRelic::Agent::Transaction.parent.stats_hash.record(metric) do |stats|
229
- stats.record_data_point(duration, exclusive)
230
- end
226
+ parent_txn = NewRelic::Agent::Transaction.parent
227
+ parent_txn.stats_hash.record(metric, duration, exclusive)
231
228
  end
232
229
  end
233
230
 
@@ -345,7 +345,7 @@ module NewRelic
345
345
  response
346
346
  rescue SystemCallError, SocketError => e
347
347
  # These include Errno connection errors
348
- raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to the server: #{e}"
348
+ raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to #{@collector}: #{e}"
349
349
  end
350
350
 
351
351
 
@@ -13,7 +13,7 @@ module NewRelic
13
13
  end
14
14
 
15
15
  def self.supported_on_this_platform?
16
- defined?(ObjectSpace) && ObjectSpace.respond_to?(:live_objects)
16
+ NewRelic::LanguageSupport.object_space_enabled? && ObjectSpace.respond_to?(:live_objects)
17
17
  end
18
18
 
19
19
  def poll
@@ -117,16 +117,18 @@ module NewRelic
117
117
  alias_method :apdex_t, :total_call_time
118
118
  alias_method :apdex_f, :total_exclusive_time
119
119
 
120
- def record_apdex_s
121
- @call_count += 1
122
- end
123
-
124
- def record_apdex_t
125
- @total_call_time += 1
126
- end
127
-
128
- def record_apdex_f
129
- @total_exclusive_time += 1
120
+ def record_apdex(bucket, apdex_t)
121
+ case bucket
122
+ when :apdex_s then @call_count += 1
123
+ when :apdex_t then @total_call_time += 1
124
+ when :apdex_f then @total_exclusive_time += 1
125
+ end
126
+ if apdex_t
127
+ @min_call_time = apdex_t
128
+ @max_call_time = apdex_t
129
+ else
130
+ ::NewRelic::Agent.logger.warn("Attempted to set apdex_t to #{apdex_t.inspect}, backtrace = #{caller.join("\n")}")
131
+ end
130
132
  end
131
133
 
132
134
  protected
@@ -15,14 +15,13 @@ module NewRelic
15
15
  #
16
16
  # This method is thead-safe, and is preferred to the lookup / modify
17
17
  # method pairs (e.g. get_stats + record_data_point)
18
+ #
19
+ # @api private
18
20
  def record_metrics(metric_names_or_specs, value=nil, options={}, &blk)
19
- defaults = {
20
- :scoped => false,
21
- :scope => in_transaction? ? SCOPE_PLACEHOLDER : nil
22
- }
23
- options = defaults.merge(options)
21
+ scoped = options[:scoped]
22
+ scope = in_transaction? ? SCOPE_PLACEHOLDER : nil
23
+ effective_scope = scoped && scope
24
24
 
25
- effective_scope = options[:scoped] && options[:scope]
26
25
  specs = coerce_to_metric_spec_array(metric_names_or_specs, effective_scope)
27
26
 
28
27
  if in_transaction?
@@ -34,6 +33,25 @@ module NewRelic
34
33
  end
35
34
  end
36
35
 
36
+ # Fast-path version of the #record_metrics version above, used in
37
+ # performance-sensitive code paths
38
+ #
39
+ # metric_specs must be an Array of MetricSpec objects
40
+ # value and aux are passed directly to the corresponding parameters of
41
+ # StatsHash#record
42
+ #
43
+ # @api private
44
+ def record_metrics_internal(metric_specs, value, aux)
45
+ tsh = transaction_stats_hash
46
+ if tsh
47
+ tsh.record(metric_specs, value, aux)
48
+ else
49
+ with_stats_lock do
50
+ @stats_hash.record(metric_specs, value, aux)
51
+ end
52
+ end
53
+ end
54
+
37
55
  # a simple accessor for looking up a stat with no scope -
38
56
  # returns a new stats object if no stats object for that
39
57
  # metric exists yet