./ct_report/coverage/mongoose_instrument_prometheus.COVER.html

1 -module(mongoose_instrument_prometheus).
2
3 -behaviour(mongoose_instrument).
4
5 -export([set_up/3, handle_event/4]).
6
7 %% Define Prometheus metric-related types, because the library has no type specs
8 -type spec() :: proplists:proplist().
9 -type name() :: string().
10 -type help() :: string().
11
12 -spec set_up(mongoose_instrument:event_name(), mongoose_instrument:labels(),
13 mongoose_instrument:config()) -> boolean().
14 set_up(EventName, Labels, #{metrics := Metrics}) ->
15
:-(
maps:foreach(fun(MetricName, MetricType) ->
16
:-(
set_up_metric(EventName, Labels, MetricName, MetricType)
17 end, Metrics),
18
:-(
true;
19 set_up(_EventName, _Labels, #{}) ->
20
:-(
false.
21
22 -spec handle_event(mongoose_instrument:event_name(), mongoose_instrument:labels(),
23 mongoose_instrument:config(), mongoose_instrument:measurements()) -> ok.
24 handle_event(EventName, Labels, #{metrics := Metrics}, Measurements) ->
25
:-(
LabelValues = labels_to_values(Labels),
26
:-(
maps:foreach(fun(MetricName, MetricType) ->
27
:-(
handle_metric_event(EventName, LabelValues, MetricName, MetricType, Measurements)
28 end, Metrics).
29
30 -spec set_up_metric(mongoose_instrument:event_name(), mongoose_instrument:labels(),
31 mongoose_instrument:metric_name(), mongoose_instrument:metric_type()) ->
32 ok.
33 set_up_metric(EventName, Labels, MetricName, MetricType) ->
34
:-(
LabelKeys = labels_to_keys(Labels),
35
:-(
LabelValues = labels_to_values(Labels),
36
:-(
MetricSpec = metric_spec(EventName, LabelKeys, MetricName),
37
:-(
case declare_metric(MetricSpec, MetricType) of
38
:-(
true -> ok;
39
:-(
false -> reset_metric(proplists:get_value(name, MetricSpec), LabelValues, MetricType)
40 end.
41
42 -spec declare_metric(proplists:proplist(), mongoose_instrument:metric_type()) -> boolean().
43 declare_metric(MetricSpec, spiral) ->
44
:-(
prometheus_counter:declare(MetricSpec);
45 declare_metric(MetricSpec, histogram) ->
46
:-(
prometheus_histogram:declare([{buckets, histogram_buckets()} | MetricSpec]).
47
48 -spec reset_metric(name(), [mongoose_instrument:label_value()],
49 mongoose_instrument:metric_type()) -> ok.
50 reset_metric(Name, LabelValues, spiral) ->
51
:-(
prometheus_counter:reset(Name, LabelValues),
52
:-(
prometheus_counter:inc(Name, LabelValues, 0);
53 reset_metric(Name, LabelValues, histogram) ->
54
:-(
prometheus_histogram:reset(Name, LabelValues),
55
:-(
ok.
56
57 -spec metric_spec(mongoose_instrument:event_name(), [mongoose_instrument:label_key()],
58 mongoose_instrument:metric_name()) -> spec().
59 metric_spec(EventName, LabelKeys, MetricName) ->
60
:-(
[{name, full_metric_name(EventName, MetricName)},
61 {help, metric_help(EventName, MetricName)},
62 {labels, LabelKeys}].
63
64 -spec histogram_buckets() -> [integer()].
65 histogram_buckets() ->
66
:-(
histogram_buckets([], 1 bsl 30). % ~1.07 * 10^9
67
68 histogram_buckets(AccBuckets, Val) when Val > 0 ->
69
:-(
histogram_buckets([Val | AccBuckets], Val bsr 1);
70 histogram_buckets(AccBuckets, _Val) ->
71
:-(
AccBuckets.
72
73 -spec handle_metric_event(mongoose_instrument:event_name(), [mongoose_instrument:label_value()],
74 mongoose_instrument:metric_name(), mongoose_instrument:metric_type(),
75 mongoose_instrument:measurements()) -> ok.
76 handle_metric_event(EventName, LabelValues, MetricName, MetricType, Measurements) ->
77
:-(
case Measurements of
78 #{MetricName := MetricValue} ->
79
:-(
FullName = full_metric_name(EventName, MetricName),
80
:-(
update_metric(FullName, LabelValues, MetricType, MetricValue);
81 #{} ->
82
:-(
ok
83 end.
84
85 -spec metric_help(mongoose_instrument:event_name(), mongoose_instrument:metric_name()) -> help().
86 metric_help(EventName, MetricName) ->
87
:-(
lists:flatten(io_lib:format("Event: ~p, Metric: ~p", [EventName, MetricName])).
88
89 -spec full_metric_name(mongoose_instrument:event_name(), mongoose_instrument:metric_name()) ->
90 name().
91 full_metric_name(EventName, MetricName) ->
92
:-(
atom_to_list(EventName) ++ "_" ++ atom_to_list(MetricName).
93
94 -spec labels_to_keys(mongoose_instrument:labels()) -> [mongoose_instrument:label_key()].
95 labels_to_keys(Labels) ->
96
:-(
lists:sort(maps:keys(Labels)).
97
98 -spec labels_to_values(mongoose_instrument:labels()) -> [mongoose_instrument:label_value()].
99 labels_to_values(Labels) ->
100
:-(
[V || {_K, V} <- lists:keysort(1, maps:to_list(Labels))].
101
102 -spec update_metric(name(), [mongoose_instrument:label_value()],
103 mongoose_instrument:metric_type(), integer()) -> ok.
104 update_metric(Name, Labels, spiral, Value) when is_integer(Value), Value >= 0 ->
105
:-(
ok = prometheus_counter:inc(Name, Labels, Value);
106 update_metric(Name, Labels, histogram, Value) when is_integer(Value) ->
107
:-(
ok = prometheus_histogram:observe(Name, Labels, Value).
Line Hits Source