FIX: setting a Gauge to nil corrupts metrics

FIX: setting a Gauge to nil corrupts metrics

New behavior is to remove gauge if set to nil and raise otherwise
if non numeric

From e72b24a0fcbfa8896e7e01ef57743cb12339411d Mon Sep 17 00:00:00 2001
From: Sam <sam.saffron@gmail.com>
Date: Fri, 30 Nov 2018 12:43:03 +1100
Subject: [PATCH] FIX: setting a Gauge to nil corrupts metrics

New behavior is to remove gauge if set to nil and raise otherwise
if non numeric

diff --git a/CHANGELOG b/CHANGELOG
index 48998c8..3fddacf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+0.4.2 - 30-11-2018
+
+- Fix/Feature: setting a Gauge to nil will remove Gauge (setting to non numeric will raise)
+
 0.4.0 - 23-10-2018
 
 - Feature: histogram support
diff --git a/lib/prometheus_exporter/metric/gauge.rb b/lib/prometheus_exporter/metric/gauge.rb
index 8c81a22..b26ddcf 100644
--- a/lib/prometheus_exporter/metric/gauge.rb
+++ b/lib/prometheus_exporter/metric/gauge.rb
@@ -20,7 +20,14 @@ module PrometheusExporter::Metric
     end
 
     def observe(value, labels = {})
-      @data[labels] = value
+      if value.nil?
+        data.delete(labels)
+      else
+        if !(Numeric === value)
+          raise ArgumentError, 'value must be a number'
+        end
+        @data[labels] = value
+      end
     end
 
     def increment(labels = {}, value = 1)
diff --git a/lib/prometheus_exporter/version.rb b/lib/prometheus_exporter/version.rb
index f2ab058..934c627 100644
--- a/lib/prometheus_exporter/version.rb
+++ b/lib/prometheus_exporter/version.rb
@@ -1,3 +1,3 @@
 module PrometheusExporter
-  VERSION = "0.4.1"
+  VERSION = "0.4.2"
 end
diff --git a/test/metric/gauge_test.rb b/test/metric/gauge_test.rb
index 984ab4b..71cca1a 100644
--- a/test/metric/gauge_test.rb
+++ b/test/metric/gauge_test.rb
@@ -11,6 +11,29 @@ module PrometheusExporter::Metric
       Base.default_prefix = ''
     end
 
+    it "should not allow observe to corrupt data" do
+      assert_raises do
+        gauge.observe("hello")
+      end
+
+      # going to special case nil here instead of adding a new API
+      # observing nil should set to nothing
+      # this is a slight difference to official API which would raise
+      # on non numeric, however it provides a bit more flexibility
+      # and allows us to remove metrics if we wish
+      gauge.observe(100)
+      gauge.observe(nil)
+      gauge.observe(nil, a: "thing")
+
+      text = <<~TEXT
+        # HELP a_gauge my amazing gauge
+        # TYPE a_gauge gauge
+
+      TEXT
+
+      assert_equal(gauge.to_prometheus_text, text)
+    end
+
     it "supports a dynamic prefix" do
       Base.default_prefix = 'web_'
       gauge.observe(400.11)

GitHub

2 Likes