lib/new_relic/agent/stats.rb in newrelic_rpm-8.6.0 vs lib/new_relic/agent/stats.rb in newrelic_rpm-8.7.0

- old
+ new

@@ -2,18 +2,21 @@ # This file is distributed under New Relic's license terms. # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. module NewRelic module Agent class Stats + SKIP_MARSHALLING = [:@lock] + attr_accessor :call_count attr_accessor :min_call_time attr_accessor :max_call_time attr_accessor :total_call_time attr_accessor :total_exclusive_time attr_accessor :sum_of_squares def initialize + @lock = Mutex.new reset end def reset @call_count = 0 @@ -32,16 +35,18 @@ stats = self.clone stats.merge!(other_stats) end def merge!(other) - @min_call_time = other.min_call_time if min_time_less?(other) - @max_call_time = other.max_call_time if other.max_call_time > max_call_time - @total_call_time += other.total_call_time - @total_exclusive_time += other.total_exclusive_time - @sum_of_squares += other.sum_of_squares - @call_count += other.call_count + @lock.synchronize do + @min_call_time = other.min_call_time if min_time_less?(other) + @max_call_time = other.max_call_time if other.max_call_time > max_call_time + @total_call_time += other.total_call_time + @total_exclusive_time += other.total_exclusive_time + @sum_of_squares += other.sum_of_squares + @call_count += other.call_count + end self end def to_s "[#{'%2i' % call_count.to_i} calls #{'%.4f' % total_call_time.to_f}s / #{'%.4f' % total_exclusive_time.to_f}s ex]" @@ -76,25 +81,27 @@ # record a single data point into the statistical gatherer. The gatherer # will aggregate all data points collected over a specified period and upload # its data to the NewRelic server def record_data_point(value, exclusive_time = value) - @call_count += 1 - @total_call_time += value - @min_call_time = value if value < @min_call_time || @call_count == 1 - @max_call_time = value if value > @max_call_time - @total_exclusive_time += exclusive_time + @lock.synchronize do + @call_count += 1 + @total_call_time += value + @min_call_time = value if value < @min_call_time || @call_count == 1 + @max_call_time = value if value > @max_call_time + @total_exclusive_time += exclusive_time - @sum_of_squares += (value * value) + @sum_of_squares += (value * value) + end self end alias trace_call record_data_point # increments the call_count by one def increment_count(value = 1) - @call_count += value + @lock.synchronize { @call_count += value } end # Concerned about implicit usage of inspect relying on stats format, so # putting back a version to get full inspection as separate method def inspect_full @@ -120,20 +127,38 @@ alias_method :apdex_s, :call_count alias_method :apdex_t, :total_call_time alias_method :apdex_f, :total_exclusive_time def record_apdex(bucket, apdex_t) - case bucket - when :apdex_s then @call_count += 1 - when :apdex_t then @total_call_time += 1 - when :apdex_f then @total_exclusive_time += 1 + @lock.synchronize do + case bucket + when :apdex_s then @call_count += 1 + when :apdex_t then @total_call_time += 1 + when :apdex_f then @total_exclusive_time += 1 + end + if apdex_t + @min_call_time = apdex_t + @max_call_time = apdex_t + else + ::NewRelic::Agent.logger.warn("Attempted to set apdex_t to #{apdex_t.inspect}, backtrace = #{caller.join("\n")}") + end end - if apdex_t - @min_call_time = apdex_t - @max_call_time = apdex_t - else - ::NewRelic::Agent.logger.warn("Attempted to set apdex_t to #{apdex_t.inspect}, backtrace = #{caller.join("\n")}") + end + + # Override marshalling methods to exclude @lock from being included in marshalled data + def marshal_dump + instance_variables.each_with_object({}) do |name, instance_copy| + next if SKIP_MARSHALLING.include?(name) + instance_copy[name] = instance_variable_get(name) end + end + + def marshal_load(marshalled_data) + marshalled_data.each do |name, value| + instance_variable_set(name, value) unless SKIP_MARSHALLING.include?(name) + end + # since the lock is excluded when marshalling, create a new lock when loading marshalled data + @lock = Mutex.new end protected def min_time_less?(other)