diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 0000000..8ebbe30 --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_DISABLE_SHARED_GEMS: "1" diff --git a/lib/ruby-metrics.rb b/lib/ruby-metrics.rb index f008e5b..a4a3397 100644 --- a/lib/ruby-metrics.rb +++ b/lib/ruby-metrics.rb @@ -20,3 +20,4 @@ def logger require File.join(File.dirname(__FILE__), 'ruby-metrics', 'agent') +require File.join(File.dirname(__FILE__), 'ruby-metrics', 'console_reporter') diff --git a/lib/ruby-metrics/console_reporter.rb b/lib/ruby-metrics/console_reporter.rb new file mode 100644 index 0000000..3570682 --- /dev/null +++ b/lib/ruby-metrics/console_reporter.rb @@ -0,0 +1,103 @@ +require File.join(File.dirname(__FILE__), 'logging') +require File.join(File.dirname(__FILE__), 'instruments') +require File.join(File.dirname(__FILE__), 'time_units') + +module Metrics + class ConsoleReporter + include Logging + include Instruments::TypeMethods + + attr_reader :instruments + + def initialize(out = STDOUT) + logger.debug "Initializing Reporter..." + @instruments = Metrics::Instruments + @out = out + end + + def start(period = 10) + start_reporter_daemon_thread(period) + end + + protected + def start_reporter_daemon_thread(period) + logger.debug "Creating Metrics console reporter daemon thread." + @reporter_daemon_thread = Thread.new do + begin + loop do + start_time = Time.now + start_time_str = start_time.strftime("%m/%d/%Y %X ") + @out.print start_time_str + (80-start_time_str.length-1).times { @out.print('=') } + @out.puts + + print_instruments + + @out.puts + @out.flush + sleep(period) + end + rescue Exception => e + logger.error "Error in worker thread: #{e.class.name}: #{e}\n #{e.backtrace.join("\n ")}" + end # begin + end # thread new + end + + def print_instruments + @instruments.registered.each do |name, metric| + @out.puts "Name: #{name}, Type: #{metric.class.to_s.gsub(/.+::/, "")}" + if metric.is_a? Instruments::Gauge + print_gauge(metric) + elsif metric.is_a? Instruments::Counter + print_counter(metric) + elsif metric.is_a? Instruments::Histogram + print_histogram(metric) + elsif metric.is_a? Instruments::Meter + print_metered(metric) + elsif metric.is_a? Instruments::Timer + print_timer(metric) + end + end + end + + def print_gauge(gauge) + @out.puts(" value = #{gauge.get}") + end + + def print_counter(counter) + @out.puts(" count = #{counter}") + end + + def print_metered(meter) + @out.puts(" count = #{meter.count}") + @out.puts(" mean rate = #{meter.mean_rate}") + @out.puts(" 1-minute rate = #{meter.one_minute_rate}") + @out.puts(" 5-minute rate = #{meter.five_minute_rate}") + @out.puts(" 15-minute rate = #{meter.fifteen_minute_rate}") + end + + def print_histogram(histogram) + percentiles = histogram.quantiles([0.5, 0.75, 0.95, 0.98, 0.99, 0.999]) + @out.puts(" min = #{histogram.min}") + @out.puts(" max = #{histogram.max}") + @out.puts(" mean = #{histogram.mean}") + @out.puts(" stddev = #{histogram.std_dev}") + percentiles.each do |name, percentile| + @out.puts(" #{name} <= #{percentile}") + end + end + + def print_timer(timer) + print_metered(timer); + percentiles = timer.quantiles([0.5, 0.75, 0.95, 0.98, 0.99, 0.999]); + @out.puts(" min = #{timer.min}") + @out.puts(" max = #{timer.max}") + @out.puts(" mean = #{timer.mean}") + @out.puts(" stddev = #{timer.std_dev}") + percentiles.each do |name, percentile| + @out.puts(" #{name} <= #{percentile}") + end + end + + end +end \ No newline at end of file diff --git a/lib/ruby-metrics/instruments/meter.rb b/lib/ruby-metrics/instruments/meter.rb index 896557e..90d6550 100644 --- a/lib/ruby-metrics/instruments/meter.rb +++ b/lib/ruby-metrics/instruments/meter.rb @@ -74,7 +74,7 @@ def fifteen_minute_rate(rate_unit = :seconds) convert_to_ns @fifteen_minute_rate, rate_unit end - def mean_rate(rate_unit = seconds) + def mean_rate(rate_unit = :seconds) count = @count if count == 0 return 0.0; diff --git a/spec/console_reporter_spec.rb b/spec/console_reporter_spec.rb new file mode 100644 index 0000000..0b0194b --- /dev/null +++ b/spec/console_reporter_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper.rb' + +describe Metrics::ConsoleReporter do + before :each do + out = File.new('/dev/null', 'w') + @reporter = Metrics::ConsoleReporter.new(out) + end + + it "should call the get method for gauge" do + gauge = Metrics::Instruments::Gauge.new do + "test" + end + Metrics::Instruments::Gauge.stub!(:new).and_return gauge + gauge.should_receive(:get) + @reporter.gauge :test_gauge do + "test" + end + @reporter.instance_eval { print_instruments } + end + + it "should call the to_s method for counter" do + counter = Metrics::Instruments::Counter.new + Metrics::Instruments::Counter.stub!(:new).and_return counter + counter.should_receive(:to_s) + @reporter.counter(:test_counter) + @reporter.instance_eval { print_instruments } + end + + it "should call the count, mean_rate, one_minute_rate, five_minute_rate, fifteen_minute_rate methods for meter" do + Thread.stub!(:new).and_return nil + meter = Metrics::Instruments::Meter.new + Metrics::Instruments::Meter.stub!(:new).and_return meter + meter.should_receive(:count) + meter.should_receive(:mean_rate) + meter.should_receive(:one_minute_rate) + meter.should_receive(:five_minute_rate) + meter.should_receive(:fifteen_minute_rate) + @reporter.meter(:test_meter) + @reporter.instance_eval { print_instruments } + end + + it "should call the min, max, mean, std_dev, quantiles methods for histogram" do + uniform_histogram = Metrics::Instruments::UniformHistogram.new + Metrics::Instruments::UniformHistogram.stub!(:new).and_return uniform_histogram + uniform_histogram.stub!(:quantiles).and_return [] + uniform_histogram.should_receive(:quantiles) + uniform_histogram.should_receive(:min) + uniform_histogram.should_receive(:max) + uniform_histogram.should_receive(:mean) + uniform_histogram.should_receive(:std_dev) + @reporter.uniform_histogram(:test_histogram) + @reporter.instance_eval { print_instruments } + end +end \ No newline at end of file