diff --git a/README.md b/README.md index 818ebcf3..6dfcbf30 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,12 @@ class MyComponent end ``` +### `init_label_set` + +The time series of a metric are not initialized until something happens. For counters, for example, this means that the time series do not exist until the counter is incremented for the first time. + +To get around this problem the client provides the `init_label_set` method that can be used to initialise the time series of a metric for a given label set. + ### Reserved labels The following labels are reserved by the client library, and attempting to use them in a diff --git a/lib/prometheus/client/histogram.rb b/lib/prometheus/client/histogram.rb index 893282ef..7c32d016 100644 --- a/lib/prometheus/client/histogram.rb +++ b/lib/prometheus/client/histogram.rb @@ -94,6 +94,16 @@ def values end end + def init_label_set(labels) + base_label_set = label_set_for(labels) + + @store.synchronize do + (buckets + ["+Inf", "sum"]).each do |bucket| + @store.set(labels: base_label_set.merge(le: bucket.to_s), val: 0) + end + end + end + private # Modifies the passed in parameter diff --git a/lib/prometheus/client/metric.rb b/lib/prometheus/client/metric.rb index 1bb43347..92de2530 100644 --- a/lib/prometheus/client/metric.rb +++ b/lib/prometheus/client/metric.rb @@ -55,6 +55,10 @@ def with_labels(labels) store_settings: @store_settings) end + def init_label_set(labels) + @store.set(labels: label_set_for(labels), val: 0) + end + # Returns all label sets with their values def values @store.all_values diff --git a/lib/prometheus/client/summary.rb b/lib/prometheus/client/summary.rb index 9f65faa8..43a15126 100644 --- a/lib/prometheus/client/summary.rb +++ b/lib/prometheus/client/summary.rb @@ -45,6 +45,15 @@ def values end end + def init_label_set(labels) + base_label_set = label_set_for(labels) + + @store.synchronize do + @store.set(labels: base_label_set.merge(quantile: "count"), val: 0) + @store.set(labels: base_label_set.merge(quantile: "sum"), val: 0) + end + end + private def reserved_labels diff --git a/spec/prometheus/client/counter_spec.rb b/spec/prometheus/client/counter_spec.rb index 806c55b6..bd7d794f 100644 --- a/spec/prometheus/client/counter_spec.rb +++ b/spec/prometheus/client/counter_spec.rb @@ -79,4 +79,16 @@ end.to change { counter.get }.by(100.0) end end + + describe '#init_label_set' do + let(:expected_labels) { [:test] } + + it 'initializes the metric for a given label set' do + expect(counter.values).to eql({}) + + counter.init_label_set(test: 'value') + + expect(counter.values).to eql({test: 'value'} => 0.0) + end + end end diff --git a/spec/prometheus/client/gauge_spec.rb b/spec/prometheus/client/gauge_spec.rb index 9476272f..fedf3221 100644 --- a/spec/prometheus/client/gauge_spec.rb +++ b/spec/prometheus/client/gauge_spec.rb @@ -161,4 +161,16 @@ end.to change { gauge.get }.by(-100.0) end end + + describe '#init_label_set' do + let(:expected_labels) { [:test] } + + it 'initializes the metric for a given label set' do + expect(gauge.values).to eql({}) + + gauge.init_label_set(test: 'value') + + expect(gauge.values).to eql({test: 'value'} => 0.0) + end + end end diff --git a/spec/prometheus/client/histogram_spec.rb b/spec/prometheus/client/histogram_spec.rb index c64c6218..473a6b5c 100644 --- a/spec/prometheus/client/histogram_spec.rb +++ b/spec/prometheus/client/histogram_spec.rb @@ -118,4 +118,20 @@ ) end end + + describe '#init_label_set' do + let(:expected_labels) { [:status] } + + it 'initializes the metric for a given label set' do + expect(histogram.values).to eql({}) + + histogram.init_label_set(status: 'bar') + histogram.init_label_set(status: 'foo') + + expect(histogram.values).to eql( + { status: 'bar' } => { "2.5" => 0.0, "5" => 0.0, "10" => 0.0, "+Inf" => 0.0, "sum" => 0.0 }, + { status: 'foo' } => { "2.5" => 0.0, "5" => 0.0, "10" => 0.0, "+Inf" => 0.0, "sum" => 0.0 }, + ) + end + end end diff --git a/spec/prometheus/client/summary_spec.rb b/spec/prometheus/client/summary_spec.rb index c69f754f..514cf8dc 100644 --- a/spec/prometheus/client/summary_spec.rb +++ b/spec/prometheus/client/summary_spec.rb @@ -99,4 +99,20 @@ ) end end + + describe '#init_label_set' do + let(:expected_labels) { [:status] } + + it 'initializes the metric for a given label set' do + expect(summary.values).to eql({}) + + summary.init_label_set(status: 'bar') + summary.init_label_set(status: 'foo') + + expect(summary.values).to eql( + { status: 'bar' } => { "count" => 0.0, "sum" => 0.0 }, + { status: 'foo' } => { "count" => 0.0, "sum" => 0.0 }, + ) + end + end end