Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jeff Kunkle
committed
Aug 13, 2011
1 parent
524d92d
commit 8858f65
Showing
5 changed files
with
110 additions
and
2 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
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,57 @@ | ||
require 'thread' | ||
|
||
module SystemMetrics | ||
class AsyncStore | ||
|
||
# An instrumenter that does not send notifications. This is used in the | ||
# AsyncStore so saving events does not send any notifications, not even | ||
# for logging. | ||
class VoidInstrumenter < ::ActiveSupport::Notifications::Instrumenter | ||
def instrument(name, payload={}) | ||
yield(payload) if block_given? | ||
end | ||
end | ||
|
||
def initialize | ||
@queue = Queue.new | ||
@thread = Thread.new do | ||
set_void_instrumenter | ||
consume | ||
end | ||
end | ||
|
||
def save(events) | ||
@queue << events | ||
end | ||
|
||
protected | ||
def set_void_instrumenter | ||
Thread.current[:"instrumentation_#{notifier.object_id}"] = VoidInstrumenter.new(notifier) | ||
end | ||
|
||
def notifier | ||
ActiveSupport::Notifications.notifier | ||
end | ||
|
||
def consume | ||
while events = @queue.pop | ||
root_event = SystemMetrics::NestedEvent.arrange(events, :presort => false) | ||
root_model = create_metric(root_event) | ||
root_model.update_attributes(:request_id => root_model.id) | ||
save_tree(root_event.children, root_model.id, root_model.id) | ||
end | ||
end | ||
|
||
def save_tree(events, request_id, parent_id) | ||
events.each do |event| | ||
model = create_metric(event, :request_id => request_id, :parent_id => parent_id) | ||
save_tree(event.children, request_id, model.id) | ||
end | ||
end | ||
|
||
def create_metric(event, merge_params={}) | ||
SystemMetrics::Metric.create(event.to_hash.merge(merge_params)) | ||
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
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,50 @@ | ||
require File.dirname(__FILE__) + '/../spec_helper' | ||
require 'system_metrics/metric' | ||
|
||
describe SystemMetrics::AsyncStore do | ||
include NotificationsSupport | ||
|
||
describe '#save' do | ||
it 'should save an array of events hierarchically' do | ||
parent = event(:start => Time.now - 10.seconds, :end => Time.now) | ||
child = event(:start => Time.now - 9.seconds, :end => Time.now - 1.seconds) | ||
grandchild = event(:start => Time.now - 8.seconds, :end => Time.now - 2.seconds) | ||
|
||
store = SystemMetrics::AsyncStore.new | ||
|
||
lambda { | ||
store.save([grandchild, child, parent]) | ||
sleep(0.1) | ||
}.should change(SystemMetrics::Metric, :count).by(3) | ||
|
||
metrics = SystemMetrics::Metric.all | ||
verify_equal(parent, metrics[0]) | ||
verify_equal(child, metrics[0].children[0]) | ||
verify_equal(grandchild, metrics[0].children[0].children[0]) | ||
end | ||
|
||
it 'should not attempt to save anything if passed an empty array of events' do | ||
store = SystemMetrics::AsyncStore.new | ||
lambda { store.save([]); sleep(0.1) }.should_not change(SystemMetrics::Metric, :count) | ||
end | ||
|
||
it 'should not attempt to save anything if passed a nil' do | ||
store = SystemMetrics::AsyncStore.new | ||
lambda { store.save(nil); sleep(0.1) }.should_not change(SystemMetrics::Metric, :count) | ||
end | ||
end | ||
|
||
private | ||
|
||
def verify_equal(event, metric) | ||
event.name.should == metric.name | ||
event.action.should == metric.action | ||
event.category.should == metric.category | ||
event.transaction_id.should == metric.transaction_id | ||
event.payload.should == metric.payload | ||
event.started_at.should be_within(1).of(metric.started_at) | ||
event.duration.should be_within(1).of(metric.duration) | ||
event.exclusive_duration.should be_within(1).of(metric.exclusive_duration) | ||
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