-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from bukalapak/master
histogram support for ruby client
- Loading branch information
Showing
6 changed files
with
195 additions
and
0 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,73 @@ | ||
# encoding: UTF-8 | ||
|
||
require 'prometheus/client/metric' | ||
|
||
module Prometheus | ||
module Client | ||
# A histogram samples observations (usually things like request durations | ||
# or response sizes) and counts them in configurable buckets. It also | ||
# provides a sum of all observed values. | ||
class Histogram < Metric | ||
# Value represents the state of a Histogram at a given point. | ||
class Value < Hash | ||
attr_accessor :sum, :total | ||
|
||
def initialize(buckets) | ||
@sum = 0.0 | ||
@total = 0 | ||
|
||
buckets.each do |bucket| | ||
self[bucket] = 0 | ||
end | ||
end | ||
|
||
def observe(value) | ||
@sum += value | ||
@total += 1 | ||
|
||
each_key do |bucket| | ||
self[bucket] += 1 if value <= bucket | ||
end | ||
end | ||
end | ||
|
||
# DEFAULT_BUCKETS are the default Histogram buckets. The default buckets | ||
# are tailored to broadly measure the response time (in seconds) of a | ||
# network service. (From DefBuckets client_golang) | ||
DEFAULT_BUCKETS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, | ||
2.5, 5, 10].freeze | ||
|
||
# Offer a way to manually specify buckets | ||
def initialize(name, docstring, base_labels = {}, | ||
buckets = DEFAULT_BUCKETS) | ||
raise ArgumentError, 'Unsorted buckets, typo?' unless sorted? buckets | ||
|
||
@buckets = buckets | ||
super(name, docstring, base_labels) | ||
end | ||
|
||
def type | ||
:histogram | ||
end | ||
|
||
def observe(labels, value) | ||
if labels[:le] | ||
raise ArgumentError, 'Label with name "le" is not permitted' | ||
end | ||
|
||
label_set = label_set_for(labels) | ||
synchronize { @values[label_set].observe(value) } | ||
end | ||
|
||
private | ||
|
||
def default | ||
Value.new(@buckets) | ||
end | ||
|
||
def sorted?(bucket) | ||
bucket.each_cons(2).all? { |i, j| i <= j } | ||
end | ||
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
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,72 @@ | ||
# encoding: UTF-8 | ||
|
||
require 'prometheus/client/histogram' | ||
require 'examples/metric_example' | ||
|
||
describe Prometheus::Client::Histogram do | ||
let(:histogram) do | ||
described_class.new(:bar, 'bar description', {}, [2.5, 5, 10]) | ||
end | ||
|
||
it_behaves_like Prometheus::Client::Metric do | ||
let(:type) { Hash } | ||
end | ||
|
||
describe '#initialization' do | ||
it 'raise error for unsorted buckets' do | ||
expect do | ||
described_class.new(:bar, 'bar description', {}, [5, 2.5, 10]) | ||
end.to raise_error ArgumentError | ||
end | ||
end | ||
|
||
describe '#observe' do | ||
it 'records the given value' do | ||
expect do | ||
histogram.observe({}, 5) | ||
end.to change { histogram.get } | ||
end | ||
|
||
it 'raise error for le labels' do | ||
expect do | ||
histogram.observe({ le: 1 }, 5) | ||
end.to raise_error ArgumentError | ||
end | ||
end | ||
|
||
describe '#get' do | ||
before do | ||
histogram.observe({ foo: 'bar' }, 3) | ||
histogram.observe({ foo: 'bar' }, 5.2) | ||
histogram.observe({ foo: 'bar' }, 13) | ||
histogram.observe({ foo: 'bar' }, 4) | ||
end | ||
|
||
it 'returns a set of buckets values' do | ||
expect(histogram.get(foo: 'bar')).to eql(2.5 => 0, 5 => 2, 10 => 3) | ||
end | ||
|
||
it 'returns a value which responds to #sum and #total' do | ||
value = histogram.get(foo: 'bar') | ||
|
||
expect(value.sum).to eql(25.2) | ||
expect(value.total).to eql(4) | ||
end | ||
|
||
it 'uses zero as default value' do | ||
expect(histogram.get({})).to eql(2.5 => 0, 5 => 0, 10 => 0) | ||
end | ||
end | ||
|
||
describe '#values' do | ||
it 'returns a hash of all recorded summaries' do | ||
histogram.observe({ status: 'bar' }, 3) | ||
histogram.observe({ status: 'foo' }, 6) | ||
|
||
expect(histogram.values).to eql( | ||
{ status: 'bar' } => { 2.5 => 0, 5 => 1, 10 => 1 }, | ||
{ status: 'foo' } => { 2.5 => 0, 5 => 0, 10 => 1 }, | ||
) | ||
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