Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RUBY-1259 Wrappers for snapshotting VM values
In order to deal sanely across the various versions and implementations of Ruby we support, this adds a layer that allows us to safely take snapshots of the VM stats that we care about. NewRelic::Agent::VM::Snapshot will have nil's for values that aren't supported and represents the state of the VM at a given instant in time. It will be the responsibility of the sampler to properly compare to prior snapshots and calculate metrics based off these values.
- Loading branch information
1 parent
d5d7f69
commit dcaa09d
Showing
8 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/language_support' | ||
require 'new_relic/agent/vm/mri_vm' | ||
require 'new_relic/agent/vm/jruby_vm' | ||
require 'new_relic/agent/vm/rubinius_vm' | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
def self.snapshot | ||
vm.snapshot | ||
end | ||
|
||
def self.vm | ||
@vm ||= create_vm | ||
end | ||
|
||
def self.create_vm | ||
if NewRelic::LanguageSupport.using_engine?('jruby') | ||
JRubyVM.new | ||
elsif NewRelic::LanguageSupport.using_engine?('rbx') | ||
RubiniusVM.new | ||
else | ||
MriVM.new | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/agent/vm/vm_base' | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
class JRubyVM < VMBase | ||
def gather_stats(snap) | ||
# TODO: Which can we gather here? | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/agent/vm/vm_base' | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
class MriVM < VMBase | ||
def gather_stats(snap) | ||
gather_gc_stats(snap) | ||
gather_ruby_vm_stats(snap) | ||
gather_thread_stats(snap) | ||
end | ||
|
||
def gather_gc_stats(snap) | ||
if supports?(:gc_runs) | ||
gc_stats = GC.stat | ||
snap.gc_runs = gc_stats[:count] | ||
snap.total_allocated_object = gc_stats[:total_allocated_object] | ||
snap.major_gc_count = gc_stats[:major_gc_count] | ||
snap.minor_gc_count = gc_stats[:minor_gc_count] | ||
snap.heap_live = gc_stats[:heap_live_slot] || gc_stats[:heap_live_num] | ||
snap.heap_free = gc_stats[:heap_free_slot] || gc_stats[:heap_free_num] | ||
end | ||
end | ||
|
||
def gather_ruby_vm_stats(snap) | ||
if supports?(:method_cache_invalidations) | ||
vm_stats = RubyVM.stat | ||
snap.method_cache_invalidations = vm_stats[:global_method_state] | ||
snap.constant_cache_invalidations = vm_stats[:global_constant_state] | ||
end | ||
end | ||
|
||
def gather_thread_stats(snap) | ||
snap.thread_count = Thread.list.size | ||
end | ||
|
||
def supports?(key) | ||
case key | ||
when :gc_runs | ||
RUBY_VERSION >= '1.9.2' | ||
when :total_allocated_object | ||
RUBY_VERSION >= '2.0.0' | ||
when :major_gc_count | ||
RUBY_VERSION >= '2.1.0' | ||
when :minor_gc_count | ||
RUBY_VERSION >= '2.1.0' | ||
when :heap_live | ||
RUBY_VERSION >= '1.9.2' | ||
when :heap_free | ||
RUBY_VERSION >= '1.9.2' | ||
when :method_cache_invalidations | ||
RUBY_VERSION >= '2.1.0' | ||
when :constant_cache_invalidations | ||
RUBY_VERSION >= '2.1.0' | ||
when :thread_count | ||
true | ||
else | ||
false | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/agent/vm/vm_base' | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
class RubiniusVM < VMBase | ||
def gather_stats(snap) | ||
# TODO: Which can we gather here? | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
class Snapshot | ||
attr_accessor :gc_runs, :major_gc_count, :minor_gc_count, | ||
:total_allocated_object, :heap_live, :heap_free, | ||
:method_cache_invalidations, :constant_cache_invalidations, | ||
:thread_count | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/agent/vm/snapshot' | ||
|
||
module NewRelic | ||
module Agent | ||
module VM | ||
class VMBase | ||
def snapshot | ||
snap = Snapshot.new | ||
gather_stats(snap) | ||
snap | ||
end | ||
|
||
def gather_stats(snap) | ||
raise NotImplementedError("VM subclasses expected to implement gather_stats") | ||
end | ||
|
||
def supports?(key) | ||
false | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require 'new_relic/agent/vm/snapshot' | ||
|
||
class NewRelic::Agent::VM::SnapshotTestCase < MiniTest::Unit::TestCase | ||
def test_fail | ||
#assert false | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# encoding: utf-8 | ||
# This file is distributed under New Relic's license terms. | ||
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details. | ||
|
||
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper')) | ||
require 'new_relic/agent/vm' | ||
|
||
class NewRelic::Agent::VMTestCase < MiniTest::Unit::TestCase | ||
attr_reader :vm, :snapshot | ||
|
||
def setup | ||
@vm = NewRelic::Agent::VM.vm | ||
@snapshot = NewRelic::Agent::VM.snapshot | ||
end | ||
|
||
def test_gets_snapshot | ||
refute_nil snapshot | ||
end | ||
|
||
EXPECTED_SNAPSHOT_VALUES = [ | ||
:gc_runs, | ||
:total_allocated_object, | ||
:major_gc_count, | ||
:minor_gc_count, | ||
:heap_live, | ||
:heap_free, | ||
:method_cache_invalidations, | ||
:constant_cache_invalidations, | ||
:thread_count | ||
] | ||
|
||
EXPECTED_SNAPSHOT_VALUES.each do |val| | ||
define_method("test_snapshot_has_#{val}") do | ||
assert_correct_value_for(val) | ||
end | ||
end | ||
|
||
# A VM snapshot will either support a value and have something non-nil, | ||
# or it will not support it in which case the method exists but must be nil! | ||
def assert_correct_value_for(meth) | ||
if vm.supports?(meth) | ||
refute_nil snapshot.send(meth) | ||
else | ||
assert_nil snapshot.send(meth) | ||
end | ||
end | ||
end | ||
|