FEATURE: add #remove to all metric types

FEATURE: add #remove to all metric types

#remove can be used to remove labels from a metric.

This is only rarely needed, a specific example would be a process monitoring containers, where you want to throw away old container metrics when the container goes away.

A custom collector can handle this but it more awkward to use

Resolves #59

diff --git a/CHANGELOG b/CHANGELOG
index 8e0450a..b15bd93 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+0.5.3 - 29-07-2020
+
+- FEATURE: added #remove to all metric types so users can remove specific labels if needed
+
 0.5.2 - 01-07-2020
 
 - FEATURE: expanded instrumentation for sidekiq
diff --git a/lib/prometheus_exporter/metric/counter.rb b/lib/prometheus_exporter/metric/counter.rb
index 284a729..68efcc0 100644
--- a/lib/prometheus_exporter/metric/counter.rb
+++ b/lib/prometheus_exporter/metric/counter.rb
@@ -27,6 +27,10 @@ module PrometheusExporter::Metric
       @data.dup
     end
 
+    def remove(labels)
+      @data.delete(labels)
+    end
+
     def observe(increment = 1, labels = {})
       @data[labels] ||= 0
       @data[labels] += increment
diff --git a/lib/prometheus_exporter/metric/gauge.rb b/lib/prometheus_exporter/metric/gauge.rb
index ecc3e4c..cfbdbd9 100644
--- a/lib/prometheus_exporter/metric/gauge.rb
+++ b/lib/prometheus_exporter/metric/gauge.rb
@@ -27,6 +27,10 @@ module PrometheusExporter::Metric
       @data.dup
     end
 
+    def remove(labels)
+      @data.delete(labels)
+    end
+
     def observe(value, labels = {})
       if value.nil?
         data.delete(labels)
diff --git a/lib/prometheus_exporter/metric/histogram.rb b/lib/prometheus_exporter/metric/histogram.rb
index 6354537..78a2a9d 100644
--- a/lib/prometheus_exporter/metric/histogram.rb
+++ b/lib/prometheus_exporter/metric/histogram.rb
@@ -27,6 +27,12 @@ module PrometheusExporter::Metric
       data
     end
 
+    def remove(labels)
+      @observations.delete(labels)
+      @counts.delete(labels)
+      @sums.delete(labels)
+    end
+
     def type
       "histogram"
     end
diff --git a/lib/prometheus_exporter/metric/summary.rb b/lib/prometheus_exporter/metric/summary.rb
index 07c0dcf..180087b 100644
--- a/lib/prometheus_exporter/metric/summary.rb
+++ b/lib/prometheus_exporter/metric/summary.rb
@@ -32,6 +32,13 @@ module PrometheusExporter::Metric
       data
     end
 
+    def remove(labels)
+      @counts.delete(labels)
+      @sums.delete(labels)
+      @buffers[0].delete(labels)
+      @buffers[1].delete(labels)
+    end
+
     def type
       "summary"
     end
diff --git a/lib/prometheus_exporter/version.rb b/lib/prometheus_exporter/version.rb
index 70c53ed..e10e8e0 100644
--- a/lib/prometheus_exporter/version.rb
+++ b/lib/prometheus_exporter/version.rb
@@ -1,5 +1,5 @@
 # frozen_string_literal: true
 
 module PrometheusExporter
-  VERSION = '0.5.2'
+  VERSION = '0.5.3'
 end
diff --git a/test/metric/counter_test.rb b/test/metric/counter_test.rb
index a2ac042..d844492 100644
--- a/test/metric/counter_test.rb
+++ b/test/metric/counter_test.rb
@@ -128,6 +128,15 @@ module PrometheusExporter::Metric
       assert_equal(counter.to_prometheus_text, text)
     end
 
+    it "can correctly remove metrics" do
+      counter.observe(5, sam: "ham")
+      counter.observe(10, foo: "bar")
+      counter.remove(sam: "ham")
+      counter.remove(missing: "ham")
+
+      assert_equal(counter.to_h, { foo: "bar" } => 10)
+    end
+
     it "can correctly return data set" do
       counter.observe(5, sam: "ham")
       counter.observe(10, foo: "bar")
diff --git a/test/metric/gauge_test.rb b/test/metric/gauge_test.rb
index f11383f..2be5e97 100644
--- a/test/metric/gauge_test.rb
+++ b/test/metric/gauge_test.rb
@@ -134,6 +134,15 @@ module PrometheusExporter::Metric
       assert_equal(gauge.to_prometheus_text, text)
     end
 
+    it "can correctly remove metrics" do
+      gauge.observe(5, sam: "ham")
+      gauge.observe(10, foo: "bar")
+      gauge.remove(sam: "ham")
+      gauge.remove(bam: "ham")
+
+      assert_equal(gauge.to_h, { foo: "bar" } => 10)
+    end
+
     it "can correctly return data set" do
       gauge.observe(5, sam: "ham")
       gauge.observe(10, foo: "bar")
diff --git a/test/metric/histogram_test.rb b/test/metric/histogram_test.rb
index 9732253..23b6324 100644
--- a/test/metric/histogram_test.rb
+++ b/test/metric/histogram_test.rb
@@ -126,5 +126,18 @@ module PrometheusExporter::Metric
 
       assert_equal(histogram.to_h, { name: "bob", family: "skywalker" } => { "count" => 3, "sum" => 1.79 })
     end
+
+    it "can correctly remove histograms" do
+      histogram.observe(0.1, name: "bob", family: "skywalker")
+      histogram.observe(0.7, name: "bob", family: "skywalker")
+      histogram.observe(0.99, name: "bob", family: "skywalker")
+
+      histogram.observe(0.6, name: "gandalf", family: "skywalker")
+
+      histogram.remove(name: "gandalf", family: "skywalker")
+      histogram.remove(name: "jane", family: "skywalker")
+
+      assert_equal(histogram.to_h, { name: "bob", family: "skywalker" } => { "count" => 3, "sum" => 1.79 })
+    end
   end
 end
diff --git a/test/metric/summary_test.rb b/test/metric/summary_test.rb
index 633f56b..bf31134 100644
--- a/test/metric/summary_test.rb
+++ b/test/metric/summary_test.rb
@@ -129,5 +129,18 @@ module PrometheusExporter::Metric
 
       assert_equal(summary.to_h, { name: "bob", family: "skywalker" } => { "count" => 3, "sum" => 1.79 })
     end
+
+    it "can correctly remove data" do
+      summary.observe(0.1, name: "bob", family: "skywalker")
+      summary.observe(0.7, name: "bob", family: "skywalker")
+      summary.observe(0.99, name: "bob", family: "skywalker")
+
+      summary.observe(0.1, name: "jane", family: "skywalker")
+      summary.observe(0.2, name: "jane", family: "skywalker")
+
+      summary.remove(name: "jane", family: "skywalker")
+
+      assert_equal(summary.to_h, { name: "bob", family: "skywalker" } => { "count" => 3, "sum" => 1.79 })
+    end
   end
 end

GitHub sha: cf5997fa