Class: NewRelic::Agent::StatsEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/new_relic/agent/stats_engine.rb,
lib/new_relic/agent/stats_engine/gc_profiler.rb

Overview

This class handles all the statistics gathering for the agent

Defined Under Namespace

Modules: GCProfiler

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeStatsEngine

Returns a new instance of StatsEngine.



16
17
18
19
20
# File 'lib/new_relic/agent/stats_engine.rb', line 16

def initialize
  @stats_lock = Mutex.new
  @stats_hash = StatsHash.new
  @metric_rules = RulesEngine.new
end

Instance Attribute Details

#metric_rulesObject



14
15
16
# File 'lib/new_relic/agent/stats_engine.rb', line 14

def metric_rules
  @metric_rules
end

Instance Method Details

#apply_rules_to_metric_data(rules_engine, stats_hash) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
# File 'lib/new_relic/agent/stats_engine.rb', line 161

def apply_rules_to_metric_data(rules_engine, stats_hash)
  renamed_stats = NewRelic::Agent::StatsHash.new(stats_hash.started_at)
  stats_hash.each do |spec, stats|
    new_name = rules_engine.rename(spec.name)
    unless new_name.nil?
      new_spec = NewRelic::MetricSpec.new(new_name, spec.scope)
      renamed_stats[new_spec].merge!(stats)
    end
  end
  renamed_stats
end

#clear_statsObject

For use by test code only.



188
189
190
191
# File 'lib/new_relic/agent/stats_engine.rb', line 188

def clear_stats
  reset!
  NewRelic::Agent::TransactionTimeAggregator.reset!
end

#coerce_to_metric_spec_array(metric_names_or_specs, scope) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/new_relic/agent/stats_engine.rb', line 173

def coerce_to_metric_spec_array(metric_names_or_specs, scope)
  specs = []
  Array(metric_names_or_specs).map do |name_or_spec|
    case name_or_spec
    when String
      specs << NewRelic::MetricSpec.new(name_or_spec)
      specs << NewRelic::MetricSpec.new(name_or_spec, scope) if scope
    when NewRelic::MetricSpec
      specs << name_or_spec
    end
  end
  specs
end

#harvest!Object



153
154
155
156
157
158
159
# File 'lib/new_relic/agent/stats_engine.rb', line 153

def harvest!
  now = Process.clock_gettime(Process::CLOCK_REALTIME)
  snapshot = reset!
  snapshot = apply_rules_to_metric_data(@metric_rules, snapshot)
  snapshot.harvested_at = now
  snapshot
end

#merge!(other_stats_hash) ⇒ Object

merge data from previous harvests into this stats engine



140
141
142
143
144
145
# File 'lib/new_relic/agent/stats_engine.rb', line 140

def merge!(other_stats_hash)
  with_stats_lock do
    @stats_hash.merge!(other_stats_hash)
    @stats_hash
  end
end

#merge_transaction_metrics!(txn_metrics, scope) ⇒ Object



147
148
149
150
151
# File 'lib/new_relic/agent/stats_engine.rb', line 147

def merge_transaction_metrics!(txn_metrics, scope)
  with_stats_lock do
    @stats_hash.merge_transaction_metrics!(txn_metrics, scope)
  end
end

#record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics = nil, value = nil, aux = nil, &blk) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/new_relic/agent/stats_engine.rb', line 105

def record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics = nil, value = nil, aux = nil, &blk)
  txn = state.current_transaction
  if txn
    txn.metrics.record_scoped_and_unscoped(scoped_metric, value, aux, &blk)
    if summary_metrics
      txn.metrics.record_unscoped(summary_metrics, value, aux, &blk)
    end
  else
    specs = coerce_to_metric_spec_array(scoped_metric, nil)
    if summary_metrics
      specs.concat(coerce_to_metric_spec_array(summary_metrics, nil))
    end
    with_stats_lock do
      @stats_hash.record(specs, value, aux, &blk)
    end
  end
end

#record_unscoped_metrics(state, metric_names, value = nil, aux = nil, &blk) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/new_relic/agent/stats_engine.rb', line 69

