Class: NewRelic::Agent::Samplers::VMSampler

Inherits:
NewRelic::Agent::Sampler show all
Defined in:
lib/new_relic/agent/samplers/vm_sampler.rb

Constant Summary collapse

GC_RUNS_METRIC =
'RubyVM/GC/runs'.freeze
HEAP_LIVE_METRIC =
'RubyVM/GC/heap_live'.freeze
HEAP_FREE_METRIC =
'RubyVM/GC/heap_free'.freeze
THREAD_COUNT_METRIC =
'RubyVM/Threads/all'.freeze
OBJECT_ALLOCATIONS_METRIC =
'RubyVM/GC/total_allocated_object'.freeze
MAJOR_GC_METRIC =
'RubyVM/GC/major_gc_count'.freeze
MINOR_GC_METRIC =
'RubyVM/GC/minor_gc_count'.freeze
METHOD_INVALIDATIONS_METRIC =
'RubyVM/CacheInvalidations/method'.freeze
CONSTANT_INVALIDATIONS_METRIC =
'RubyVM/CacheInvalidations/constant'.freeze
CONSTANT_MISSES_METRIC =
'RubyVM/CacheMisses/constant'.freeze

Instance Attribute Summary collapse

Attributes inherited from NewRelic::Agent::Sampler

#id

Instance Method Summary collapse

Methods inherited from NewRelic::Agent::Sampler

enabled?, inherited, named, sampler_classes, supported_on_this_platform?

Constructor Details

#initializeVMSampler

Returns a new instance of VMSampler.



27
28
29
30
31
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 27

def initialize
  @lock = Mutex.new
  @transaction_count = 0
  @last_snapshot = take_snapshot
end

Instance Attribute Details

#transaction_countObject (readonly)

Returns the value of attribute transaction_count.



23
24
25
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 23

def transaction_count
  @transaction_count
end

Instance Method Details

#on_transaction_finished(*_) ⇒ Object



41
42
43
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 41

def on_transaction_finished(*_)
  @lock.synchronize { @transaction_count += 1 }
end

#pollObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 108

def poll
  snap = take_snapshot
  tcount = reset_transaction_count

  record_gc_runs_metric(snap, tcount)
  record_delta(snap, :total_allocated_object, OBJECT_ALLOCATIONS_METRIC, tcount)
  record_delta(snap, :major_gc_count, MAJOR_GC_METRIC, tcount)
  record_delta(snap, :minor_gc_count, MINOR_GC_METRIC, tcount)
  record_delta(snap, :method_cache_invalidations, METHOD_INVALIDATIONS_METRIC, tcount)
  record_delta(snap, :constant_cache_invalidations, CONSTANT_INVALIDATIONS_METRIC, tcount)
  record_delta(snap, :constant_cache_misses, CONSTANT_MISSES_METRIC, tcount)
  record_heap_live_metric(snap)
  record_heap_free_metric(snap)
  record_thread_count_metric(snap)

  @last_snapshot = snap
end

#record_delta(snapshot, key, metric, txn_count) ⇒ Object

THREAD_LOCAL_ACCESS



72
73
74
75
76
77
78
79
80
81
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 72

def record_delta(snapshot, key, metric, txn_count) # THREAD_LOCAL_ACCESS
  value = snapshot.send(key)
  if value
    delta = value - @last_snapshot.send(key)
    NewRelic::Agent.agent.stats_engine.tl_record_unscoped_metrics(metric) do |stats|
      stats.call_count += txn_count
      stats.total_call_time += delta
    end
  end
end

#record_gauge_metric(metric_name, value) ⇒ Object

THREAD_LOCAL_ACCESS



83
84
85
86
87
88
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 83

def record_gauge_metric(metric_name, value) # THREAD_LOCAL_ACCESS
  NewRelic::Agent.agent.stats_engine.tl_record_unscoped_metrics(metric_name) do |stats|
    stats.call_count = value
    stats.sum_of_squares = 1
  end
end

#record_gc_runs_metric(snapshot, txn_count) ⇒ Object

THREAD_LOCAL_ACCESS



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 53

def record_gc_runs_metric(snapshot, txn_count) # THREAD_LOCAL_ACCESS
  if snapshot.gc_total_time || snapshot.gc_runs
    if snapshot.gc_total_time
      gc_time = snapshot.gc_total_time - @last_snapshot.gc_total_time.to_f
    end
    if snapshot.gc_runs
      gc_runs = snapshot.gc_runs - @last_snapshot.gc_runs
    end
    wall_clock_time = snapshot.taken_at - @last_snapshot.taken_at
    NewRelic::Agent.agent.stats_engine.tl_record_unscoped_metrics(GC_RUNS_METRIC) do |stats|
      stats.call_count += txn_count
      stats.total_call_time += gc_runs if gc_runs
      stats.total_exclusive_time += gc_time if gc_time
      stats.max_call_time = (gc_time.nil? ? 0 : 1)
      stats.sum_of_squares += wall_clock_time
    end
  end
end

#record_heap_free_metric(snapshot) ⇒ Object



96
97
98
99
100
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 96

def record_heap_free_metric(snapshot)
  if snapshot.heap_free
    record_gauge_metric(HEAP_FREE_METRIC, snapshot.heap_free)
  end
end

#record_heap_live_metric(snapshot) ⇒ Object



90
91
92
93
94
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 90

def record_heap_live_metric(snapshot)
  if snapshot.heap_live
    record_gauge_metric(HEAP_LIVE_METRIC, snapshot.heap_live)
  end
end

#record_thread_count_metric(snapshot) ⇒ Object



102
103
104
105
106
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 102

def record_thread_count_metric(snapshot)
  if snapshot.thread_count
    record_gauge_metric(THREAD_COUNT_METRIC, snapshot.thread_count)
  end
end

#reset_transaction_countObject



45
46
47
48
49
50
51
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 45

def reset_transaction_count
  @lock.synchronize do
    old_count = @transaction_count
    @transaction_count = 0
    old_count
  end
end

#setup_events(event_listener) ⇒ Object



37
38
39
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 37

def setup_events(event_listener)
  event_listener.subscribe(:transaction_finished, &method(:on_transaction_finished))
end

#take_snapshotObject



33
34
35
# File 'lib/new_relic/agent/samplers/vm_sampler.rb', line 33

def take_snapshot
  NewRelic::Agent::VM.snapshot
end