diff --git a/lib/puppet/util/profiler.rb b/lib/puppet/util/profiler.rb index 2f895f493..d0d373cc2 100644 --- a/lib/puppet/util/profiler.rb +++ b/lib/puppet/util/profiler.rb @@ -1,52 +1,52 @@ require 'benchmark' # A simple profiling callback system. # # @api public module Puppet::Util::Profiler require 'puppet/util/profiler/wall_clock' require 'puppet/util/profiler/object_counts' - require 'puppet/util/profiler/manager' + require 'puppet/util/profiler/around_profiler' + + @profiler = Puppet::Util::Profiler::AroundProfiler.new - @profiler_manager = Puppet::Util::Profiler::Manager.new - # Reset the profiling system to the original state # # @api private def self.clear - @profiler_manager.clear + @profiler.clear end # Retrieve the current list of profilers # # @api private def self.current - @profiler_manager.current + @profiler.current end # @param profiler [#profile] A profiler for the current thread # @api private def self.add_profiler(profiler) - @profiler_manager.add_profiler(profiler) + @profiler.add_profiler(profiler) end # @param profiler [#profile] A profiler to remove from the current thread # @api private def self.remove_profiler(profiler) - @profiler_manager.remove_profiler(profiler) + @profiler.remove_profiler(profiler) end # Profile a block of code and log the time it took to execute. # # This outputs logs entries to the Puppet masters logging destination # providing the time it took, a message describing the profiled code # and a leaf location marking where the profile method was called # in the profiled hierachy. # # @param message [String] A description of the profiled event # @param block [Block] The segment of code to profile # @api public def self.profile(message, &block) - @profiler_manager.profile(message, &block) + @profiler.profile(message, &block) end end diff --git a/lib/puppet/util/profiler/manager.rb b/lib/puppet/util/profiler/around_profiler.rb similarity index 84% rename from lib/puppet/util/profiler/manager.rb rename to lib/puppet/util/profiler/around_profiler.rb index 50793e0dd..5ee546640 100644 --- a/lib/puppet/util/profiler/manager.rb +++ b/lib/puppet/util/profiler/around_profiler.rb @@ -1,66 +1,66 @@ -require 'puppet/util/profiler' - -# A class used to manage profiler instances +# A Profiler that can be used to wrap around blocks of code. It is configured +# with other profilers and controls them to start before the block is executed +# and finish after the block is executed. # # @api private -class Puppet::Util::Profiler::Manager +class Puppet::Util::Profiler::AroundProfiler def initialize @profilers = [] end # Reset the profiling system to the original state # # @api private def clear @profilers = [] end # Retrieve the current list of profilers # # @api private def current @profilers end # @param profiler [#profile] A profiler for the current thread # @api private def add_profiler(profiler) @profilers << profiler profiler end # @param profiler [#profile] A profiler to remove from the current thread # @api private def remove_profiler(profiler) @profilers.delete(profiler) end # Profile a block of code and log the time it took to execute. # # This outputs logs entries to the Puppet masters logging destination # providing the time it took, a message describing the profiled code # and a leaf location marking where the profile method was called # in the profiled hierachy. # # @param message [String] A description of the profiled event # @param block [Block] The segment of code to profile # @api private def profile(message) retval = nil contexts = {} @profilers.each do |profiler| contexts[profiler] = profiler.start(message) end begin retval = yield ensure @profilers.each do |profiler| profiler.finish(contexts[profiler], message) end end retval end -end \ No newline at end of file +end diff --git a/spec/unit/util/profiler/logging_spec.rb b/spec/unit/util/profiler/logging_spec.rb index 52a407480..08d83cde3 100644 --- a/spec/unit/util/profiler/logging_spec.rb +++ b/spec/unit/util/profiler/logging_spec.rb @@ -1,68 +1,67 @@ require 'spec_helper' require 'puppet/util/profiler' -require 'puppet/util/profiler/manager' describe Puppet::Util::Profiler::Logging do let(:logger) { SimpleLog.new } let(:identifier) { "Profiling ID" } let(:logging_profiler) { TestLoggingProfiler.new(logger, identifier) } let(:profiler) do - p = Puppet::Util::Profiler::Manager.new + p = Puppet::Util::Profiler::AroundProfiler.new p.add_profiler(logging_profiler) p end it "logs the explanation of the profile results" do profiler.profile("Testing") { } logger.messages.first.should =~ /the explanation/ end it "describes the profiled segment" do profiler.profile("Tested measurement") { } logger.messages.first.should =~ /PROFILE \[#{identifier}\] \d Tested measurement/ end it "indicates the order in which segments are profiled" do profiler.profile("Measurement") { } profiler.profile("Another measurement") { } logger.messages[0].should =~ /1 Measurement/ logger.messages[1].should =~ /2 Another measurement/ end it "indicates the nesting of profiled segments" do profiler.profile("Measurement") { profiler.profile("Nested measurement") { } } profiler.profile("Another measurement") { profiler.profile("Another nested measurement") { } } logger.messages[0].should =~ /1.1 Nested measurement/ logger.messages[1].should =~ /1 Measurement/ logger.messages[2].should =~ /2.1 Another nested measurement/ logger.messages[3].should =~ /2 Another measurement/ end class TestLoggingProfiler < Puppet::Util::Profiler::Logging def do_start "the start" end def do_finish(context) "the explanation of #{context}" end end class SimpleLog attr_reader :messages def initialize @messages = [] end def call(msg) @messages << msg end end end diff --git a/spec/unit/util/profiler/manager_spec.rb b/spec/unit/util/profiler/manager_spec.rb index 1d6b8e524..9dbc6a79c 100644 --- a/spec/unit/util/profiler/manager_spec.rb +++ b/spec/unit/util/profiler/manager_spec.rb @@ -1,64 +1,61 @@ require 'spec_helper' -require 'puppet/util/profiler/manager' +require 'puppet/util/profiler' -describe Puppet::Util::Profiler::Manager do - let(:profiler) { TestProfiler.new() } +describe Puppet::Util::Profiler::AroundProfiler do + let(:child) { TestProfiler.new() } + let(:profiler) { Puppet::Util::Profiler::AroundProfiler.new } before :each do - subject.add_profiler(profiler) - end - - after :each do - subject.remove_profiler(profiler) + profiler.add_profiler(child) end it "returns the value of the profiled segment" do - retval = subject.profile("Testing") { "the return value" } + retval = profiler.profile("Testing") { "the return value" } retval.should == "the return value" end it "propogates any errors raised in the profiled segment" do expect do - subject.profile("Testing") { raise "a problem" } + profiler.profile("Testing") { raise "a problem" } end.to raise_error("a problem") end it "makes the description and the context available to the `start` and `finish` methods" do - subject.profile("Testing") { } + profiler.profile("Testing") { } - profiler.context.should == "Testing" - profiler.description.should == "Testing" + child.context.should == "Testing" + child.description.should == "Testing" end it "calls finish even when an error is raised" do begin - subject.profile("Testing") { raise "a problem" } + profiler.profile("Testing") { raise "a problem" } rescue - profiler.context.should == "Testing" + child.context.should == "Testing" end end it "supports multiple profilers" do profiler2 = TestProfiler.new - subject.add_profiler(profiler2) - subject.profile("Testing") {} + profiler.add_profiler(profiler2) + profiler.profile("Testing") {} - profiler.context.should == "Testing" + child.context.should == "Testing" profiler2.context.should == "Testing" end class TestProfiler attr_accessor :context, :description def start(description) description end def finish(context, description) @context = context @description = description end end end