Current section
Files
Jump to
Current section
Files
src/prometheus_push.erl
-module(prometheus_push).
-export([push/0,
push/1,
add/0,
add/1,
delete/0,
delete/1
]).
-export([hostname_grouping_key/0]).
-ifdef(TEST).
-export([encode_grouping_key/1,
to_string/1,
get_config_from_env/0,
prepare_request_params/1,
construct_url/3]).
-endif.
%%%===================================================================
%%% API
%%%===================================================================
push() ->
request(put, #{}).
push(Options) when is_map(Options) ->
request(put, Options);
push(Job) ->
request(put, #{job => Job}).
add() ->
request(post, #{}).
add(Options) when is_map(Options) ->
request(post, Options);
add(Job) ->
request(post, #{job => Job}).
delete() ->
request(delete, #{}).
delete(Options) when is_map(Options) ->
request(delete, Options);
delete(Job) ->
request(delete, #{job => Job}).
hostname_grouping_key() ->
{ok, Hostname} = inet:gethostname(),
#{
<<"instance">> => Hostname
}.
%%%===================================================================
%%% Private functions
%%%===================================================================
request(Method, Request) ->
try
{Job, Registry, GroupingKey, Address} = prepare_request_params(Request),
URL = construct_url(Address, Job, GroupingKey),
ContentType = prometheus_text_format:content_type(),
Body =
case Method of
delete ->
<<>>;
_ ->
prometheus_text_format:format(Registry)
end,
request(Method, URL, ContentType, Body)
catch
error:{badkey, Key} ->
{error, {missing_option, Key}};
error:{unknown_registry, UR} ->
{error, {unknown_registry, UR}};
error:{to_string_failed, IS} ->
{error, {to_string_failed, IS}}
end.
request(Method, URL0, CT0, Body) ->
URL = binary_to_list(iolist_to_binary(URL0)),
CT = binary_to_list(iolist_to_binary(CT0)),
case httpc:request(Method, {URL, [], CT, Body}, [], []) of
{ok, {{_, 202, _}, _, _}} ->
ok;
Error -> Error
end.
prepare_request_params(Request) ->
Config0 = get_config_from_env(),
Config = maps:merge(Config0, Request),
Job = maps:get(job, Config),
Registry = maps:get(registry, Config, default),
case prometheus_registry:exists(Registry) of
true -> ok;
false ->
erlang:error({unknown_registry, Registry})
end,
GroupingKey = maps:get(grouping_key, Config, #{}),
Address = maps:get(address, Config, "http://127.0.0.1:9091"),
{Job, Registry, GroupingKey, Address}.
get_config_from_env() ->
case application:get_env(prometheus, pushgateway, #{}) of
LC when is_list(LC) ->
MC = maps:from_list(LC),
application:set_env(prometheus, pushgateway, MC),
MC;
MC when is_map(MC) ->
MC
end.
encode_grouping_key(GK) when is_map(GK) ->
maps:fold(fun(K, V, Acc) ->
[encode_grouping_key_pair(K, V) ++ Acc]
end,
[],
GK);
encode_grouping_key(GK) when is_list(GK) ->
lists:foldl(fun({K, V}, Acc) ->
[encode_grouping_key_pair(K, V) ++ Acc]
end,
[],
GK).
encode_grouping_key_pair(K, V) ->
["/", http_uri:encode(to_string(K)),
"/", http_uri:encode(to_string(V))].
to_string(Val) ->
binary_to_list(iolist_to_binary(to_string_(Val))).
to_string_(Val) when is_atom(Val) ->
atom_to_binary(Val, utf8);
to_string_(Val) when is_number(Val) ->
io_lib:format("~p", [Val]);
to_string_(Val) ->
try iolist_to_binary(Val) of
Str -> Str
catch
error:badarg ->
erlang:error({to_string_failed, Val})
end.
construct_url(Address, Job, GroupingKey) ->
[Address,
"/metrics/job/", http_uri:encode(to_string(Job)),
encode_grouping_key(GroupingKey)].