Skip to content

Commit 54ae406

Browse files
Merge pull request #9656 from cloudamqp/prometheus_escape_label
Escape prometheus core metric label values
2 parents 1d6a792 + 8c78760 commit 54ae406

File tree

4 files changed

+81
-11
lines changed

4 files changed

+81
-11
lines changed

MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,8 @@ erlang_package.hex_package(
315315
erlang_package.hex_package(
316316
name = "prometheus",
317317
build_file = "@rabbitmq-server//bazel:BUILD.prometheus",
318-
sha256 = "2a99bb6dce85e238c7236fde6b0064f9834dc420ddbd962aac4ea2a3c3d59384",
319-
version = "4.10.0",
318+
sha256 = "719862351aabf4df7079b05dc085d2bbcbe3ac0ac3009e956671b1d5ab88247d",
319+
version = "4.11.0",
320320
)
321321

322322
erlang_package.hex_package(

deps/rabbitmq_prometheus/src/collectors/prometheus_rabbitmq_core_metrics_collector.erl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
counter_metric/2,
1717
untyped_metric/2]).
1818

19+
-import(prometheus_text_format, [escape_label_value/1]).
20+
1921
-include_lib("prometheus/include/prometheus.hrl").
2022
-include_lib("rabbit_common/include/rabbit.hrl").
2123

@@ -408,22 +410,24 @@ label(L) when is_binary(L) ->
408410
L;
409411
label(M) when is_map(M) ->
410412
maps:fold(fun (K, V, Acc = <<>>) ->
411-
<<Acc/binary, K/binary, "=\"", V/binary, "\"">>;
413+
<<Acc/binary, K/binary, "=\"", (escape_label_value(V))/binary, "\"">>;
412414
(K, V, Acc) ->
413-
<<Acc/binary, ",", K/binary, "=\"", V/binary, "\"">>
415+
<<Acc/binary, ",", K/binary, "=\"", (escape_label_value(V))/binary, "\"">>
414416
end, <<>>, M);
415417
label(#resource{virtual_host = VHost, kind = exchange, name = Name}) ->
416-
<<"vhost=\"", VHost/binary, "\",exchange=\"", Name/binary, "\"">>;
418+
<<"vhost=\"", (escape_label_value(VHost))/binary, "\",",
419+
"exchange=\"", (escape_label_value(Name))/binary, "\"">>;
417420
label(#resource{virtual_host = VHost, kind = queue, name = Name}) ->
418-
<<"vhost=\"", VHost/binary, "\",queue=\"", Name/binary, "\"">>;
421+
<<"vhost=\"", (escape_label_value(VHost))/binary, "\",",
422+
"queue=\"", (escape_label_value(Name))/binary, "\"">>;
419423
label({P, {#resource{virtual_host = QVHost, kind = queue, name = QName},
420424
#resource{virtual_host = EVHost, kind = exchange, name = EName}}}) when is_pid(P) ->
421425
%% channel_queue_exchange_metrics {channel_id, {queue_id, exchange_id}}
422426
<<"channel=\"", (iolist_to_binary(pid_to_list(P)))/binary, "\",",
423-
"queue_vhost=\"", QVHost/binary, "\",",
424-
"queue=\"", QName/binary, "\",",
425-
"exchange_vhost=\"", EVHost/binary, "\",",
426-
"exchange=\"", EName/binary, "\""
427+
"queue_vhost=\"", (escape_label_value(QVHost))/binary, "\",",
428+
"queue=\"", (escape_label_value(QName))/binary, "\",",
429+
"exchange_vhost=\"", (escape_label_value(EVHost))/binary, "\",",
430+
"exchange=\"", (escape_label_value(EName))/binary, "\""
427431
>>;
428432
label({RemoteAddress, Username, Protocol}) when is_binary(RemoteAddress), is_binary(Username),
429433
is_atom(Protocol) ->

deps/rabbitmq_prometheus/test/rabbit_prometheus_http_SUITE.erl

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ all() ->
2424
{group, per_object_endpoint_metrics},
2525
{group, commercial},
2626
{group, detailed_metrics},
27+
{group, special_chars},
2728
{group, authentication}
2829
].
2930

@@ -62,6 +63,7 @@ groups() ->
6263
exchange_bindings_metric,
6364
exchange_names_metric
6465
]},
66+
{special_chars, [], [core_metrics_special_chars]},
6567
{authentication, [], [basic_auth]}
6668
].
6769

@@ -206,6 +208,39 @@ init_per_group(commercial, Config0) ->
206208
Config1 = rabbit_ct_helpers:merge_app_env(Config0, ProductConfig),
207209
init_per_group(commercial, Config1, []);
208210

211+
init_per_group(special_chars, Config0) ->
212+
StatsEnv = {rabbit, [{collect_statistics, fine}, {collect_statistics_interval, 100}]},
213+
Config1 = init_per_group(special_chars, rabbit_ct_helpers:merge_app_env(Config0, StatsEnv), []),
214+
215+
VHost = <<"vhost\"\n\\">>,
216+
rabbit_ct_broker_helpers:add_vhost(Config1, 0, VHost, <<"guest">>),
217+
rabbit_ct_broker_helpers:set_full_permissions(Config1, VHost),
218+
VHostConn = rabbit_ct_client_helpers:open_unmanaged_connection(Config1, 0, VHost),
219+
{ok, VHostCh} = amqp_connection:open_channel(VHostConn),
220+
221+
%% new line characters (\r and \n) are removed from queue and
222+
%% exchange names during creation (unlike for vhosts)
223+
QName = <<"queue\"\\">>,
224+
#'queue.declare_ok'{} = amqp_channel:call(VHostCh,
225+
#'queue.declare'{queue = QName,
226+
durable = true
227+
}),
228+
Exchange = <<"exchange\"\\">>,
229+
#'exchange.declare_ok'{} = amqp_channel:call(VHostCh, #'exchange.declare'{exchange = Exchange}),
230+
#'queue.bind_ok'{} = amqp_channel:call(VHostCh, #'queue.bind'{queue = QName, exchange = Exchange, routing_key = QName}),
231+
232+
amqp_channel:call(VHostCh,
233+
#'basic.publish'{exchange = Exchange, routing_key = QName},
234+
#amqp_msg{payload = <<"msg">>}),
235+
236+
Config2 = [{vhost_name, VHost},
237+
{queue_name, QName},
238+
{exchange_name, Exchange},
239+
{connection, VHostConn},
240+
{channel, VHostCh}
241+
|Config1],
242+
init_per_group(special_chars, Config2, []);
243+
209244
init_per_group(authentication, Config) ->
210245
Config1 = rabbit_ct_helpers:merge_app_env(
211246
Config, {rabbitmq_prometheus, [{authentication, [{enabled, true}]}]}),
@@ -249,6 +284,11 @@ end_per_group(detailed_metrics, Config) ->
249284
amqp_channel:close(VHost2Ch),
250285
amqp_connection:close(?config(vhost2_conn, Config)),
251286

287+
%% Delete queues?
288+
end_per_group_(Config);
289+
end_per_group(special_chars, Config) ->
290+
amqp_channel:close(?config(channel, Config)),
291+
amqp_connection:close(?config(connection, Config)),
252292
%% Delete queues?
253293
end_per_group_(Config);
254294
end_per_group(authentication, Config) ->
@@ -560,6 +600,32 @@ exchange_names_metric(Config) ->
560600
}, Names),
561601
ok.
562602

