Current section

Files

Jump to
prometheus_httpd src prometheus_httpd_ct.erl
Raw

src/prometheus_httpd_ct.erl

%% @doc
%% Ready-to-use test function.
%% Helps to test an app actually has working metrics endpoint.
%% Configuration is a proplist(hence compatible with common test) with two keys:
%% - `metrics_port';
%% - `metrics_path'.
%% Function assumes localhost.
%% @end
-module(prometheus_httpd_ct).
-export([self_test/1]).
-export([self_test/2]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-define(TELEMETRY_METRICS_METADATA,
[
"# TYPE telemetry_scrape_duration_seconds summary",
"# HELP telemetry_scrape_duration_seconds Scrape duration",
"# TYPE telemetry_scrape_size_bytes summary",
"# HELP telemetry_scrape_size_bytes Scrape size, not encoded",
"# TYPE telemetry_scrape_encoded_size_bytes summary",
"# HELP telemetry_scrape_encoded_size_bytes Scrape size, encoded"
]).
%% ===================================================================
%% API
%% ===================================================================
self_test(Config) ->
Path = ?config(metrics_path, Config),
Port = ?config(metrics_port, Config),
self_test(Port, Path).
self_test(Port, Path0) ->
Path = normalize_path(Path0),
URL = format_to_string("http://localhost:~p/~s", [Port, Path]),
{ok, MetricsResponse} = httpc:request(URL),
?assertMatch(200, status(MetricsResponse)),
MetricsCT = prometheus_text_format:content_type(),
ExpectedMetricsCT = binary_to_list(MetricsCT),
?assertMatch([{"content-encoding", "identity"},
{"content-length", ExpectedMetricsCL},
{"content-type", ExpectedMetricsCT}|_]
when ExpectedMetricsCL > 0, headers(MetricsResponse)),
MetricsBody = body(MetricsResponse),
?assertMatch(true, all_telemetry_metrics_present(MetricsBody)).
%% ===================================================================
%% Private functions
%% ===================================================================
all_telemetry_metrics_present(Body) ->
lists:all(fun(Metric) ->
case re:run(Body, Metric) of
{match, _} -> true;
_ -> false
end
end, ?TELEMETRY_METRICS_METADATA).
status({{_, Status, _}, _, _}) ->
Status.
body({_, _, Body}) ->
Body.
headers({_, Headers, _}) ->
lists:sort(Headers).
normalize_path([$/| Rest]) ->
Rest;
normalize_path(<<"/", Rest/binary>>) ->
Rest;
normalize_path(Path) ->
Path.
format_to_string(Format, Args) ->
binary_to_list(
iolist_to_binary(
io_lib:format(Format, Args))).