Skip to content

Commit

Permalink
More porting work.
Browse files Browse the repository at this point in the history
  • Loading branch information
dougbarth committed Aug 4, 2008
1 parent c665fd2 commit 4053c8b
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 21 deletions.
5 changes: 5 additions & 0 deletions lib/erma/event_monitor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Erma::EventMonitor < Erma::Monitor
def initialize(name)
super(name)
end
end
38 changes: 38 additions & 0 deletions lib/erma/monitor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ def initialize(name)
self.attributes['name'] = AttributeHolder.new(name, false, false)
end

# Returns the value for the attribute with the given key.
def [](key)
attributes[key].value
end
Expand All @@ -12,6 +13,25 @@ def attributes
@attributes ||= {}
end

# True if the attribute for the given key is set on this Monitor.
def has_attribute?(key)
!! attributes[key]
end

# True if the attribute for the given key is locked.
def locked?(key)
attributes[key].locked?
end

# True if the attribute for the given key is marked as serializable.
def serializable?(key)
attributes[key].serializable?
end

def set(key, value)
self.attributes[key] = AttributeHolder.new(value, false, false)
end

# Holds a Monitor attribute value and associated metadata.
class AttributeHolder
attr_reader :value
Expand All @@ -20,6 +40,24 @@ def initialize(value, serializable, locked)
@serializable = serializable
@locked = locked
end

def serializable
@serializable = true
self
end

def serializable?
@serializable
end

def lock
@locked = true
self
end

def locked?
@locked
end
end
end
end
48 changes: 45 additions & 3 deletions lib/erma/monitoring_engine.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'singleton'
require 'monitor.rb'
require 'monitor'

module Erma
# The engine that controls basic correlation of monitors as they are collected
Expand Down Expand Up @@ -46,6 +46,16 @@ def shutdown
end
end

# Shuts down the MonitoringEngine if it is running. After it is shutdown,
# the MonitoringEngine will be started up.
#
# *This method is not thread-safe.* Clients should take care to ensure
# that multithreaded access to this method is synchronized.
def restart
shutdown if running?
startup
end

# A lifecycle method that initializes the Monitor. All monitor
# implementations must call this methods before setting any attributes on
# themselves.
Expand All @@ -54,8 +64,11 @@ def shutdown
# inherited and global attributes applied.
def init_monitor(monitor)
return unless processing?

monitor.set(:created_at, Time.now).serializable.lock
monitor.set(:thread_id, Thread.current.__id__).serializable.lock

inherit_attributes(monitor)
end

# A lifecycle method that notifies observing MonitorProcessors that a new
Expand Down Expand Up @@ -94,7 +107,12 @@ def composite_monitor_started(monitor)
# before they call process().
def composite_monitor_completed(monitor)
return unless processing?
handle_monitor(monitor, :composite_monitor_completed)

return unless monitor_stack.include?(monitor)

while (missed_mon = monitor_stack.pop) != monitor
process(missed_mon)
end
end

# A lifecycle method that notifies observing MonitorProcessors that a
Expand All @@ -105,7 +123,16 @@ def process(monitor)
handle_monitor(monitor, :process)
end


# Obtains the first CompositeMonitor found on the per thread stack that has
# its name attribute equal to the supplied name. This method should be used
# in situations where stateless code is unable to hold a reference to
# the CompositeMonitor that was originally created. Supplying the name
# value is needed to ensure that instrumentation errors in code called by
# users of this method does not interfere with the ability to correctly
# obtain the original CompositeMonitor.
def get_composite_monitor_named(name)
raise 'Must supply a non-nil name' if name.nil?
monitor_stack.reverse.find {|m| m['name'] == name}
end

Expand All @@ -114,7 +141,16 @@ def global_attributes
end

def inheritable_attributes
@global_attributes
inheritable_attributes = {}
global_attributes.each do |key, value|
inheritable_attributes[key] = Erma::Monitor::AttributeHolder.new(value, false, false)
end

monitor_stack.each do |ancestor|
inheritable_attributes.merge!(ancestor.inheritable_attribute_holders)
end

inheritable_attributes
end

attr_writer :enabled
Expand Down Expand Up @@ -147,6 +183,12 @@ def handle_monitor(monitor, callback_method)
end
end

def inherit_attributes(monitor)
global_attributes.each do |key, value|
monitor.set(key, value)
end
end

def initialize
self.enabled = true
end
Expand Down
1 change: 1 addition & 0 deletions lib/ermarb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ module Erma; end

require 'erma/monitoring_engine'
require 'erma/monitor'
require 'erma/event_monitor'
100 changes: 82 additions & 18 deletions spec/monitoring_engine_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
@engine = Erma::MonitoringEngine.instance
@engine.enabled = true
@engine.processor_factory = stub('MockProcessorFactory', :null_object => true)
@engine.startup
@engine.restart
end

after { @engine.shutdown }

it "should be enabled after startup" do
@engine.startup
@engine.should be_enabled
Expand Down Expand Up @@ -65,6 +63,24 @@
@engine.should_not be_running
end

