Page MenuHomePhorge

No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/prometheus/metric.ex b/lib/prometheus/metric.ex
index 3834ed7..e1ff485 100644
--- a/lib/prometheus/metric.ex
+++ b/lib/prometheus/metric.ex
@@ -1,27 +1,123 @@
defmodule Prometheus.Metric do
@moduledoc false
+ @metrics [:counter, :gauge, :boolean, :summary, :histogram]
+
defmacro __using__(_opts) do
+ module_name = __CALLER__.module
+
quote do
alias Prometheus.Metric.{Counter,Gauge,Histogram,Summary,Boolean}
require Prometheus.Metric.{Counter,Gauge,Histogram,Summary,Boolean}
+
+ unquote_splicing(
+ for metric <- @metrics do
+ quote do
+ Module.register_attribute unquote(module_name), unquote(metric), accumulate: true
+ end
+ end)
+
+ @before_compile unquote(__MODULE__)
+ end
+ end
+
+ defmacro __before_compile__(env) do
+ quote do
+ def __declare_prometheus_metrics__() do
+ unquote_splicing(
+ for metric <- @metrics do
+ declarations = Module.get_attribute(env.module, metric)
+ Module.delete_attribute(env.module, metric)
+ quote do
+ unquote_splicing(
+ for params <- declarations do
+ emit_create_metric(metric, params)
+ end)
+ :ok
+ end
+ end)
+ end
+
+ unquote(
+ case get_on_load_attribute(env.module) do
+ nil ->
+ quote do
+ @on_load :__declare_prometheus_metrics__
+ end
+ on_load ->
+ Module.delete_attribute(env.module, :on_load)
+ Module.put_attribute(env.module, :on_load, :__prometheus_on_load_override__)
+ quote do
+ def __prometheus_on_load_override__() do
+ case unquote(on_load)() do
+ :ok -> __declare_prometheus_metrics__()
+ result -> result
+ end
+ end
+ end
+ end)
+ end
+ end
+
+ defp get_on_load_attribute(module) do
+ case Module.get_attribute(module, :on_load) do
+ [] ->
+ nil
+ nil ->
+ nil
+ atom when is_atom(atom) ->
+ atom
+ {atom, 0} when is_atom(atom) ->
+ atom
+ [{atom, 0}] when is_atom(atom) ->
+ atom
+ other ->
+ raise ArgumentError,
+ "expected the @on_load attribute to be an atom or a " <>
+ "{atom, 0} tuple, got: #{inspect(other)}"
+ end
+ end
+
+ defp emit_create_metric(:counter, params) do
+ quote do
+ Prometheus.Metric.Counter.declare(unquote(params))
+ end
+ end
+ defp emit_create_metric(:gauge, params) do
+ quote do
+ Prometheus.Metric.Gauge.declare(unquote(params))
+ end
+ end
+ defp emit_create_metric(:boolean, params) do
+ quote do
+ Prometheus.Metric.Boolean.declare(unquote(params))
+ end
+ end
+ defp emit_create_metric(:summary, params) do
+ quote do
+ Prometheus.Metric.Summary.declare(unquote(params))
+ end
+ end
+ defp emit_create_metric(:histogram, params) do
+ quote do
+ Prometheus.Metric.Histogram.declare(unquote(params))
end
end
defmacro ct_parsable_spec?(spec) do
quote do
is_list(unquote(spec)) or is_atom(unquote(spec))
end
end
def parse_spec(spec) when is_list(spec) do
registry = Keyword.get(spec, :registry, :default)
name = Keyword.fetch!(spec, :name)
labels = Keyword.get(spec, :labels, [])
{registry, name, labels}
end
def parse_spec(spec) when is_atom(spec) do
{:default, spec, []}
end
end
diff --git a/test/metric_test.exs b/test/metric_test.exs
new file mode 100644
index 0000000..f0b6e86
--- /dev/null
+++ b/test/metric_test.exs
@@ -0,0 +1,65 @@
+defmodule Prometheus.MetricTest do
+ use Prometheus.Case
+
+ defmacro __before_compile__(_env) do
+ quote do
+ def injected_fun() do
+ 1
+ end
+ end
+ end
+
+ test "@metric attributes leads to metric declaration" do
+ defmodule ModuleWithMetrics do
+ use Prometheus.Metric
+ @before_compile Prometheus.MetricTest
+
+ @counter name: :test_counter1, labels: [], help: "qwe"
+ @counter name: :test_counter2, labels: [:tag], help: "qwa"
+
+ @gauge name: :test_gauge1, labels: [], help: "qwe"
+ @gauge name: :test_gauge2, labels: [:tag], help: "qwa"
+
+ @boolean name: :test_boolean1, labels: [], help: "qwe"
+ @boolean name: :test_boolean2, labels: [:tag], help: "qwa"
+
+ @summary name: :test_summary1, labels: [], help: "qwe"
+ @summary name: :test_summary2, labels: [:tag], help: "qwa"
+
+ @histogram name: :test_histogram1, labels: [], buckets: [1, 2], help: "qwe"
+ @histogram name: :test_histogram2, labels: [:tag], buckets: [1, 2], help: "qwa"
+
+ @on_load :custom_on_load_fun
+
+ def custom_on_load_fun() do
+ Counter.declare(name: :custom_counter, labels: [], help: "qwe")
+ :ok
+ end
+ end
+
+ defmodule ModuleWithoutOnLoad do
+ use Prometheus.Metric
+
+ @counter name: :test_counter3, labels: [], help: "qwe"
+ end
+
+ assert 1 == ModuleWithMetrics.injected_fun()
+ assert false == Counter.declare(name: :custom_counter, labels: [], help: "qwe")
+ assert false == Counter.declare(name: :test_counter3, labels: [], help: "qwe")
+
+ assert false == Counter.declare(name: :test_counter1, labels: [], help: "qwe")
+ assert false == Counter.declare(name: :test_counter2, labels: [:tag], help: "qwa")
+
+ assert false == Gauge.declare(name: :test_gauge1, labels: [], help: "qwe")
+ assert false == Gauge.declare(name: :test_gauge2, labels: [:tag], help: "qwa")
+
+ assert false == Boolean.declare(name: :test_boolean1, labels: [], help: "qwe")
+ assert false == Boolean.declare(name: :test_boolean2, labels: [:tag], help: "qwa")
+
+ assert false == Summary.declare(name: :test_summary1, labels: [], help: "qwe")
+ assert false == Summary.declare(name: :test_summary2, labels: [:tag], help: "qwa")
+
+ assert false == Histogram.declare(name: :test_histogram1, labels: [], buckets: [1, 2], help: "qwe")
+ assert false == Histogram.declare(name: :test_histogram2, labels: [:tag], buckets: [1, 2], help: "qwa")
+ end
+end

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 29, 2:49 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41234
Default Alt Text
(6 KB)

Event Timeline