Feature: allow finding registered metric by metric name, type, or help (#86)

Feature: allow finding registered metric by metric name, type, or help (#86)

When reusing the same client in different places to export the same metric, there is no external interface to retrieve this metric after it’s registered. Using instance_variable_get to reach into the instance variable @metrics is less preferable. Re-registering the metric will lead to an ever-growing array of @metrics.

This commit provides a way to get the metric by name, and optionally by type and help, so that we can use the registered metric(s) to observe

diff --git a/lib/prometheus_exporter/client.rb b/lib/prometheus_exporter/client.rb
index ad5de14..1f1d357 100644
--- a/lib/prometheus_exporter/client.rb
+++ b/lib/prometheus_exporter/client.rb
@@ -7,6 +7,8 @@ module PrometheusExporter
 
   class Client
     class RemoteMetric
+      attr_reader :name, :type, :help
+
       def initialize(name:, help:, type:, client:)
         @name = name
         @help = help
@@ -87,6 +89,16 @@ module PrometheusExporter
       metric
     end
 
+    def find_registered_metric(name, type: nil, help: nil)
+      @metrics.find do |metric|
+        type_match = type ? metric.type == type : true
+        help_match = help ? metric.help == help : true
+        name_match = metric.name == name
+
+        type_match && help_match && name_match
+      end
+    end
+
     def send_json(obj)
       payload = @custom_labels.nil? ? obj : obj.merge(custom_labels: @custom_labels)
       send(@json_serializer.dump(payload))
diff --git a/test/client_test.rb b/test/client_test.rb
new file mode 100644
index 0000000..6f30a3d
--- /dev/null
+++ b/test/client_test.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class PrometheusExporterTest < Minitest::Test
+  def test_find_the_correct_registered_metric
+    client = PrometheusExporter::Client.new
+
+    # register a metrics for testing
+    counter_metric = client.register(:counter, 'counter_metric', 'helping')
+
+    # when the given name doesn't match any existing metric, it returns nil
+    result = client.find_registered_metric('not_registered')
+    assert_nil(result)
+
+    # when the given name matches an existing metric, it returns this metric
+    result = client.find_registered_metric('counter_metric')
+    assert_equal(counter_metric, result)
+
+    # when the given name matches an existing metric, but the given type doesn't, it returns nil
+    result = client.find_registered_metric('counter_metric', type: :gauge)
+    assert_nil(result)
+
+    # when the given name and type match an existing metric, it returns the metric
+    result = client.find_registered_metric('counter_metric', type: :counter)
+    assert_equal(counter_metric, result)
+
+    # when the given name matches an existing metric, but the given help doesn't, it returns nil
+    result = client.find_registered_metric('counter_metric', help: 'not helping')
+    assert_nil(result)
+
+    # when the given name and help match an existing metric, it returns the metric
+    result = client.find_registered_metric('counter_metric', help: 'helping')
+    assert_equal(counter_metric, result)
+
+    # when the given name matches an existing metric, but the given help and type don't, it returns nil
+    result = client.find_registered_metric('counter_metric', type: :gauge, help: 'not helping')
+    assert_nil(result)
+
+    # when the given name, type, and help all match an existing metric, it returns the metric
+    result = client.find_registered_metric('counter_metric', type: :counter, help: 'helping')
+    assert_equal(counter_metric, result)
+  end
+end

GitHub sha: a70657f2