defmodule Prometheus.InvalidValueError do @moduledoc """ Raised when given `value` is invalid i.e. when you pass a negative number to `Prometheus.Metric.Counter.inc/2`. """ defexception [:value, :orig_message] def message(%{value: value, orig_message: message}) do "Invalid value: #{inspect value} (#{message})." end end defmodule Prometheus.InvalidMetricNameError do @moduledoc """ Raised when given metric `name` is invalid i.e. can't be represented as printable utf-8 string that matches `^[a-zA-Z_:][a-zA-Z0-9_:]*$` regular expression. """ defexception [:name] def message(%{name: name}) do "Invalid metric name: #{name}." end end defmodule Prometheus.InvalidMetricLabelsError do @moduledoc """ Raised when `labels` isn't a list. """ defexception [:labels] def message(%{labels: labels}) do "Invalid metric labels: #{labels}." end end defmodule Prometheus.InvalidMetricHelpError do @moduledoc """ Raised when given metric `help` is invalid i.e. isn't a printable utf-8 string. """ defexception [:help] def message(%{help: help}) do "Invalid metric help: #{help}." end end defmodule Prometheus.InvalidMetricArityError do @moduledoc """ Raised when metric arity is invalid e.g. counter metric was created with two labels but only one label value is passed to `Prometheus.Metric.Counter.inc/2`. """ defexception [:present, :expected] def message(%{present: present, expected: expected}) do "Invalid metric arity: got #{present}, expected #{expected}." end end defmodule Prometheus.UnknownMetricError do defexception [:registry, :name] def message(%{registry: registry, name: name}) do "Unknown metric {registry: #{registry}, name: #{name}}." end end defmodule Prometheus.InvalidLabelNameError do @moduledoc """ Raised when label `name` is invalid i.e. can't be represented as printable utf-8 string that matches `^[a-zA-Z_][a-zA-Z0-9_]*$` regular expression or starts with `__`. Metric can impose further restrictions on label names. """ defexception [:name, :orig_message] def message(%{name: name, orig_message: message}) do "Invalid label name: #{name} (#{message})." end end defmodule Prometheus.MFAlreadyExistsError do @moduledoc """ Raised when one tries to create metric in `registry` with `name` it already exists. """ defexception [:registry, :name] def message(%{registry: registry, name: name}) do "Metric #{registry}:#{name} already exists." end end defmodule Prometheus.HistogramNoBucketsError do @moduledoc """ Raised by histogram constructors when buckets can't be found in spec, or found value is empty list. """ defexception [:buckets] def message(%{buckets: buckets}) do "Invalid histogram buckets: #{buckets}." end end defmodule Prometheus.HistogramInvalidBucketsError do @moduledoc """ Raised by histogram constructors when buckets are invalid i.e. not sorted in increasing order or generator spec is unknown. """ defexception [:buckets, :orig_message] def message(%{buckets: buckets, orig_message: message}) do buckets = :io_lib.format("~p", [buckets]) "Invalid histogram buckets: #{buckets} (#{message})." end end defmodule Prometheus.HistogramInvalidBoundError do @moduledoc """ Raised by histogram constructors when bucket bound isn't a number. """ defexception [:bound] def message(%{bound: bound}) do "Invalid histogram bound: #{bound}." end end defmodule Prometheus.MissingMetricSpecKeyError do @moduledoc """ Raised when required metric `spec` `key` is missing. All metrics require at least `name` and when metric created `help`. Metrics can have their specific required keys. """ defexception [:key, :spec] def message(%{key: key}) do "Required key #{key} is missing from metric spec." end end defmodule Prometheus.Error do @moduledoc false @lint [{Credo.Check.Refactor.ABCSize, false}, {Credo.Check.Refactor.CyclomaticComplexity, false}] def normalize(erlang_error) do case erlang_error do %ErlangError{original: original} -> case original do {:invalid_value, value, message} -> %Prometheus.InvalidValueError{value: value, orig_message: message} {:invalid_metric_name, name, _message} -> %Prometheus.InvalidMetricNameError{name: name} {:invalid_metric_help, help, _message} -> %Prometheus.InvalidMetricHelpError{help: help} {:invalid_metric_arity, present, expected} -> %Prometheus.InvalidMetricArityError{present: present, expected: expected} {:unknown_metric, registry, name} -> %Prometheus.UnknownMetricError{registry: registry, name: name} {:invalid_metric_labels, labels, _message} -> %Prometheus.InvalidMetricLabelsError{labels: labels} {:invalid_metric_label_name, name, message} -> %Prometheus.InvalidLabelNameError{name: name, orig_message: message} {:mf_already_exists, {registry, name}, _message} -> %Prometheus.MFAlreadyExistsError{registry: registry, name: name} {:histogram_no_buckets, buckets} -> %Prometheus.HistogramNoBucketsError{buckets: buckets} {:histogram_invalid_buckets, buckets, message} -> %Prometheus.HistogramInvalidBucketsError{buckets: buckets, orig_message: message} {:histogram_invalid_bound, bound} -> %Prometheus.HistogramInvalidBoundError{bound: bound} {:missing_metric_spec_key, key, spec} -> %Prometheus.MissingMetricSpecKeyError{key: key, spec: spec} _ -> erlang_error end _ -> erlang_error end end defmacro with_prometheus_error(block) do quote do try do unquote(block) rescue e in ErlangError -> reraise Prometheus.Error.normalize(e), System.stacktrace end end end end