newrelic_rpm 5.3.0.346 → 5.4.0.347

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a104aa20426e4da3129e97dfaa651e7232ef804cf91de87b0aa4ac68d00d3fe7
4
- data.tar.gz: f8ae7ba61e0dc5442212c8d4a8d985d4e9ac353c23e9ff61ebb709ff11bfd28a
3
+ metadata.gz: 979f362569155df00b770dba3907bd0eb894169f70b712085ae19d16852f53a7
4
+ data.tar.gz: b67e7d1c0cb1b5831f06d29c574f8efea5a95405a809b97c55add2e40d0cb101
5
5
  SHA512:
6
- metadata.gz: 58d78970fa151543b165d1ef8b37a9ab7adefabf35ccad2292df5038812a1d5d5524f21cb7822a8d99bc4eabed8ceafc537b6f913b829f2a25ff0cf19a399e3a
7
- data.tar.gz: 6859b4ba6ceaab1faeac5634ea264e015329f20af436872da764e3f17ac6b22f2ad2cbfc4604eccc883d9f7b1a0ef5c1fb193c9faf7fdbfab107bae3a2109b8d
6
+ metadata.gz: 2974f98ab0c47eb9f1c0e2014fb4122138fe4d1bf4d5265f8d09d1583f7ee8fc3f9ab5cb86bf1dc7e31d8b44d5762e56c8e1edd421120151ae85e3e2e4bd854d
7
+ data.tar.gz: 7d16296c46075e1e84824afaeff67db60ea39e0b5b4032bbae9bbcbde8c6c5ca6dc6d40618c92cbf29391f0ba36876937e8d2444313d3805031827a7e8313607
@@ -1,5 +1,29 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v5.4.0
4
+
5
+ * Capacity analysis for multi-threaded dispatchers
6
+
7
+ Metrics around capacity analysis did not previously account for multi-threaded
8
+ dispatchers, and consequently could result in capacities of over 100% being
9
+ recorded. This version now properly accounts for multi-threaded dispatchers.
10
+
11
+ * `NewRelic::Agent.disable_transaction_tracing` deprecated
12
+
13
+ `NewRelic::Agent.disable_transaction_tracing` has been deprecated. Users
14
+ are encouraged to use `NewRelic::Agent.disable_all_tracing` or
15
+ `NewRelic::Agent.ignore_transaction` instead.
16
+
17
+ * Bugfix for SQL over-obfuscation
18
+
19
+ A bug, introduced in v5.3.0, where SQL could be over-obfuscated for some
20
+ database adapters has been fixed.
21
+
22
+ * Bugfix for span event data in Resque processes
23
+
24
+ A bug where span events would not be sent from Resque processes due to a
25
+ missing endpoint has been fixed.
26
+
3
27
  ## v5.3.0 ##
4
28
 
5
29
  * Distributed Tracing