describe "restart" do
it "should call shutdown" do
@engine.should_receive(:shutdown)
@engine.restart
end

it "should not call shutdown if not running" do
@engine.shutdown
@engine.should_receive(:shutdown).never
@engine.restart
end

it "should call startup" do
@engine.should_receive(:startup)
@engine.restart
end
end

# TODO Java version should have this concept instead of confusing isEnabled() method
describe "processing?" do
it "should be true if enabled and running" do
Expand Down Expand Up @@ -148,29 +164,32 @@

describe "processing init_monitor callback" do
before do
@monitor = stub_everything('mock_monitor')
@monitor = Erma::EventMonitor.new('test')
end

it "should set the created_at attribute on the monitor as serializable and locked" do
attr_holder = mock('attr_holder')
@monitor.should_receive(:set).with(:created_at, anything).and_return(attr_holder)
@monitor.should_receive(:set).with(:thread_id, anything).and_return(stub_everything)
attr_holder.should_receive(:serializable).and_return(attr_holder)
attr_holder.should_receive(:lock)
@engine.init_monitor(@monitor)
@monitor.should have_attribute(:created_at)
@monitor.should be_locked(:created_at)
@monitor.should be_serializable(:created_at)
end

it "should set the thread ID attribute on the monitor and serializable and locked" do
attr_holder = mock('attr_holder')
@monitor.should_receive(:set).with(:created_at, anything).and_return(stub_everything)
@monitor.should_receive(:set).with(:thread_id, Thread.current.__id__).and_return(attr_holder)
attr_holder.should_receive(:serializable).and_return(attr_holder)
attr_holder.should_receive(:lock)
@engine.init_monitor(@monitor)
@monitor.should have_attribute(:thread_id)
@monitor.should be_locked(:thread_id)
@monitor.should be_serializable(:thread_id)
@monitor[:thread_id].should == Thread.current.__id__
end

it "should set inherited attributes on monitor"

it "should inherit global attributes" do
@engine.global_attributes['foo'] = 10
@engine.init_monitor(@monitor)
@monitor['foo'].should == 10
end

it "should do nothing if not enabled" do
@engine.enabled = false
@engine.init_monitor(mock('mock_monitor'))
Expand Down Expand Up @@ -212,23 +231,69 @@
end

describe "processing composite_monitor_completed callback" do
it "should pop the monitor from the stack" do
@monitor = Erma::Monitor.new('foo')
@engine.composite_monitor_started(@monitor)
@engine.composite_monitor_completed(@monitor)
@engine.get_composite_monitor_named('foo').should == nil
end

it "should pop only the monitor provided" do
@parent = Erma::Monitor.new('parent')
@child = Erma::Monitor.new('child')
@engine.composite_monitor_started(@parent)
@engine.composite_monitor_started(@child)
@engine.composite_monitor_completed(@child)
@engine.get_composite_monitor_named('child').should == nil
@engine.get_composite_monitor_named('parent').should == @parent
end

it "should ignore double calls" do
@parent = Erma::Monitor.new('parent')
@child = Erma::Monitor.new('child')
@engine.composite_monitor_started(@parent)
@engine.composite_monitor_started(@child)
@engine.composite_monitor_completed(@child)
@engine.composite_monitor_completed(@child)
@engine.get_composite_monitor_named('child').should == nil
@engine.get_composite_monitor_named('parent').should == @parent
end

it "should process missed monitors" do
@parent = Erma::Monitor.new('parent')
@child = Erma::Monitor.new('child')
@engine.should_receive(:process).with(@child)
@engine.composite_monitor_started(@parent)
@engine.composite_monitor_started(@child)
@engine.composite_monitor_completed(@parent)
end
end

describe "get_composite_monitor_named" do
it "should raise a RuntimeError when passed nil" do
lambda { @engine.get_composite_monitor_named(nil) }.should raise_error
end
end

describe "global_attributes" do
before do
@engine.global_attributes.clear
end

it "should be included in the inheritable_attributes call" do
@engine.global_attributes['foo'] = 12
@engine.inheritable_attributes['foo'].should == 12
@engine.inheritable_attributes['foo'].value.should == 12
end

it "should be able to be overridden" do
@engine.global_attributes['foo'] = 12
@engine.global_attributes['foo'] = 13
@engine.inheritable_attributes['foo'].should == 13
@engine.inheritable_attributes['foo'].value.should == 13
end

it "should be global across threads" do
@engine.global_attributes['foo'] = 12
thread = Thread.new { @engine.inheritable_attributes['foo'].should == 12 }
thread = Thread.new { @engine.inheritable_attributes['foo'].value.should == 12 }
thread.join
end
end
Expand All @@ -244,7 +309,6 @@
end

it "should include inheritable attributes on parent Monitors" do
pending
@engine.inheritable_attributes.should == @attr_holders
end
end
Expand Down

0 comments on commit 4053c8b

Please sign in to comment.