def record_unscoped_metrics(state, metric_names, value = nil, aux = nil, &blk)
  txn = state.current_transaction
  if txn
    txn.metrics.record_unscoped(metric_names, value, aux, &blk)
  else
    specs = coerce_to_metric_spec_array(metric_names, nil)
    with_stats_lock do
      @stats_hash.record(specs, value, aux, &blk)
    end
  end
end

#reset!Object



131
132
133
134
135
136
137
# File 'lib/new_relic/agent/stats_engine.rb', line 131

def reset!
  with_stats_lock do
    old = @stats_hash
    @stats_hash = StatsHash.new
    old
  end
end

#tl_record_scoped_and_unscoped_metrics(scoped_metric, summary_metrics = nil, value = nil, aux = nil, &blk) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Like tl_record_unscoped_metrics, but records a scoped metric as well.

This is an internal method, subject to change at any time. Client apps and gems should use the public API (NewRelic::Agent.record_metric) instead.

The given scoped_metric will be recoded as both a scoped and an unscoped metric. The summary_metrics will be recorded as unscoped metrics only.

If called during a transaction, all metrics will be attached to the Transaction, and not merged into the global set of metrics until the end of the transaction.

If called outside of a transaction, only the unscoped metrics will be recorded, directly into the global set of metrics (under a lock).



100
101
102
103
# File 'lib/new_relic/agent/stats_engine.rb', line 100

def tl_record_scoped_and_unscoped_metrics(scoped_metric, summary_metrics = nil, value = nil, aux = nil, &blk)
  state = NewRelic::Agent::Tracer.state
  record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics, value, aux, &blk)
end

#tl_record_supportability_metric_count(metric, value) ⇒ Object

Helper for recording a straight value into the count



124
125
126
127
128
129
# File 'lib/new_relic/agent/stats_engine.rb', line 124

def tl_record_supportability_metric_count(metric, value)
  real_name = "Supportability/#{metric}"
  tl_record_unscoped_metrics(real_name) do |stat|
    stat.call_count = value
  end
end

#tl_record_unscoped_metrics(metric_names, value = nil, aux = nil, &blk) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Update the unscoped metrics given in metric_names. metric_names may be either a single name, or an array of names.

This is an internal method, subject to change at any time. Client apps and gems should use the public API (NewRelic::Agent.record_metric) instead.

There are four ways to use this method:

  1. With a numeric value, it will update the Stats objects associated with the given metrics by calling record_data_point(value, aux). aux will be treated in this case as the exclusive time associated with the call being recorded.

  2. With a value of :apdex_s, :apdex_t, or :apdex_f, it will treat the associated stats as an Apdex metric, updating it to reflect the occurrence of a transaction falling into the given category. The aux value in this case should be the apdex threshold used in bucketing the request.

  3. If a block is given, value and aux will be ignored, and instead the Stats object associated with each named unscoped metric will be yielded to the block for customized update logic.

  4. If value is a Stats instance, it will be merged into the Stats associated with each named unscoped metric.

If this method is called during a transaction, the metrics will be attached to the Transaction, and not merged into the global set until the end of the transaction.

Otherwise, the metrics will be recorded directly into the global set of metrics, under a lock.



64
65
66
67
# File 'lib/new_relic/agent/stats_engine.rb', line 64

def tl_record_unscoped_metrics(metric_names, value = nil, aux = nil, &blk)
  state = NewRelic::Agent::Tracer.state
  record_unscoped_metrics(state, metric_names, value, aux, &blk)
end

#to_hObject

For use by test code only.



194
195
196
# File 'lib/new_relic/agent/stats_engine.rb', line 194

def to_h
  with_stats_lock { @stats_hash.to_h }
end

#with_stats_lockObject

All access to the @stats_hash ivar should be funnelled through this method to ensure thread-safety.



24
25
26
# File 'lib/new_relic/agent/stats_engine.rb', line 24

def with_stats_lock
  @stats_lock.synchronize { yield }
end