Page MenuHomePhorge

No OneTemporary

Size
11 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/prometheus/metric.ex b/lib/prometheus/metric.ex
index 50ead0a..448859f 100644
--- a/lib/prometheus/metric.ex
+++ b/lib/prometheus/metric.ex
@@ -1,176 +1,178 @@
defmodule Prometheus.Metric do
@moduledoc """
Prometheus metrics shortcuts.
Aliases and requires respective metric modules so they are
accessible without `Prometheus.Metric` prefix.
Allows to automatically setup metrics with
- `@<type`> attributes. Metrics will be declared in
+ `@<type>` attributes. Metrics will be declared in
the `@on_load` callback. If the module already
- has `@on_laod` callback, metrics will be declared
+ has `@on_load` callback, metrics will be declared
iff the callback returns `:ok`.
- iex(1)> defmodule MyCoolModule do
- ...(1)> use Prometheus.Metric
- ...(1)>
- ...(1)> @counter name: :test_counter3, labels: [], help: "qwe"
- ...(1)> end
- iex(2)> require Prometheus.Metric.Counter
- Prometheus.Metric.Counter
- iex(3)> Prometheus.Metric.Counter.value(:test_counter3)
- 0
+ Example:
+
+ iex(1)> defmodule MyCoolModule do
+ ...(1)> use Prometheus.Metric
+ ...(1)>
+ ...(1)> @counter name: :test_counter3, labels: [], help: "qwe"
+ ...(1)> end
+ iex(2)> require Prometheus.Metric.Counter
+ Prometheus.Metric.Counter
+ iex(3)> Prometheus.Metric.Counter.value(:test_counter3)
+ 0
"""
@metrics [:counter, :gauge, :boolean, :summary, :histogram]
defmacro __using__(_opts) do
module_name = __CALLER__.module
quote do
# credo:disable-for-next-line Credo.Check.Readability.SpaceAfterCommas
alias Prometheus.Metric.{Counter, Gauge, Histogram, Summary, Boolean}
# credo:disable-for-next-line Credo.Check.Readability.SpaceAfterCommas
require Prometheus.Metric.{Counter, Gauge, Histogram, Summary, Boolean}
require Prometheus.Error
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
if List.keymember?(Application.started_applications(), :prometheus, 0) 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
))
else
:ok
end
end
unquote(gen_on_load(env))
end
end
defp gen_on_load(env) do
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
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/lib/prometheus/metric/histogram.ex b/lib/prometheus/metric/histogram.ex
index dc6fbe1..76ad507 100644
--- a/lib/prometheus/metric/histogram.ex
+++ b/lib/prometheus/metric/histogram.ex
@@ -1,171 +1,171 @@
defmodule Prometheus.Metric.Histogram do
@moduledoc """
A Histogram tracks the size and number of events in buckets.
You can use Histograms for aggregatable calculation of quantiles.
Example use cases for Histograms:
- Response latency;
- Request size.
Histogram expects `buckets` key in a metric spec. Buckets can be:
- a list of numbers in increasing order;
- one of the generate specs (shortcuts for `Prometheus.Buckets` macros)
- - :default;
- - {:linear, start, step, count};
- - {:exponential, start, step, count}.
+ - `:default`;
+ - `{:linear, start, step, count}`;
+ - `{:exponential, start, step, count}`.
Example:
```
defmodule ExampleInstrumenter do
use Prometheus.Metric
## to be called at app/supervisor startup.
## to tolerate restarts use declare.
def setup do
Histogram.new([name: :http_request_duration_milliseconds,
labels: [:method],
buckets: [100, 300, 500, 750, 1000],
help: "Http Request execution time."])
end
def instrument(%{time: time, method: method}) do
Histogram.observe([name: :http_request_duration_milliseconds, labels: [method]],
time)
end
end
```
"""
use Prometheus.Erlang, :prometheus_histogram
@doc """
Creates a histogram using `spec`.
Histogram cannot have a label named "le".
Raises `Prometheus.MissingMetricSpecKeyError` if required `spec` key is missing.<br>
Raises `Prometheus.InvalidMetricNameError` if metric name is invalid.<br>
Raises `Prometheus.InvalidMetricHelpError` if help is invalid.<br>
Raises `Prometheus.InvalidMetricLabelsError` if labels isn't a list.<br>
Raises `Prometheus.InvalidMetricNameError` if label name is invalid.<br>
Raises `Prometheus.InvalidValueError` exception if duration_unit is unknown or
doesn't match metric name.<br>
Raises `Prometheus.MFAlreadyExistsError` if a histogram with the same `spec` exists.
Histogram-specific exceptions:
Raises `Prometheus.HistogramNoBucketsError` if buckets are missing, not a list,
empty list or not known buckets spec.<br>
Raises `Prometheus.HistogramInvalidBucketsError` if buckets aren't
in increasing order.<br>
Raises `Prometheus.HistogramInvalidBoundError` if bucket bound isn't a number.
"""
defmacro new(spec) do
Erlang.call([spec])
end
@doc """
Creates a histogram using `spec`.
Histogram cannot have a label named "le".
If a histogram with the same `spec` exists returns `false`.
Raises `Prometheus.MissingMetricSpecKeyError` if required `spec` key is missing.<br>
Raises `Prometheus.InvalidMetricNameError` if metric name is invalid.<br>
Raises `Prometheus.InvalidMetricHelpError` if help is invalid.<br>
Raises `Prometheus.InvalidMetricLabelsError` if labels isn't a list.<br>
Raises `Prometheus.InvalidMetricNameError` if label name is invalid.<br>
Raises `Prometheus.InvalidValueError` exception if duration_unit is unknown or
doesn't match metric name.
Histogram-specific exceptions:
Raises `Prometheus.HistogramNoBucketsError` if buckets are missing, not a list,
empty list or not known buckets spec.<br>
Raises `Prometheus.HistogramInvalidBucketsError` if buckets aren't
in increasing order.<br>
Raises `Prometheus.HistogramInvalidBoundError` if bucket bound isn't a number.
"""
defmacro declare(spec) do
Erlang.call([spec])
end
@doc """
Observes the given amount.
Raises `Prometheus.InvalidValueError` exception if `amount` isn't
a number.<br>
Raises `Prometheus.UnknownMetricError` exception if a histogram for `spec`
can't be found.<br>
Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
"""
defmacro observe(spec, amount \\ 1) do
Erlang.metric_call(spec, [amount])
end
@doc """
Observes the amount of time spent executing `body`.
Raises `Prometheus.UnknownMetricError` exception if a histogram for `spec`
can't be found.<br>
Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
Raises `Prometheus.InvalidValueError` exception if fun isn't a function or block.
"""
defmacro observe_duration(spec, body) do
env = __CALLER__
Prometheus.Injector.inject(
fn block ->
quote do
start_time = :erlang.monotonic_time()
try do
unquote(block)
after
end_time = :erlang.monotonic_time()
Prometheus.Metric.Histogram.observe(unquote(spec), end_time - start_time)
end
end
end,
env,
body
)
end
@doc """
Removes histogram series identified by spec.
Raises `Prometheus.UnknownMetricError` exception if a histogram for `spec`
can't be found.<br>
Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
"""
defmacro remove(spec) do
Erlang.metric_call(spec)
end
@doc """
Resets the value of the histogram identified by `spec`.
Raises `Prometheus.UnknownMetricError` exception if a histogram for `spec`
can't be found.<br>
Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
"""
defmacro reset(spec) do
Erlang.metric_call(spec)
end
@doc """
Returns the value of the histogram identified by `spec`. If there is no histogram for
given labels combination, returns `:undefined`.
Raises `Prometheus.UnknownMetricError` exception if a histogram for `spec`
can't be found.<br>
Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
"""
defmacro value(spec) do
Erlang.metric_call(spec)
end
end

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 27, 1:53 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40648
Default Alt Text
(11 KB)

Event Timeline