Current section

Files

Jump to
prometheus src formats prometheus_text_format.erl
Raw

src/formats/prometheus_text_format.erl

-module(prometheus_text_format).
-export([content_type/0,
format/0,
format/1,
registry_collect_callback/3,
collector_metrics_callback/5]).
-ifdef(TEST).
-export([escape_metric_help/1,
escape_label_value/1]).
-endif.
-include("prometheus.hrl").
-behaviour(prometheus_format).
content_type() ->
<<"text/plain; version=0.0.4">>.
format() ->
format(default).
format(Registry) ->
{ok, Fd} = ram_file:open("", [write,read,binary]),
prometheus_registry:collect(Registry, fun (_, Collector) ->
registry_collect_callback(Fd, Registry, Collector)
end),
file:write(Fd, io_lib:format("\n", [])),
{ok, Size} = ram_file:get_size(Fd),
{ok, Str} = file:pread(Fd, 0, Size),
ok = file:close(Fd),
Str.
emit_mf_prologue(Fd, Type, Name, Help) ->
file:write(Fd, io_lib:format("# TYPE ~s ~s\n# HELP ~s ~s\n", [Name, Type, Name, escape_metric_help(Help)])).
registry_collect_callback(Fd, Registry, Collector) ->
Collector:collect_mf(
fun (Type, MFName, Labels, Help, MFData) ->
emit_mf_prologue(Fd, Type, MFName, Help),
Collector:collect_metrics(MFName,
fun (Series, Value) ->
case Series of
{Name, LabelValues} ->
collector_metrics_callback(Fd, Name, Labels, LabelValues, Value);
{Name, NewLabels, LabelValues} ->
collector_metrics_callback(Fd, Name, Labels ++ NewLabels, LabelValues, Value);
LabelValues ->
collector_metrics_callback(Fd, MFName, Labels, LabelValues, Value)
end
end,
MFData)
end,
Registry).
labels_string(Labels, LabelValues) ->
case length(Labels) of
0 ->
"";
_ ->
LabelsPList = lists:zip(Labels, LabelValues),
"{" ++ string:join(lists:map(fun ({Label, Value1}) ->
io_lib:format("~s=\"~s\"", [Label, escape_label_value(Value1)])
end,
LabelsPList),
",") ++ "}"
end.
collector_metrics_callback(Fd, Name, Labels, LabelValues, '') ->
LString = labels_string(Labels, LabelValues),
file:write(Fd, io_lib:format("~s" ++ LString ++ " NaN\n", [Name]));
collector_metrics_callback(Fd, Name, Labels, LabelValues, undefined) ->
LString = labels_string(Labels, LabelValues),
file:write(Fd, io_lib:format("~s" ++ LString ++ " NaN\n", [Name]));
collector_metrics_callback(Fd, Name, Labels, LabelValues, Value) ->
LString = labels_string(Labels, LabelValues),
file:write(Fd, io_lib:format("~s" ++ LString ++ " ~p\n", [Name, Value])).
escape_metric_help(Help) ->
sub(sub(Help, "\\", "\\\\\\\\"), "\n", "\\\\n").
escape_label_value(LValue) when is_list(LValue)->
sub(sub(sub(LValue, "\\", "\\\\\\\\"), "\n", "\\\\n"), "\"", "\\\\\"");
escape_label_value(LValue) when is_binary(LValue) ->
escape_label_value(binary_to_list(LValue));
escape_label_value('+Inf') ->
"+Inf";
escape_label_value(LValue) ->
escape_label_value(io_lib:format("~p", [LValue])).
sub(Str, Old, New) when is_atom(Str) ->
sub(atom_to_list(Str), Old, New);
sub(Str,Old,New) ->
RegExp = "\\Q"++Old++"\\E",
re:replace(Str,RegExp,New,[global, {return, list}]).