data/config.dot CHANGED
@@ -42,7 +42,7 @@ digraph AgentEnabled {
42
42
  "[dispatcher]"
43
43
  "[force_send]"
44
44
  "[textmate]"
45
- "[post_size_limit]"
45
+ "[max_payload_size_in_bytes]"
46
46
  "[sync_startup]"
47
47
  "[send_data_on_exit]"
48
48
  "[high_security]"
@@ -223,7 +223,7 @@ digraph AgentEnabled {
223
223
  "NewRelicService#initialize" -> "[timeout]"
224
224
  "NewRelicService#initialize" -> "[license_key]"
225
225
  "NewRelicService#initialize" -> "Control#server"
226
- "NewRelicService#check_post_size" -> "[post_size_limit]"
226
+ "NewRelicService#check_post_size" -> "[max_payload_size_in_bytes]"
227
227
  "NewRelicService#connect" -> "Control#server_from_host"
228
228
  "NewRelicService#send_request" -> "Control#http_connection"
229
229
 
@@ -45,7 +45,6 @@ module NewRelic
45
45
  require 'new_relic/agent/sql_sampler'
46
46
  require 'new_relic/agent/commands/thread_profiler_session'
47
47
  require 'new_relic/agent/error_collector'
48
- require 'new_relic/agent/busy_calculator'
49
48
  require 'new_relic/agent/sampler'
50
49
  require 'new_relic/agent/database'
51
50
  require 'new_relic/agent/datastores'
@@ -55,6 +54,7 @@ module NewRelic
55
54
  require 'new_relic/agent/http_clients/uri_util'
56
55
  require 'new_relic/agent/system_info'
57
56
  require 'new_relic/agent/external'
57
+ require 'new_relic/agent/deprecator'
58
58
 
59
59
  require 'new_relic/agent/instrumentation/controller_instrumentation'
60
60
 
@@ -206,11 +206,17 @@ module NewRelic
206
206
  # This method is safe to use from any thread.
207
207
  #
208
208
  # @api public
209
+
210
+ SUPPORTABILITY_INCREMENT_METRIC = 'Supportability/API/increment_metric'.freeze
211
+
209
212
  def increment_metric(metric_name, amount=1) #THREAD_LOCAL_ACCESS
210
213
  return unless agent
211
-
212
- { 'Supportability/API/increment_metric' => 1, metric_name => amount }.each do |metric, increment_amount|
213
- agent.stats_engine.tl_record_unscoped_metrics(metric) {|stats| stats.increment_count(increment_amount) }
214
+ if amount == 1
215
+ metrics = [metric_name, SUPPORTABILITY_INCREMENT_METRIC]
216
+ agent.stats_engine.tl_record_unscoped_metrics(metrics) {|stats| stats.increment_count}
217
+ else
218
+ agent.stats_engine.tl_record_unscoped_metrics(metric_name) {|stats| stats.increment_count(amount)}
219
+ agent.stats_engine.tl_record_unscoped_metrics(SUPPORTABILITY_INCREMENT_METRIC) {|stats| stats.increment_count}
214
220
  end
215
221
  end
216
222
 
@@ -504,16 +510,10 @@ module NewRelic
504
510
  # @api public
505
511
  #
506
512
  def disable_transaction_tracing
513
+ Deprecator.deprecate :disable_transaction_tracing,
514
+ 'disable_all_tracing or ignore_transaction'
507
515
  record_api_supportability_metric(:disable_transaction_tracing)
508
-
509
- return yield unless agent
510
-
511
- state = agent.set_record_tt(false)
512
- begin
513
- yield
514
- ensure
515
- agent.set_record_tt(state)
516
- end
516
+ yield
517
517
  end
518
518
 
519
519
  # This method sets the state of sql recording in the transaction
@@ -547,12 +547,6 @@ module NewRelic
547
547
  NewRelic::Agent::TransactionState.tl_get.is_execution_traced?
548
548
  end
549
549
 
550
- # helper method to check the thread local to determine whether the
551
- # transaction in progress is traced or not
552
- def tl_is_transaction_traced?
553
- NewRelic::Agent::TransactionState.tl_get.is_transaction_traced?
554
- end
555
-
556
550
  # helper method to check the thread local to determine whether sql
557
551
  # is being recorded or not
558
552
  def tl_is_sql_recorded?
@@ -268,16 +268,6 @@ module NewRelic
268
268
  prev.nil? || prev
269
269
  end
270
270
 
271
- # Sets a thread local variable as to whether we should or
272
- # should not record transaction traces in the current
273
- # thread. Returns the previous value, if there is one
274
- def set_record_tt(should_record) #THREAD_LOCAL_ACCESS
275
- state = TransactionState.tl_get
276
- prev = state.record_tt
277
- state.record_tt = should_record
278
- prev.nil? || prev
279
- end
280
-
281
271
  # Push flag indicating whether we should be tracing in this
282
272
  # thread. This uses a stack which allows us to disable tracing
283
273
  # children of a transaction without affecting the tracing of
@@ -934,6 +924,7 @@ module NewRelic
934
924
  when :error_event_data then @error_collector.error_event_aggregator
935
925
  when :analytic_event_data then transaction_event_aggregator
936
926
  when :custom_event_data then @custom_event_aggregator
927
+ when :span_event_data then span_event_aggregator
937
928
  when :sql_trace_data then @sql_sampler
938
929
  end
939
930
  end
@@ -1084,7 +1075,7 @@ module NewRelic
1084
1075
  end
1085
1076
 
1086
1077
  def harvest_and_send_timeslice_data
1087
- NewRelic::Agent::BusyCalculator.harvest_busy
1078
+ NewRelic::Agent::TransactionTimeAggregator.harvest!
1088
1079
  harvest_and_send_from_container(@stats_engine, :metric_data)
1089
1080
  end
1090
1081
 
@@ -504,8 +504,8 @@ module NewRelic
504
504
  :allowed_from_server => false,
505
505
  :description => 'If <code>true</code>, enables the exit handler that sends data to the New Relic <a href="https://docs.newrelic.com/docs/apm/new-relic-apm/getting-started/glossary#collector">collector</a> before shutting down.'
506
506
  },
507
- :post_size_limit => {
508
- :default => 2 * 1024 * 1024, # 2MB
507
+ :max_payload_size_in_bytes => {
508
+ :default => 1000000,
509
509
  :public => false,
510
510
  :type => Integer,
511
511
  :allowed_from_server => true,
@@ -25,6 +25,7 @@ module NewRelic
25
25
  "error_beacon",
26
26
  "js_agent_file",
27
27
  "js_agent_loader",
28
+ "max_payload_size_in_bytes",
28
29
  "primary_application_id",
29
30
  "sampling_target",
30
31
  "sampling_target_period_in_seconds",
@@ -203,7 +203,7 @@ module NewRelic
203
203
  def safe_sql
204
204
  @safe_sql ||= case Database.record_sql_method
205
205
  when :obfuscated
206
- Database.obfuscate_sql(sql)
206
+ Database.obfuscate_sql(self)
207
207
  when :raw
208
208
  sql.to_s
209
209
  else
@@ -65,9 +65,6 @@ module NewRelic
65
65
  if !state.current_transaction
66
66
  ::NewRelic::Agent.logger.debug "Not in transaction. Skipping browser instrumentation."
67
67
  false
68
- elsif !state.is_transaction_traced?
69
- ::NewRelic::Agent.logger.debug "Transaction is not traced. Skipping browser instrumentation."
70
- false
71
68
  elsif !state.is_execution_traced?
72
69
  ::NewRelic::Agent.logger.debug "Execution is not traced. Skipping browser instrumentation."
73
70
  false
@@ -193,7 +193,7 @@ module NewRelic
193
193
  # We do not compress if content is smaller than 64kb. There are
194
194
  # problems with bugs in Ruby in some versions that expose us
195
195
  # to a risk of segfaults if we compress aggressively.
196
- def compress_request_if_needed(data)
196
+ def compress_request_if_needed(data, endpoint)
197
197
  encoding = 'identity'
198
198
  if data.size > 64 * 1024
199
199
  encoding = Agent.config[:compressed_content_encoding]
@@ -203,7 +203,7 @@ module NewRelic
203
203
  Encoders::Compressed::Deflate.encode(data)
204
204
  end
205
205
  end
206
- check_post_size(data)
206
+ check_post_size(data, endpoint)
207
207
  [data, encoding]
208
208
  end
209
209
 
@@ -412,7 +412,7 @@ module NewRelic
412
412
  end
413
413
  serialize_finish_ts = Time.now
414
414
 
415
- data, encoding = compress_request_if_needed(data)
415
+ data, encoding = compress_request_if_needed(data, method)
416
416
  size = data.size
417
417
 
418
418
  uri = remote_method_uri(method)
@@ -471,9 +471,10 @@ module NewRelic
471
471
 
472
472
  # Raises an UnrecoverableServerException if the post_string is longer
473
473
  # than the limit configured in the control object
474
- def check_post_size(post_string)
475
- return if post_string.size < Agent.config[:post_size_limit]
474
+ def check_post_size(post_string, endpoint)
475
+ return if post_string.size < Agent.config[:max_payload_size_in_bytes]
476
476
  ::NewRelic::Agent.logger.debug "Tried to send too much data: #{post_string.size} bytes"
477
+ NewRelic::Agent.increment_metric("Supportability/Agent/Collector/#{endpoint}/MaxPayloadSizeLimit")
477
478
  raise UnrecoverableServerException.new('413 Request Entity Too Large')
478
479
  end
479
480
 
@@ -53,6 +53,10 @@ module NewRelic
53
53
  write_to_pipe(:error_event_data, events) if events
54
54
  end
55
55
 
56
+ def span_event_data(events)
57
+ write_to_pipe(:span_event_data, events) if events
58
+ end
59
+
56
60
  def sql_trace_data(sql)
57
61
  write_to_pipe(:sql_trace_data, sql) if sql
58
62
  end
@@ -186,7 +186,7 @@ module NewRelic
186
186
  # For use by test code only.
187
187
  def clear_stats
188
188
  reset!
189
- NewRelic::Agent::BusyCalculator.reset
189
+ NewRelic::Agent::TransactionTimeAggregator.reset!
190
190
  end
191
191
 
192
192
  # For use by test code only.
@@ -11,6 +11,7 @@ require 'new_relic/agent/transaction/request_attributes'
11
11
  require 'new_relic/agent/transaction/tracing'
12
12
  require 'new_relic/agent/transaction/distributed_tracing'
13
13
  require 'new_relic/agent/cross_app_tracing'
14
+ require 'new_relic/agent/transaction_time_aggregator'
14
15
 
15
16
  module NewRelic
16
17
  module Agent
@@ -446,7 +447,7 @@ module NewRelic
446
447
 
447
448
  sql_sampler.on_start_transaction(state, start_time, request_path)
448
449
  NewRelic::Agent.instance.events.notify(:start_transaction)
449
- NewRelic::Agent::BusyCalculator.dispatcher_start(start_time)
450
+ NewRelic::Agent::TransactionTimeAggregator.transaction_start(start_time)
450
451
 
451
452
  ignore! if user_defined_rules_ignore?
452
453
 
@@ -542,7 +543,7 @@ module NewRelic
542
543
 
543
544
  outermost_frame.finish
544
545
 
545
- NewRelic::Agent::BusyCalculator.dispatcher_finish(end_time)
546
+ NewRelic::Agent::TransactionTimeAggregator.transaction_stop(end_time)
546
547
 
547
548
  commit!(state, end_time, outermost_frame.name) unless @ignore_this_transaction
548
549
  end
@@ -34,13 +34,12 @@ module NewRelic
34
34
  def initialize
35
35
  @untraced = []
36
36
  @current_transaction = nil
37
- @record_tt = nil
38
37
  @record_sql = nil
39
38
  end
40
39
 
41
40
  # This starts the timer for the transaction.
42
41
  def reset(transaction=nil)
43
- # We purposefully don't reset @untraced, @record_tt and @record_sql
42
+ # We purposefully don't reset @untraced or @record_sql
44
43
  # since those are managed by NewRelic::Agent.disable_* calls explicitly
45
44
  # and (more importantly) outside the scope of a transaction
46
45
 
@@ -125,11 +124,7 @@ module NewRelic
125
124
  end
126
125
 
127
126
  # TT's and SQL
128
- attr_accessor :record_tt, :record_sql
129
-
130
- def is_transaction_traced?
131
- @record_tt != false
132
- end
127
+ attr_accessor :record_sql
133
128
 
134
129
  def is_sql_recorded?
135
130
  @record_sql != false
@@ -0,0 +1,131 @@
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
+ require 'objspace'
6
+
7
+ # This module powers the Busy calculation for the Capacity report in
8
+ # APM (https://rpm.newrelic.com/accounts/.../applications/.../optimize/capacity_analysis).
9
+ #
10
+ # total time spent in transactions this harvest across all threads
11
+ # Busy time = ------------------------------------------------------------------------
12
+ # (elapsed time for this harvest cycle) * (# threads that had transactions)
13
+ #
14
+ module NewRelic
15
+ module Agent
16
+ module TransactionTimeAggregator
17
+ TransactionStats = Struct.new :transaction_started_at, :elapsed_transaction_time
18
+
19
+ @lock = Mutex.new
20
+ @harvest_cycle_started_at = Time.now
21
+
22
+ @stats = Hash.new do |h, k|
23
+ h[k] = TransactionStats.new nil, 0.0
24
+ end
25
+
26
+ def reset!(now = Time.now)
27
+ @harvest_cycle_started_at = now
28
+ @stats.clear
29
+ end
30
+
31
+ def transaction_start(now = Time.now)
32
+ @lock.synchronize do
33
+ set_transaction_start_time now
34
+ end
35
+ end
36
+
37
+ def transaction_stop(now = Time.now)
38
+ @lock.synchronize do
39
+ record_elapsed_transaction_time_until now
40
+ set_transaction_start_time nil
41
+ end
42
+ end
43
+
44
+ INSTANCE_BUSY_METRIC = 'Instance/Busy'.freeze
45
+
46
+ def harvest!(now = Time.now)
47
+ active_threads = 0
48
+ result = @lock.synchronize do
49
+ # Sum up the transaction times spent in each thread
50
+ elapsed_transaction_time = @stats.inject(0.0) do |total, (thread_id, entry)|
51
+ total + transaction_time_in_thread(thread_id, entry, now)
52
+ end
53
+
54
+ active_threads = @stats.size
55
+ elapsed_harvest_time = (now - @harvest_cycle_started_at) * active_threads
56
+ @harvest_cycle_started_at = now
57
+
58
+ # Clear out the stats for all threads, _except_ the live ones
59
+ # that have transactions still open (we'll count the rest of
60
+ # those in a future harvest)
61
+ @stats.keep_if do |thread_id, _|
62
+ in_transaction?(thread_id) && thread_is_alive?(thread_id)
63
+ end
64
+
65
+ if elapsed_harvest_time > 0.0
66
+ elapsed_transaction_time / elapsed_harvest_time
67
+ else
68
+ 0.0
69
+ end
70
+ end
71
+
72
+ if Agent.config[:report_instance_busy]
73
+ NewRelic::Agent.record_metric(INSTANCE_BUSY_METRIC, result)
74
+ end
75
+
76
+ result
77
+ end
78
+
79
+ module_function :reset!,
80
+ :transaction_start,
81
+ :transaction_stop,
82
+ :harvest!
83
+
84
+ class <<self
85
+ private
86
+
87
+ def record_elapsed_transaction_time_until(timestamp, thread_id: current_thread)
88
+ @stats[thread_id].elapsed_transaction_time +=
89
+ (timestamp - (@stats[thread_id].transaction_started_at || 0.0))
90
+ end
91
+
92
+ def in_transaction?(thread_id = current_thread)
93
+ !!@stats[thread_id].transaction_started_at
94
+ end
95
+
96
+ def current_thread
97
+ Thread.current.object_id
98
+ end
99
+
100
+ def thread_is_alive?(thread_id)
101
+ thread = ObjectSpace._id2ref(thread_id)
102
+ thread && thread.alive?
103
+ rescue StandardError
104
+ false
105
+ end
106
+
107
+ def set_transaction_start_time(timestamp)
108
+ @stats[current_thread].transaction_started_at = timestamp
109
+ end
110
+
111
+ def split_transaction_at_harvest(now, thread_id: nil)
112
+ raise ArgumentError, 'thread_id required' unless thread_id
113
+ @stats[thread_id].transaction_started_at = now
114
+ @stats[thread_id].elapsed_transaction_time = 0.0
115
+ end
116
+
117
+ def transaction_time_in_thread thread_id, entry, now
118
+ return entry.elapsed_transaction_time unless in_transaction? thread_id
119
+
120
+ # Count the portion of the transaction that's elapsed so far,...
121
+ elapsed = record_elapsed_transaction_time_until now, thread_id: thread_id
122
+
123
+ # ...then readjust the transaction start time to the next harvest
124
+ split_transaction_at_harvest now, thread_id: thread_id
125
+
126
+ elapsed
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -11,7 +11,7 @@ module NewRelic
11
11
  end
12
12
 
13
13
  MAJOR = 5
14
- MINOR = 3
14
+ MINOR = 4
15
15
  TINY = 0
16
16
 
17
17
  begin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.0.346
4
+ version: 5.4.0.347
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Wear
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-07-26 00:00:00.000000000 Z
14
+ date: 2018-09-04 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rake
@@ -202,7 +202,6 @@ files:
202
202
  - lib/new_relic/agent/attribute_processing.rb
203
203
  - lib/new_relic/agent/audit_logger.rb
204
204
  - lib/new_relic/agent/autostart.rb
205
- - lib/new_relic/agent/busy_calculator.rb
206
205
  - lib/new_relic/agent/chained_call.rb
207
206
  - lib/new_relic/agent/commands/agent_command.rb
208
207
  - lib/new_relic/agent/commands/agent_command_router.rb
@@ -393,6 +392,7 @@ files:
393
392
  - lib/new_relic/agent/transaction_metrics.rb
394
393
  - lib/new_relic/agent/transaction_sampler.rb
395
394
  - lib/new_relic/agent/transaction_state.rb
395
+ - lib/new_relic/agent/transaction_time_aggregator.rb
396
396
  - lib/new_relic/agent/transaction_timings.rb
397
397
  - lib/new_relic/agent/utilization/aws.rb
398
398
  - lib/new_relic/agent/utilization/azure.rb
@@ -1,117 +0,0 @@
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
- require 'new_relic/agent/transaction_state'
6
-
7
- module NewRelic
8
- module Agent
9
- # This module supports calculation of actual time spent processing requests over the course of
10
- # one harvest period. It's similar to what you would get if you just added up all the
11
- # execution times of controller calls, however that will be inaccurate when requests
12
- # span the minute boundaries. This module manages accounting of requests not yet
13
- # completed.
14
- #
15
- # Calls are re-entrant. All start calls must be paired with finish
16
- # calls, or a reset call.
17
- module BusyCalculator
18
-
19
- extend self
20
-
21
- # For testability, add accessors:
22
- attr_reader :harvest_start, :accumulator
23
-
24
- # sets up busy calculations based on the start and end of
25
- # transactions - used for a rough estimate of what percentage of
26
- # wall clock time is spent processing requests
27
- def dispatcher_start(time) #THREAD_LOCAL_ACCESS
28
- state = TransactionState.tl_get
29
- state.busy_entries ||= 0
30
- callers = state.busy_entries += 1
31
- return if callers > 1
32
- @lock.synchronize do
33
- @entrypoint_stack.push time
34
- end
35
- end
36
-
37
- # called when a transaction finishes, to add time to the
38
- # instance variable accumulator. this is harvested when we send
39
- # data to the server
40
- def dispatcher_finish(end_time = nil) #THREAD_LOCAL_ACCESS
41
- state = TransactionState.tl_get
42
- # If #dispatcher_start hasn't been called at least once, abort early
43
- return unless state.busy_entries
44
-
45
- end_time ||= time_now
46
- callers = state.busy_entries -= 1
47
-
48
- # Ignore nested calls
49
- return if callers > 0
50
-
51
- @lock.synchronize do
52
- if @entrypoint_stack.empty?
53
- ::NewRelic::Agent.logger.warn("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
54
- else
55
- @accumulator += (end_time - @entrypoint_stack.pop).to_f
56
- end
57
- end
58
- end
59
-
60
- # this returns the size of the entry point stack, which
61
- # determines how many transactions are running
62
- def busy_count
63
- @entrypoint_stack.size
64
- end
65
-
66
- # Reset the state of the information accumulated by all threads,
67
- # but only reset the recursion counter for this thread.
68
- def reset #THREAD_LOCAL_ACCESS
69
- @entrypoint_stack = []
70
- TransactionState.tl_get.busy_entries = 0
71
- @lock ||= Mutex.new
72
- @accumulator = 0
73
- @harvest_start = time_now
74
- end
75
-
76
-
77
- # Called before uploading to to the server to collect current busy stats.
78
- def harvest_busy
79
- busy = 0
80
- t0 = time_now
81
- @lock.synchronize do
82
- busy = accumulator
83
- @accumulator = 0
84
-
85
- # Walk through the stack and capture all times up to
86
- # now for entrypoints
87
- @entrypoint_stack.size.times do |frame|
88
- busy += (t0 - @entrypoint_stack[frame]).to_f
89
- @entrypoint_stack[frame] = t0
90
- end
91
-
92
- end
93
-
94
- busy = 0.0 if busy < 0.0 # don't go below 0%
95
-
96
- time_window = (t0 - harvest_start).to_f
97
- time_window = 1.0 if time_window == 0.0 # protect against divide by zero
98
-
99
- busy = busy / time_window
100
-
101
- if Agent.config[:report_instance_busy]
102
- NewRelic::Agent.record_metric('Instance/Busy', busy)
103
- end
104
- @harvest_start = t0
105
- end
106
-
107
- private
108
-
109
- # so we can stub Time.now only for the BusyCalculator in tests
110
- def time_now
111
- Time.now
112
- end
113
-
114
- self.reset
115
- end
116
- end
117
- end