Page MenuHomePhorge

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/prometheus/metric/boolean.ex b/lib/prometheus/metric/boolean.ex
new file mode 100644
index 0000000..b03a899
--- /dev/null
+++ b/lib/prometheus/metric/boolean.ex
@@ -0,0 +1,130 @@
+defmodule Prometheus.Metric.Boolean do
+ @moduledoc """
+ Boolean metric, to report booleans and flags.
+
+ Boolean is a non-standard metric that uses untyped metric underneath.
+
+ A Boolean is typically used as a flag i.e. enabled/disabled, online/offline.
+
+ Example:
+ ```
+ -module(my_fuse_instrumenter).
+
+ -export([setup/0,
+ fuse_event/2]).
+
+ setup() ->
+ prometheus_boolean:declare([{name, app_fuse_state},
+ {labels, [name]}, %% fuse name
+ {help, "State of various app fuses."}]),
+
+ fuse_event(Fuse, Event) ->
+ case Event of
+ ok -> prometheus_boolean:set(app_fuse_state, [Fuse], true);
+ blown -> prometheus_boolean:set(app_fuse_state, [Fuse], false);
+ _ -> ok
+ end.
+ ```
+ """
+
+ use Prometheus.Erlang, :prometheus_boolean
+
+ @doc """
+ Creates a boolean using `spec`.
+
+ 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.InvalidLabelNameError` if label name is invalid.<br>
+ Raises `Prometheus.MFAlreadyExistsError` if a boolean with
+ the same `spec` already exists.
+ """
+ defmacro new(spec) do
+ Erlang.call([spec])
+ end
+
+ @doc """
+ Creates a boolean using `spec`.
+ If a boolean 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.InvalidLabelNameError` if label name is invalid.
+ """
+ defmacro declare(spec) do
+ Erlang.call([spec])
+ end
+
+ @doc """
+ Sets the boolean identified by `spec` to `value`.
+
+ Valid "truthy" values:
+ - `true`;
+ - `false`;
+ - `0` -> false;
+ - `number > 0` -> true;
+ - `[]` -> false
+ - `non-empty list` -> true;
+ - `:undefined` -> undefined
+
+ Other values will generate `Prometheus.InvalidValueError` error.
+
+ Raises `Prometheus.InvalidValueError` exception if `value` isn't
+ a boolean or `:undefined`.<br>
+ Raises `Prometheus.UnknownMetricError` exception if a boolean for `spec`
+ can't be found.<br>
+ Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
+ """
+ defmacro set(spec, value) do
+ Erlang.metric_call(spec, [value])
+ end
+
+ @doc """
+ Toggles the boolean identified by `spec` to `value`.
+
+ Raises `Prometheus.InvalidValueError` exception if boolean is `:undefined`.<br>
+ Raises `Prometheus.UnknownMetricError` exception if a boolean for `spec`
+ can't be found.<br>
+ Raises `Prometheus.InvalidMetricArityError` exception if labels count mismatch.
+ """
+ defmacro toggle(spec) do
+ Erlang.metric_call(spec)
+ end
+
+ @doc """
+ Removes boolean series identified by spec.
+
+ Raises `Prometheus.UnknownMetricError` exception if a boolean
+ 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 boolean identified by `spec`.
+
+ Raises `Prometheus.UnknownMetricError` exception if a boolean
+ 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 boolean identified by `spec`. If there is no boolean for
+ given labels combination, returns `:undefined`.
+
+ Raises `Prometheus.UnknownMetricError` exception if a boolean
+ 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
diff --git a/test/metric/boolean_test.exs b/test/metric/boolean_test.exs
new file mode 100644
index 0000000..94a5ba9
--- /dev/null
+++ b/test/metric/boolean_test.exs
@@ -0,0 +1,210 @@
+defmodule Prometheus.BooleanTest do
+ use Prometheus.Case
+
+ test "registration" do
+ spec = [name: :name,
+ help: "",
+ registry: :qwe]
+
+ assert true == Boolean.declare(spec)
+ assert false == Boolean.declare(spec)
+ assert_raise Prometheus.MFAlreadyExistsError,
+ "Metric qwe:name already exists.",
+ fn ->
+ Boolean.new(spec)
+ end
+ end
+
+ test "spec errors" do
+ assert_raise Prometheus.MissingMetricSpecKeyError,
+ "Required key name is missing from metric spec.",
+ fn ->
+ Boolean.new([help: ""])
+ end
+ assert_raise Prometheus.InvalidMetricNameError,
+ "Invalid metric name: 12.",
+ fn ->
+ Boolean.new([name: 12, help: ""])
+ end
+ assert_raise Prometheus.InvalidMetricLabelsError,
+ "Invalid metric labels: 12.",
+ fn ->
+ Boolean.new([name: "qwe", labels: 12, help: ""])
+ end
+ assert_raise Prometheus.InvalidMetricHelpError,
+ "Invalid metric help: 12.",
+ fn ->
+ Boolean.new([name: "qwe", help: 12])
+ end
+ end
+
+ test "boolean specific errors" do
+ spec = [name: :fuse_state,
+ labels: [:qwe],
+ help: ""]
+
+ Boolean.declare(spec)
+
+ ## set
+ assert_raise Prometheus.InvalidValueError,
+ "Invalid value: %{} (value is not boolean).",
+ fn ->
+ Boolean.set(spec, %{})
+ end
+
+ ## toggle
+
+ Boolean.set(spec, :undefined)
+ assert_raise Prometheus.InvalidValueError,
+ "Invalid value: :undefined (can't toggle undefined boolean).",
+ fn ->
+ Boolean.toggle(spec)
+ end
+ end
+
+ test "mf/arity errors" do
+ spec = [name: :metric_with_label,
+ labels: [:label],
+ help: ""]
+ Boolean.declare(spec)
+
+ ## set
+ assert_raise Prometheus.UnknownMetricError,
+ "Unknown metric {registry: default, name: unknown_metric}.",
+ fn ->
+ Boolean.set(:unknown_metric, true)
+ end
+ assert_raise Prometheus.InvalidMetricArityError,
+ "Invalid metric arity: got 2, expected 1.",
+ fn ->
+ Boolean.set([name: :metric_with_label, labels: [:l1, :l2]], true)
+ end
+
+ ## toggle
+ assert_raise Prometheus.UnknownMetricError,
+ "Unknown metric {registry: default, name: unknown_metric}.",
+ fn ->
+ Boolean.toggle(:unknown_metric)
+ end
+ assert_raise Prometheus.InvalidMetricArityError,
+ "Invalid metric arity: got 2, expected 1.",
+ fn ->
+ Boolean.toggle([name: :metric_with_label, labels: [:l1, :l2]])
+ end
+
+ ## remove
+ assert_raise Prometheus.UnknownMetricError,
+ "Unknown metric {registry: default, name: unknown_metric}.",
+ fn ->
+ Boolean.remove(:unknown_metric)
+ end
+ assert_raise Prometheus.InvalidMetricArityError,
+ "Invalid metric arity: got 2, expected 1.",
+ fn ->
+ Boolean.remove([name: :metric_with_label, labels: [:l1, :l2]])
+ end
+
+ ## reset
+ assert_raise Prometheus.UnknownMetricError,
+ "Unknown metric {registry: default, name: unknown_metric}.",
+ fn ->
+ Boolean.reset(:unknown_metric)
+ end
+ assert_raise Prometheus.InvalidMetricArityError,
+ "Invalid metric arity: got 2, expected 1.",
+ fn ->
+ Boolean.reset([name: :metric_with_label, labels: [:l1, :l2]])
+ end
+
+ ## value
+ assert_raise Prometheus.UnknownMetricError,
+ "Unknown metric {registry: default, name: unknown_metric}.",
+ fn ->
+ Boolean.value(:unknown_metric)
+ end
+ assert_raise Prometheus.InvalidMetricArityError,
+ "Invalid metric arity: got 2, expected 1.",
+ fn ->
+ Boolean.value([name: :metric_with_label, labels: [:l1, :l2]])
+ end
+ end
+
+ test "set" do
+ spec = [name: :fuse_state,
+ labels: [:name],
+ help: ""]
+ Boolean.new(spec)
+
+ Boolean.set(spec, 110)
+ assert true == Boolean.value(spec)
+ Boolean.set(spec, 0)
+ assert false == Boolean.value(spec)
+ Boolean.set(spec, true)
+ assert true == Boolean.value(spec)
+ Boolean.set(spec, false)
+ assert false == Boolean.value(spec)
+ Boolean.set(spec, [1])
+ assert true == Boolean.value(spec)
+ Boolean.set(spec, [])
+ assert false == Boolean.value(spec)
+ Boolean.reset(spec)
+ assert false == Boolean.value(spec)
+ end
+
+ test "toggle" do
+ spec = [name: :fuse_state,
+ labels: [:name],
+ help: ""]
+ Boolean.new(spec)
+
+ Boolean.set(spec, 110)
+ assert true == Boolean.value(spec)
+ Boolean.toggle(spec)
+ assert false == Boolean.value(spec)
+ Boolean.toggle(spec)
+ assert true == Boolean.value(spec)
+ end
+
+ test "remove" do
+ fuse_state = [name: :fuse_state,
+ labels: [:name],
+ help: ""]
+ Boolean.new(fuse_state)
+
+ simple_boolean = [name: :simple_boolean,
+ labels: [],
+ help: ""]
+ Boolean.new(simple_boolean)
+
+ Boolean.set(fuse_state, true)
+ Boolean.set(simple_boolean, true)
+
+ assert true == Boolean.value(fuse_state)
+ assert true == Boolean.value(simple_boolean)
+
+ assert true == Boolean.remove(fuse_state)
+ assert true == Boolean.remove(simple_boolean)
+
+ assert :undefined == Boolean.value(fuse_state)
+ assert :undefined == Boolean.value(simple_boolean)
+
+ assert false == Boolean.remove(fuse_state)
+ assert false == Boolean.remove(simple_boolean)
+ end
+
+ test "default value" do
+ fuse_state = [name: :fuse_state,
+ labels: [:name],
+ help: ""]
+ Boolean.new(fuse_state)
+
+ simple_boolean = [name: :simple_boolean,
+ labels: [],
+ help: ""]
+ Boolean.new(simple_boolean)
+
+ assert :undefined == Boolean.value(fuse_state)
+ assert :undefined == Boolean.value(simple_boolean)
+ end
+
+end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 30, 9:54 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41413
Default Alt Text
(10 KB)

Event Timeline