Packages
prometheus
2.1.0
6.1.3
6.1.2
6.1.1
6.1.0
6.0.3
6.0.2
6.0.1
6.0.0
5.1.1
5.1.0
5.0.0
4.13.0
retired
4.12.0
4.11.0
4.10.0
4.9.1
4.9.0
4.8.2
4.8.1
4.8.0
4.6.0
4.5.0
4.4.1
4.4.0
4.3.0
4.2.2
4.2.0
4.1.0
4.0.1
4.0.0
3.5.1
3.5.0
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.2
3.3.1
3.3.0
3.2.3
3.2.2
3.2.1
3.1.1
3.1.0
3.0.1
3.0.0
3.0.0-rc1
3.0.0-alpha9
3.0.0-alpha8
3.0.0-alpha7
3.0.0-alpha6
3.0.0-alpha5
3.0.0-alpha4
3.0.0-alpha3
3.0.0-alpha2
3.0.0-alpha10
3.0.0-alpha1
2.2.0
2.1.0
2.0.0
1.7.0
1.6.0
1.5.0
1.0.2
1.0.1
1.0.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Prometheus.io client in Erlang
Current section
Files
Jump to
Current section
Files
src/prometheus_metric.erl
-module(prometheus_metric).
-export([insert_new_mf/5,
insert_new_mf/6,
insert_mf/5,
insert_mf/6,
deregister_mf/2,
check_mf_exists/4,
mf_data/1,
metrics/2,
extract_common_params/1]).
-export_type([name/0,
help/0,
value/0]).
-ifdef(TEST).
-export([validate_metric_name/1,
validate_metric_label_names/1,
validate_metric_help/1]).
-endif.
-include("prometheus.hrl").
%%====================================================================
%% Types
%%====================================================================
-type name() :: atom() | binary() | nonempty_string().
-type help() :: binary() | nonempty_string().
-type value() :: number() %% counter or gauge
| {Count :: number(), Sum :: number()} %% summary
| {Buckets :: [number(), ...], Sum :: number()}. %% histogram
%%====================================================================
%% Callbacks
%%====================================================================
-callback new(Spec :: prometheus_metric_spec:spec()) -> ok.
-callback new(Spec :: prometheus_metric_spec:spec(),
Registry :: prometheus_registry:registry()) -> ok.
-callback declare(Spec :: prometheus_metric_spec:spec()) -> boolean().
-callback declare(Spec :: prometheus_metric_spec:spec(),
Registry :: prometheus_registry:registry()) -> boolean().
-callback reset(Name :: name()) -> boolean().
-callback reset(Name :: name(), LValues :: list()) -> boolean().
-callback reset(Registry, Name, LValues) -> boolean() when
Registry :: prometheus_registry:registry(),
Name :: name(),
LValues :: list().
-callback value(Name :: name()) -> value().
-callback value(Name :: name(), LValues :: list()) -> value().
-callback value(Registry, Name, LValues) -> value() when
Registry :: prometheus_registry:registry(),
Name :: name(),
LValues :: list().
%%====================================================================
%% Public API
%%====================================================================
insert_new_mf(Table, Registry, Name, Labels, Help) ->
insert_new_mf(Table, Registry, Name, Labels, Help, undefined).
insert_new_mf(Table, Registry, Name, Labels, Help, Data) ->
case insert_mf(Table, Registry, Name, Labels, Help, Data) of
true ->
ok;
false ->
erlang:error({mf_already_exists, {Registry, Name},
"Consider using declare instead."})
end.
insert_mf(Table, Registry, Name, Labels, Help) ->
insert_mf(Table, Registry, Name, Labels, Help, undefined).
insert_mf(Table, Registry, Name, Labels, Help, Data) ->
ets:insert_new(Table, {{Registry, mf, Name}, Labels, Help, Data}).
deregister_mf(Table, Registry) ->
ets:match_delete(Table, {{Registry, mf, '_'}, '_', '_', '_'}).
check_mf_exists(Table, Registry, Name, LabelValues) ->
case ets:lookup(Table, {Registry, mf, Name}) of
[] ->
erlang:error({unknown_metric, Registry, Name});
[{_, Labels, _, _} = MF] ->
LVLength = length(LabelValues),
case length(Labels) of
LVLength ->
MF;
LabelsLength ->
erlang:error({invalid_metric_arity, LabelsLength}, LabelValues)
end
end.
mf_data(MF) ->
element(4, MF).
metrics(Table, Registry) ->
ets:match(Table, {{Registry, mf, '$1'}, '$2', '$3', '$4'}).
extract_common_params(Spec) ->
RawName = prometheus_metric_spec:fetch_value(name, Spec),
Name = validate_metric_name(RawName),
RawLabels = prometheus_metric_spec:get_value(labels, Spec, []),
Labels = validate_metric_label_names(RawLabels),
RawHelp = prometheus_metric_spec:fetch_value(help, Spec),
Help = validate_metric_help(RawHelp),
{Name, Labels, Help}.
%%====================================================================
%% Private Parts
%%====================================================================
validate_metric_name(RawName) when is_atom(RawName) ->
validate_metric_name(RawName, atom_to_list(RawName));
validate_metric_name(RawName) when is_binary(RawName) ->
validate_metric_name(RawName, binary_to_list(RawName));
validate_metric_name(RawName) when is_list(RawName) ->
validate_metric_name(RawName, RawName);
validate_metric_name(RawName) ->
erlang:error({invalid_metric_name, RawName, "metric name is not a string"}).
validate_metric_name(RawName, ListName) ->
case io_lib:printable_unicode_list(ListName) of
true ->
Regex = "^[a-zA-Z_:][a-zA-Z0-9_:]*$",
case re:run(ListName, Regex) of
{match, _} ->
RawName;
nomatch ->
erlang:error({invalid_metric_name, RawName,
"metric name doesn't match regex " ++ Regex})
end;
false ->
erlang:error({invalid_metric_name, RawName,
"metric name is invalid string"})
end.
validate_metric_label_names(RawLabels) when is_list(RawLabels) ->
lists:map(fun validate_metric_label_name/1, RawLabels);
validate_metric_label_names(RawLabels) ->
erlang:error({invalid_metric_labels, RawLabels, "not list"}).
validate_metric_label_name(RawName) when is_atom(RawName) ->
validate_metric_label_name(atom_to_list(RawName));
validate_metric_label_name(RawName) when is_binary(RawName) ->
validate_metric_label_name(binary_to_list(RawName));
validate_metric_label_name(RawName) when is_list(RawName) ->
case io_lib:printable_unicode_list(RawName) of
true ->
validate_metric_label_name_content(RawName);
false ->
erlang:error({invalid_metric_label_name, RawName,
"metric label is invalid string"})
end;
validate_metric_label_name(RawName) ->
erlang:error({invalid_metric_label_name, RawName,
"metric label is not a string"}).
validate_metric_label_name_content("__" ++ _Rest = RawName) ->
erlang:error({invalid_metric_label_name, RawName,
"metric label can't start with __"});
validate_metric_label_name_content(RawName) ->
Regex = "^[a-zA-Z_][a-zA-Z0-9_]*$",
case re:run(RawName, Regex) of
{match, _} -> RawName;
nomatch ->
erlang:error({invalid_metric_label_name, RawName,
"metric label doesn't match regex " ++ Regex})
end.
validate_metric_help(RawHelp) when is_binary(RawHelp) ->
validate_metric_help(binary_to_list(RawHelp));
validate_metric_help(RawHelp) when is_list(RawHelp) ->
case io_lib:printable_unicode_list(RawHelp) of
true -> RawHelp;
false -> erlang:error({invalid_metric_help, RawHelp,
"metric help is invalid string"})
end;
validate_metric_help(RawHelp) ->
erlang:error({invalid_metric_help, RawHelp, "metric help is not a string"}).