603+
core_metrics_special_chars(Config) ->
604+
{_, Body1} = http_get_with_pal(Config, "/metrics/detailed?family=queue_coarse_metrics", [], 200),
605+
?assertMatch(#{rabbitmq_detailed_queue_messages :=
606+
#{#{vhost => "vhost\\\"\\n\\\\",
607+
queue => "queue\\\"\\\\"} := [I]}}
608+
when I == 0; I == 1,
609+
parse_response(Body1)),
610+
611+
{_, Body2} = http_get_with_pal(Config, "/metrics/detailed?family=channel_exchange_metrics", [], 200),
612+
#{rabbitmq_detailed_channel_messages_published_total := LabelValue2} = parse_response(Body2),
613+
?assertMatch([{#{channel := _,
614+
vhost := "vhost\\\"\\n\\\\",
615+
exchange := "exchange\\\"\\\\"}, [I]}]
616+
when I == 0; I == 1,
617+
maps:to_list(LabelValue2)),
618+
619+
{_, Body3} = http_get_with_pal(Config, "/metrics/detailed?family=channel_queue_exchange_metrics", [], 200),
620+
#{rabbitmq_detailed_queue_messages_published_total := LabelValue3} = parse_response(Body3),
621+
?assertMatch([{#{channel := _,
622+
queue_vhost := "vhost\\\"\\n\\\\",
623+
queue := "queue\\\"\\\\",
624+
exchange_vhost := "vhost\\\"\\n\\\\",
625+
exchange := "exchange\\\"\\\\"}, [I]}]
626+
when I == 0; I == 1,
627+
maps:to_list(LabelValue3)),
628+
ok.
563629

564630
basic_auth(Config) ->
565631
http_get(Config, [{"accept-encoding", "deflate"}], 401),

rabbitmq-components.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ dep_credentials_obfuscation = hex 3.4.0
117117
dep_khepri = hex 0.10.0
118118
dep_khepri_mnesia_migration = hex 0.2.1
119119
dep_looking_glass = git https://github.com/rabbitmq/looking_glass.git main
120-
dep_prometheus = hex 4.10.0
120+
dep_prometheus = hex 4.11.0
121121
dep_ra = hex 2.7.0
122122
dep_ranch = hex 2.1.0
123123
dep_recon = hex 2.5.3

0 commit comments

Comments
 (0)