1 |
|
-module(mongoose_instrument_prometheus). |
2 |
|
|
3 |
|
-behaviour(mongoose_instrument). |
4 |
|
|
5 |
|
-export([set_up/3, handle_event/4]). |
6 |
|
|
7 |
|
-spec set_up(mongoose_instrument:event_name(), mongoose_instrument:labels(), |
8 |
|
mongoose_instrument:config()) -> boolean(). |
9 |
|
set_up(EventName, Labels, #{metrics := Metrics}) -> |
10 |
:-( |
LabelKeys = labels_to_keys(Labels), |
11 |
:-( |
maps:foreach(fun(MetricName, MetricType) -> |
12 |
:-( |
set_up_metric(EventName, LabelKeys, MetricName, MetricType) |
13 |
|
end, Metrics), |
14 |
:-( |
true; |
15 |
|
set_up(_EventName, _Labels, #{}) -> |
16 |
:-( |
false. |
17 |
|
|
18 |
|
-spec handle_event(mongoose_instrument:event_name(), mongoose_instrument:labels(), |
19 |
|
mongoose_instrument:config(), mongoose_instrument:measurements()) -> ok. |
20 |
|
handle_event(EventName, Labels, #{metrics := Metrics}, Measurements) -> |
21 |
:-( |
LabelValues = labels_to_values(Labels), |
22 |
:-( |
maps:foreach(fun(MetricName, MetricType) -> |
23 |
:-( |
handle_metric_event(EventName, LabelValues, MetricName, MetricType, Measurements) |
24 |
|
end, Metrics). |
25 |
|
|
26 |
|
set_up_metric(EventName, LabelKeys, MetricName, MetricType) -> |
27 |
:-( |
MetricSpec = metric_spec(EventName, LabelKeys, MetricName), |
28 |
:-( |
declare_metric(MetricSpec, MetricType). |
29 |
|
|
30 |
|
declare_metric(MetricSpec, spiral) -> |
31 |
:-( |
prometheus_counter:declare(MetricSpec); |
32 |
|
declare_metric(MetricSpec, histogram) -> |
33 |
:-( |
prometheus_histogram:declare([{buckets, histogram_buckets()} | MetricSpec]). |
34 |
|
|
35 |
|
metric_spec(EventName, LabelKeys, MetricName) -> |
36 |
:-( |
[{name, full_metric_name(EventName, MetricName)}, |
37 |
|
{help, metric_help(EventName, MetricName)}, |
38 |
|
{labels, LabelKeys}]. |
39 |
|
|
40 |
|
histogram_buckets() -> |
41 |
:-( |
histogram_buckets([], 1 bsl 30). % ~1.07 * 10^9 |
42 |
|
|
43 |
|
histogram_buckets(AccBuckets, Val) when Val > 0 -> |
44 |
:-( |
histogram_buckets([Val | AccBuckets], Val bsr 1); |
45 |
|
histogram_buckets(AccBuckets, _Val) -> |
46 |
:-( |
AccBuckets. |
47 |
|
|
48 |
|
handle_metric_event(EventName, LabelValues, MetricName, MetricType, Measurements) -> |
49 |
:-( |
case Measurements of |
50 |
|
#{MetricName := MetricValue} -> |
51 |
:-( |
FullName = full_metric_name(EventName, MetricName), |
52 |
:-( |
update_metric(FullName, LabelValues, MetricType, MetricValue); |
53 |
|
#{} -> |
54 |
:-( |
ok |
55 |
|
end. |
56 |
|
|
57 |
|
metric_help(EventName, MetricName) -> |
58 |
:-( |
lists:flatten(io_lib:format("Event: ~p, Metric: ~p", [EventName, MetricName])). |
59 |
|
|
60 |
|
full_metric_name(EventName, MetricName) -> |
61 |
:-( |
list_to_atom(atom_to_list(EventName) ++ "_" ++ atom_to_list(MetricName)). |
62 |
|
|
63 |
|
labels_to_keys(Labels) -> |
64 |
:-( |
lists:sort(maps:keys(Labels)). |
65 |
|
|
66 |
|
labels_to_values(Labels) -> |
67 |
:-( |
[V || {_K, V} <- lists:keysort(1, maps:to_list(Labels))]. |
68 |
|
|
69 |
|
update_metric(Name, Labels, spiral, Value) when is_integer(Value), Value >= 0 -> |
70 |
:-( |
prometheus_counter:inc(Name, Labels, Value); |
71 |
|
update_metric(Name, Labels, histogram, Value) when is_integer(Value) -> |
72 |
:-( |
prometheus_histogram:observe(Name, Labels, Value). |