From 6a036bbabd051438463ae4cec8ff77c6bfc7260a Mon Sep 17 00:00:00 2001 From: Brian Morton Date: Wed, 26 Jun 2013 22:27:39 -0700 Subject: [PATCH 1/4] Extract duplicated arrays of reportable metrics out of reporters * Add reportable_metrics class method to all metric types * Add reportable_snapshot_metrics class method to all metric types * Allow desired percentiles to be passed in for snapshot metrics --- lib/metriks/counter.rb | 18 ++++++++++++++++++ lib/metriks/gauge.rb | 18 ++++++++++++++++++ lib/metriks/histogram.rb | 19 +++++++++++++++++++ lib/metriks/meter.rb | 21 +++++++++++++++++++++ lib/metriks/timer.rb | 22 ++++++++++++++++++++++ lib/metriks/utilization_timer.rb | 24 ++++++++++++++++++++++++ test/counter_test.rb | 8 ++++++++ test/gauge_test.rb | 8 ++++++++ test/histogram_test.rb | 8 ++++++++ test/meter_test.rb | 8 ++++++++ test/timer_test.rb | 8 ++++++++ test/utilization_timer_test.rb | 8 ++++++++ 12 files changed, 170 insertions(+) diff --git a/lib/metriks/counter.rb b/lib/metriks/counter.rb index 93b9662..1c5bc6f 100644 --- a/lib/metriks/counter.rb +++ b/lib/metriks/counter.rb @@ -40,5 +40,23 @@ def decrement(decr = 1) def count @count.value end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_metrics + [:count] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options - No supported options. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_snapshot_metrics(options = {}) + [] + end end end \ No newline at end of file diff --git a/lib/metriks/gauge.rb b/lib/metriks/gauge.rb index 19c222b..4c2c1e2 100644 --- a/lib/metriks/gauge.rb +++ b/lib/metriks/gauge.rb @@ -23,5 +23,23 @@ def set(val) def value @callback ? @callback.call : @gauge.value end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols. + def self.reportable_metrics + [:value] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options - No supported options. + # + # Returns an array of symbols. + def self.reportable_snapshot_metrics(options = {}) + [] + end end end diff --git a/lib/metriks/histogram.rb b/lib/metriks/histogram.rb index 7237c50..6f47793 100644 --- a/lib/metriks/histogram.rb +++ b/lib/metriks/histogram.rb @@ -108,5 +108,24 @@ def update_variance(value) new_values end end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_metrics + [:count, :min, :max, :mean, :stddev] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options[:percentiles] - An array of percentiles methods to include. These + # must be valid methods on Metriks::Snapshot. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_snapshot_metrics(options = {}) + [:median] + options.fetch(:percentiles, []) + end end end diff --git a/lib/metriks/meter.rb b/lib/metriks/meter.rb index 3e4d64d..5275fda 100644 --- a/lib/metriks/meter.rb +++ b/lib/metriks/meter.rb @@ -81,5 +81,26 @@ def mean_rate def stop end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_metrics + [ + :count, :one_minute_rate, :five_minute_rate, :fifteen_minute_rate, + :mean_rate + ] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options - No supported options. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_snapshot_metrics(options = {}) + [] + end end end \ No newline at end of file diff --git a/lib/metriks/timer.rb b/lib/metriks/timer.rb index cf1181f..fa02be7 100644 --- a/lib/metriks/timer.rb +++ b/lib/metriks/timer.rb @@ -97,5 +97,27 @@ def stddev def stop @meter.stop end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_metrics + [ + :count, :one_minute_rate, :five_minute_rate, :fifteen_minute_rate, + :mean_rate, :min, :max, :mean, :stddev + ] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options[:percentiles] - An array of percentiles methods to include. These + # must be valid methods on Metriks::Snapshot. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_snapshot_metrics(options = {}) + [:median] + options.fetch(:percentiles, []) + end end end \ No newline at end of file diff --git a/lib/metriks/utilization_timer.rb b/lib/metriks/utilization_timer.rb index 171c45c..0754e97 100644 --- a/lib/metriks/utilization_timer.rb +++ b/lib/metriks/utilization_timer.rb @@ -39,5 +39,29 @@ def stop super @duration_meter.stop end + + # Public: An array of methods to be used for reporting metrics through a + # reporter. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_metrics + [ + :count, :one_minute_rate, :five_minute_rate, :fifteen_minute_rate, + :mean_rate, :min, :max, :mean, :stddev, :one_minute_utilization, + :five_minute_utilization, :fifteen_minute_utilization, + :mean_utilization + ] + end + + # Public: An array of methods to be used for reporting snapshot metrics + # through a reporter. + # + # options[:percentiles] - An array of percentiles methods to include. These + # must be valid methods on Metriks::Snapshot. + # + # Returns an array of symbols of methods that can be called. + def self.reportable_snapshot_metrics(options = {}) + [:median] + options.fetch(:percentiles, []) + end end end \ No newline at end of file diff --git a/test/counter_test.rb b/test/counter_test.rb index 8540a43..6a11283 100644 --- a/test/counter_test.rb +++ b/test/counter_test.rb @@ -36,4 +36,12 @@ def test_increment_by_more_threaded assert_equal 10000, @counter.count end + + def test_has_no_reportable_snapshot_metrics + assert_equal [], Metriks::Counter.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::Counter.reportable_metrics + end end diff --git a/test/gauge_test.rb b/test/gauge_test.rb index 66a22c6..afef1da 100644 --- a/test/gauge_test.rb +++ b/test/gauge_test.rb @@ -43,4 +43,12 @@ def call assert_equal 123, gauge.value end + + def test_has_no_reportable_snapshot_metrics + assert_equal [], Metriks::Gauge.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::Gauge.reportable_metrics + end end diff --git a/test/histogram_test.rb b/test/histogram_test.rb index 41642ba..7bcae34 100644 --- a/test/histogram_test.rb +++ b/test/histogram_test.rb @@ -196,4 +196,12 @@ def test_long_idle_sample assert_equal 5, @histogram.min end + + def test_has_reportable_snapshot_metrics + assert_not_empty Metriks::Histogram.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::Histogram.reportable_metrics + end end diff --git a/test/meter_test.rb b/test/meter_test.rb index 8d4e0c0..4c4ce34 100644 --- a/test/meter_test.rb +++ b/test/meter_test.rb @@ -35,4 +35,12 @@ def test_one_minute_rate assert_equal 200, @meter.one_minute_rate end + + def test_has_no_reportable_snapshot_metrics + assert_equal [], Metriks::Meter.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::Meter.reportable_metrics + end end diff --git a/test/timer_test.rb b/test/timer_test.rb index 87eb0d4..b04e755 100644 --- a/test/timer_test.rb +++ b/test/timer_test.rb @@ -29,4 +29,12 @@ def test_timer_without_block assert_in_delta 0.1, @timer.mean, 0.01 end + + def test_has_reportable_snapshot_metrics + assert_not_empty Metriks::Timer.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::Timer.reportable_metrics + end end \ No newline at end of file diff --git a/test/utilization_timer_test.rb b/test/utilization_timer_test.rb index 11961ee..27addab 100644 --- a/test/utilization_timer_test.rb +++ b/test/utilization_timer_test.rb @@ -22,4 +22,12 @@ def test_timer assert_in_delta 0.25, @timer.one_minute_utilization, 0.1 end + + def test_has_reportable_snapshot_metrics + assert_not_empty Metriks::UtilizationTimer.reportable_snapshot_metrics + end + + def test_has_reportable_metrics + assert_not_empty Metriks::UtilizationTimer.reportable_metrics + end end \ No newline at end of file From 6c43b97e680a51fb732858b4e8751791ebb5a02c Mon Sep 17 00:00:00 2001 From: Brian Morton Date: Wed, 26 Jun 2013 22:35:32 -0700 Subject: [PATCH 2/4] Add methods for turning an array of percentiles into valid Snapshot methods. * Add VALID_PERCENTILES constant to Snapshot class * Reference VALID_PERCENTILES to create a convenience method for checking validity * Add method for taking a list of percentiles and turning them into valid methods to be called on Snapshot objects --- lib/metriks/snapshot.rb | 25 +++++++++++++++++++++++++ test/snapshot_test.rb | 14 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/snapshot_test.rb diff --git a/lib/metriks/snapshot.rb b/lib/metriks/snapshot.rb index 7885c5f..70d9002 100644 --- a/lib/metriks/snapshot.rb +++ b/lib/metriks/snapshot.rb @@ -1,5 +1,7 @@ module Metriks class Snapshot + VALID_PERCENTILES = [:p75, :p95, :p98, :p99, :p999] + MEDIAN_Q = 0.5 P75_Q = 0.75 P95_Q = 0.95 @@ -55,5 +57,28 @@ def get_99th_percentile def get_999th_percentile value(P999_Q) end + + def self.valid_percentile?(percentile) + VALID_PERCENTILES.include?(percentile) + end + + # Public: Convert symbol percentiles into an array of methods to be called + # on a Snapshot object. + # + # percentiles - A symbol, or list of symbols, that represents the percentile + # that a method is needed for. + # + # Example: + # Metriks::Snapshot.methods_for_percentiles(:p95, :p99) + # # => [:get_95th_percentile, :get_99th_percentile] + # + # Returns an array of symbols + def self.methods_for_percentiles(*percentiles) + methods = percentiles.flatten.collect do |percentile| + next unless valid_percentile?(percentile) + :"get_#{percentile.to_s.gsub('p', '')}th_percentile" + end + methods.compact + end end end diff --git a/test/snapshot_test.rb b/test/snapshot_test.rb new file mode 100644 index 0000000..bf1ab03 --- /dev/null +++ b/test/snapshot_test.rb @@ -0,0 +1,14 @@ +require 'test_helper' +require 'metriks/snapshot' + +class MetriksSnapshotTest < Test::Unit::TestCase + def test_skips_invalid_percentiles + methods = Metriks::Snapshot.methods_for_percentiles(:p999, :invalid_percentile) + assert_equal [:get_999th_percentile], methods + end + + def test_multiple_percentiles + methods = Metriks::Snapshot.methods_for_percentiles(:p999, :p95) + assert_equal [:get_999th_percentile, :get_95th_percentile], methods + end +end From 35d96f5d8be50cd1e5511d9f26047dd249e9d629 Mon Sep 17 00:00:00 2001 From: Brian Morton Date: Wed, 26 Jun 2013 22:35:58 -0700 Subject: [PATCH 3/4] Add support for passing an array of percentiles to use for reporting. * Update reporters to use the reportable_metrics and reportable_snapshot_metrics class methods --- lib/metriks/reporter/graphite.rb | 51 ++++--------------------- lib/metriks/reporter/librato_metrics.rb | 44 ++------------------- lib/metriks/reporter/logger.rb | 44 ++++++--------------- lib/metriks/reporter/riemann.rb | 47 +++++++---------------- test/graphite_reporter_test.rb | 37 ++++++++++++++++++ test/librato_metrics_reporter_test.rb | 37 ++++++++++++++++++ test/logger_reporter_test.rb | 34 +++++++++++++++++ test/riemann_reporter_test.rb | 37 ++++++++++++++++++ 8 files changed, 182 insertions(+), 149 deletions(-) diff --git a/lib/metriks/reporter/graphite.rb b/lib/metriks/reporter/graphite.rb index cc2a347..089782d 100644 --- a/lib/metriks/reporter/graphite.rb +++ b/lib/metriks/reporter/graphite.rb @@ -2,7 +2,7 @@ module Metriks::Reporter class Graphite - attr_reader :host, :port + attr_reader :host, :port, :percentile_methods def initialize(host, port, options = {}) @host = host @@ -10,9 +10,11 @@ def initialize(host, port, options = {}) @prefix = options[:prefix] - @registry = options[:registry] || Metriks::Registry.default - @interval = options[:interval] || 60 - @on_error = options[:on_error] || proc { |ex| } + @registry = options[:registry] || Metriks::Registry.default + @interval = options[:interval] || 60 + @on_error = options[:on_error] || proc { |ex| } + + @percentile_methods = Metriks::Snapshot.methods_for_percentiles(options[:percentiles] || :p95) end def socket @@ -48,45 +50,8 @@ def restart def write @registry.each do |name, metric| - case metric - when Metriks::Meter - write_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate - ] - when Metriks::Counter - write_metric name, metric, [ - :count - ] - when Metriks::Gauge - write_metric name, metric, [ - :value - ] - when Metriks::UtilizationTimer - write_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev, - :one_minute_utilization, :five_minute_utilization, - :fifteen_minute_utilization, :mean_utilization, - ], [ - :median, :get_95th_percentile - ] - when Metriks::Timer - write_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] - when Metriks::Histogram - write_metric name, metric, [ - :count, :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] - end + write_metric name, metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) end end diff --git a/lib/metriks/reporter/librato_metrics.rb b/lib/metriks/reporter/librato_metrics.rb index 528970f..47fe945 100644 --- a/lib/metriks/reporter/librato_metrics.rb +++ b/lib/metriks/reporter/librato_metrics.rb @@ -3,7 +3,7 @@ module Metriks::Reporter class LibratoMetrics - attr_accessor :prefix, :source + attr_accessor :prefix, :source, :percentile_methods def initialize(email, token, options = {}) @email = email @@ -11,6 +11,7 @@ def initialize(email, token, options = {}) @prefix = options[:prefix] @source = options[:source] + @percentile_methods = Metriks::Snapshot.methods_for_percentiles(options[:percentiles] || :p95) @registry = options[:registry] || Metriks::Registry.default @time_tracker = Metriks::TimeTracker.new(options[:interval] || 60) @@ -46,45 +47,8 @@ def restart def write gauges = [] @registry.each do |name, metric| - gauges << case metric - when Metriks::Meter - prepare_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate - ] - when Metriks::Counter - prepare_metric name, metric, [ - :count - ] - when Metriks::Gauge - prepare_metric name, metric, [ - :value - ] - when Metriks::UtilizationTimer - prepare_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev, - :one_minute_utilization, :five_minute_utilization, - :fifteen_minute_utilization, :mean_utilization, - ], [ - :median, :get_95th_percentile - ] - when Metriks::Timer - prepare_metric name, metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] - when Metriks::Histogram - prepare_metric name, metric, [ - :count, :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] - end + gauges << prepare_metric(name, metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods)) end gauges.flatten! diff --git a/lib/metriks/reporter/logger.rb b/lib/metriks/reporter/logger.rb index 5904f9b..4ad3b7b 100644 --- a/lib/metriks/reporter/logger.rb +++ b/lib/metriks/reporter/logger.rb @@ -3,7 +3,7 @@ module Metriks::Reporter class Logger - attr_accessor :prefix, :log_level, :logger + attr_accessor :prefix, :log_level, :logger, :percentile_methods def initialize(options = {}) @logger = options[:logger] || ::Logger.new(STDOUT) @@ -13,6 +13,8 @@ def initialize(options = {}) @registry = options[:registry] || Metriks::Registry.default @time_tracker = Metriks::TimeTracker.new(options[:interval] || 60) @on_error = options[:on_error] || proc { |ex| } + + @percentile_methods = Metriks::Snapshot.methods_for_percentiles(options.fetch(:percentiles, :p95)) end def start @@ -51,42 +53,20 @@ def write @registry.each do |name, metric| case metric when Metriks::Meter - log_metric name, 'meter', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate - ] + log_metric name, 'meter', metric, metric.class.reportable_metrics when Metriks::Counter - log_metric name, 'counter', metric, [ - :count - ] + log_metric name, 'counter', metric, metric.class.reportable_metrics when Metriks::Gauge - log_metric name, 'gauge', metric, [ - :value - ] + log_metric name, 'gauge', metric, metric.class.reportable_metrics when Metriks::UtilizationTimer - log_metric name, 'utilization_timer', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev, - :one_minute_utilization, :five_minute_utilization, - :fifteen_minute_utilization, :mean_utilization, - ], [ - :median, :get_95th_percentile - ] + log_metric name, 'utilization_timer', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) when Metriks::Timer - log_metric name, 'timer', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] + log_metric name, 'timer', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) when Metriks::Histogram - log_metric name, 'histogram', metric, [ - :count, :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] + log_metric name, 'histogram', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) end end end diff --git a/lib/metriks/reporter/riemann.rb b/lib/metriks/reporter/riemann.rb index bdab081..e487ccf 100644 --- a/lib/metriks/reporter/riemann.rb +++ b/lib/metriks/reporter/riemann.rb @@ -2,7 +2,7 @@ module Metriks::Reporter class Riemann require 'riemann/client' - attr_accessor :client + attr_accessor :client, :percentile_methods def initialize(options = {}) @client = ::Riemann::Client.new( :host => options[:host], @@ -14,6 +14,7 @@ def initialize(options = {}) @default_event = options[:default_event] || {} @default_event[:ttl] ||= @interval * 1.5 + @percentile_methods = Metriks::Snapshot.methods_for_percentiles(options[:percentiles] || :p95) end def start @@ -55,49 +56,27 @@ def write @registry.each do |name, metric| case metric when Metriks::Meter - send_metric name, 'meter', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate - ] + send_metric name, 'meter', metric, metric.class.reportable_metrics when Metriks::Counter - send_metric name, 'counter', metric, [ - :count - ] + send_metric name, 'counter', metric, metric.class.reportable_metrics when Metriks::Gauge - send_metric name, 'gauge', metric, [ - :value - ] + send_metric name, 'gauge', metric, metric.class.reportable_metrics when Metriks::UtilizationTimer - send_metric name, 'utilization_timer', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev, - :one_minute_utilization, :five_minute_utilization, - :fifteen_minute_utilization, :mean_utilization, - ], [ - :median, :get_95th_percentile - ] + send_metric name, 'utilization_timer', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) when Metriks::Timer - send_metric name, 'timer', metric, [ - :count, :one_minute_rate, :five_minute_rate, - :fifteen_minute_rate, :mean_rate, - :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] + send_metric name, 'timer', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) when Metriks::Histogram - send_metric name, 'histogram', metric, [ - :count, :min, :max, :mean, :stddev - ], [ - :median, :get_95th_percentile - ] + send_metric name, 'histogram', metric, metric.class.reportable_metrics, + metric.class.reportable_snapshot_metrics(:percentiles => percentile_methods) end end end def send_metric(name, type, metric, keys, snapshot_keys = []) keys.each do |key| - @client << @default_event.merge( + client << @default_event.merge( :service => "#{name} #{key}", :metric => metric.send(key), :tags => [type] @@ -107,7 +86,7 @@ def send_metric(name, type, metric, keys, snapshot_keys = []) unless snapshot_keys.empty? snapshot = metric.snapshot snapshot_keys.each do |key| - @client << @default_event.merge( + client << @default_event.merge( :service => "#{name} #{key}", :metric => snapshot.send(key), :tags => [type] diff --git a/test/graphite_reporter_test.rb b/test/graphite_reporter_test.rb index 51dc9c4..2c18bfc 100644 --- a/test/graphite_reporter_test.rb +++ b/test/graphite_reporter_test.rb @@ -38,4 +38,41 @@ def test_write assert_match /gauge.testing.value 123/, @stringio.string assert_match /gauge.testing.block.value 456/, @stringio.string end + + def test_custom_percentiles_for_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.timer('timer.testing').update(1.5) + mock_snapshot = @registry.timer('timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.timer('timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:socket).returns(@stringio) + @reporter.write + end + + def test_custom_percentiles_for_utilization_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.utilization_timer('utilization_timer.testing').update(1.5) + mock_snapshot = @registry.utilization_timer('utilization_timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.utilization_timer('utilization_timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:socket).returns(@stringio) + @reporter.write + end + + def test_custom_percentiles_for_histograms + @reporter = build_reporter(:percentiles => :p999) + @registry.histogram('histogram.testing').update(1.5) + mock_snapshot = @registry.histogram('histogram.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.histogram('histogram.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:socket).returns(@stringio) + @reporter.write + end + + def test_default_percentile + assert_equal [:get_95th_percentile], @reporter.percentile_methods + end end diff --git a/test/librato_metrics_reporter_test.rb b/test/librato_metrics_reporter_test.rb index 4c98455..0941459 100644 --- a/test/librato_metrics_reporter_test.rb +++ b/test/librato_metrics_reporter_test.rb @@ -32,4 +32,41 @@ def test_write @reporter.write end + + def test_custom_percentiles_for_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.timer('timer.testing').update(1.5) + mock_snapshot = @registry.timer('timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.timer('timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:submit) + @reporter.write + end + + def test_custom_percentiles_for_utilization_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.utilization_timer('utilization_timer.testing').update(1.5) + mock_snapshot = @registry.utilization_timer('utilization_timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.utilization_timer('utilization_timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:submit) + @reporter.write + end + + def test_custom_percentiles_for_histograms + @reporter = build_reporter(:percentiles => :p999) + @registry.histogram('histogram.testing').update(1.5) + mock_snapshot = @registry.histogram('histogram.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.histogram('histogram.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:submit) + @reporter.write + end + + def test_default_percentile + assert_equal [:get_95th_percentile], @reporter.percentile_methods + end end diff --git a/test/logger_reporter_test.rb b/test/logger_reporter_test.rb index 7dafa1c..fb12ee0 100644 --- a/test/logger_reporter_test.rb +++ b/test/logger_reporter_test.rb @@ -46,4 +46,38 @@ def test_flush assert_match /median=\d/, @stringio.string assert_match /value=123/, @stringio.string end + +def test_custom_percentiles_for_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.timer('timer.testing').update(1.5) + mock_snapshot = @registry.timer('timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.timer('timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.write + end + + def test_custom_percentiles_for_utilization_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.utilization_timer('utilization_timer.testing').update(1.5) + mock_snapshot = @registry.utilization_timer('utilization_timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.utilization_timer('utilization_timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.write + end + + def test_custom_percentiles_for_histograms + @reporter = build_reporter(:percentiles => :p999) + @registry.histogram('histogram.testing').update(1.5) + mock_snapshot = @registry.histogram('histogram.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.histogram('histogram.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.write + end + + def test_default_percentile + assert_equal [:get_95th_percentile], @reporter.percentile_methods + end end diff --git a/test/riemann_reporter_test.rb b/test/riemann_reporter_test.rb index 98662ab..5dec202 100644 --- a/test/riemann_reporter_test.rb +++ b/test/riemann_reporter_test.rb @@ -85,4 +85,41 @@ def test_write @reporter.write end + +def test_custom_percentiles_for_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.timer('timer.testing').update(1.5) + mock_snapshot = @registry.timer('timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.timer('timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:client).returns([]) + @reporter.write + end + + def test_custom_percentiles_for_utilization_timers + @reporter = build_reporter(:percentiles => :p999) + @registry.utilization_timer('utilization_timer.testing').update(1.5) + mock_snapshot = @registry.utilization_timer('utilization_timer.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.utilization_timer('utilization_timer.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:client).returns([]) + @reporter.write + end + + def test_custom_percentiles_for_histograms + @reporter = build_reporter(:percentiles => :p999) + @registry.histogram('histogram.testing').update(1.5) + mock_snapshot = @registry.histogram('histogram.testing').snapshot + mock_snapshot.expects(:get_999th_percentile) + @registry.histogram('histogram.testing').stubs(:snapshot).returns(mock_snapshot) + + @reporter.stubs(:client).returns([]) + @reporter.write + end + + def test_default_percentile + assert_equal [:get_95th_percentile], @reporter.percentile_methods + end end From dafe13b55d5443fc356bfd9b17a7a35eef6aaa59 Mon Sep 17 00:00:00 2001 From: Brian Morton Date: Wed, 26 Jun 2013 22:45:51 -0700 Subject: [PATCH 4/4] Update README to include custom percentile reporting. --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 656f128..7e2f995 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,19 @@ will display: [metriks-sematext](https://github.com/sematext/metriks-sematext) gem provides reporter for sending metrics to [SPM](http://sematext.com/spm/index.html). +## Custom percentile reporting + +The Graphite, LibratoMetrics, Logger, and Riemann reporters all support +reporting customized percentiles for histograms, timers, and utilization timers. +By default, these reporters will report the p95 for these metric types. The +example below shows how to enable a custom set of percentile metrics + +``` ruby + Metriks::Reporter::Graphite.new('localhost', 3004, :percentiles => [:p95, :p99]) +``` + +These percentiles are supported: `:p75, :p95, :p98, :p99, :p999`. + # Application Server Configuration Depending on how your application server operates, you may need to configure how reporters are created. Please look at [Troubleshooting](https://github.com/eric/metriks/wiki/Troubleshooting) for more information.