Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F115904
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R26 prometheus.ex
Attached
Detach File
Event Timeline
Log In to Comment