Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3e7c76f

Browse files
committed
rabbit_logger_exchange_h: Always declare exchange, even if exchange logging is disabled
[Why] When the exchange logger handler is added, the broker is not ready to declare the exchange. The previous implementation used a temporary process that entered a loop to wait for the broker to be ready and declare the exchange. It was possible that definitions were imported before the exchange was declared, leading to errors if bindings referenced it. There was another problem: the exported definitions were dependent on the exchange logger configuration: * The default vhost under which the logger exchange is declared is configurable. * The logger exchange is only declared if the exchange logger handler is enabled in the configuration. Because of this, the import of definitions could fail if the configuration of the node where the definitions are imported does not enable the exchange logger handler. [How] This patch changes two things: 1. The logger exchange is always declared, regardless if exchange-based logging is enabled or not. This also allows to get rid of the polling in the setup process. 2. The logger exchange is included in the exported definitions. This way, the exported definitions don't depend on any configuration on the nodes they are imported in: the exported definitions are self-contained and know about this logger exchange. Part 1 could be enough to fix the problem on RabbitMQ version that include this patch. Part 2 allows to fix the problem when definitions are exported from a version with this patch and are imported on a version without.
1 parent b557f80 commit 3e7c76f

6 files changed

Lines changed: 32 additions & 57 deletions

File tree

deps/rabbit/src/rabbit.erl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,16 @@
205205
{requires, prevent_startup_if_node_was_reset},
206206
{enables, routing_ready}]}).
207207

208-
209208
-rabbit_boot_step({cluster_tags,
210209
[{description, "Set cluster tags"},
211210
{mfa, {?MODULE, update_cluster_tags, []}},
212211
{requires, core_initialized}]}).
213212

213+
-rabbit_boot_step({logger_exchange,
214+
[{description, "Declare exchange for rabbit_logger_exchange_h"},
215+
{mfa, {rabbit_logger_exchange_h, declare_exchange, []}},
216+
{requires, [core_initialized, recovery]}]}).
217+
214218
-rabbit_boot_step({routing_ready,
215219
[{description, "message delivery logic ready"},
216220
{requires, [core_initialized, recovery]}]}).

deps/rabbit/src/rabbit_definitions.erl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,9 +1020,14 @@ args(L) -> rabbit_misc:to_amqp_table(L).
10201020
%%
10211021

10221022
list_exchanges() ->
1023-
%% exclude internal exchanges, they are not meant to be declared or used by
1024-
%% applications
1025-
[exchange_definition(X) || X <- lists:filter(fun(#exchange{internal = true}) -> false;
1023+
%% Exclude internal exchanges, they are not meant to be declared or used by
1024+
%% applications, except the exchange used by `rabbit_logger_exchange_h'
1025+
%% because its vhost depends on the configurable default vhost: we don't
1026+
%% want the exported definitions to depend on the configuration, that's why
1027+
%% we include it in the export.
1028+
LoggerExchange = rabbit_logger_exchange_h:exchange(),
1029+
[exchange_definition(X) || X <- lists:filter(fun(#exchange{name = Name}) when Name =:= LoggerExchange -> true;
1030+
(#exchange{internal = true}) -> false;
10261031
(#exchange{name = #resource{name = <<>>}}) -> false;
10271032
(#exchange{name = #resource{name = <<"amq.", _Rest/binary>>}}) -> false;
10281033
(_) -> true

deps/rabbit/src/rabbit_logger_exchange_h.erl

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
%% License, v. 2.0. If a copy of the MPL was not distributed with this
33
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
44
%%
5-
%% Copyright (c) 2007-2026 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
5+
%% Copyright (c) 2007-2026 Broadcom. All Rights Reserved. The term “Broadcom”
6+
%% refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
67
%%
78

89
-module(rabbit_logger_exchange_h).
@@ -15,8 +16,10 @@
1516
%% logger callbacks
1617
-export([log/2, adding_handler/1, removing_handler/1, changing_config/3,
1718
filter_config/1]).
19+
%% Boot step callback.
20+
-export([declare_exchange/0]).
21+
-export([exchange/0]).
1822

19-
-define(DECL_EXCHANGE_INTERVAL_SECS, 5).
2023
-define(LOG_EXCH_NAME, <<"amq.rabbitmq.log">>).
2124
-define(DEFAULT_FORMATTER, logger_formatter).
2225
-define(DEFAULT_FORMATTER_CONFIG, #{}).
@@ -78,7 +81,7 @@ do_log(
7881
Content = rabbit_basic:build_content(PBasic, Body),
7982
case mc_amqpl:message(Exchange, RoutingKey, Content) of
8083
{ok, Msg} ->
81-
%% Publishing a message might involve a Erlang process, like a Ra
84+
%% Publishing a message might involve an Erlang process, like a Ra
8285
%% server process, to log something and call itself. We need to
8386
%% publish the message asynchronously from a separate process and
8487
%% ignore the fate of that publish, to not block an Erlang
@@ -159,51 +162,17 @@ start_setup_proc(#{config := InternalConfig} = Config) ->
159162
Exchange = rabbit_misc:r(DefaultVHost, exchange, ?LOG_EXCH_NAME),
160163
InternalConfig1 = InternalConfig#{exchange => Exchange},
161164
Pid = spawn(fun() ->
162-
wait_for_initial_pass(60),
163165
setup_proc(Config#{config => InternalConfig1})
164166
end),
165167
InternalConfig2 = InternalConfig1#{setup_proc => Pid},
166168
Config#{config => InternalConfig2}.
167169

168-
%% Declaring an exchange requires the metadata store to be ready
169-
%% which happens on a boot step after the second phase of the prelaunch.
170-
%% This function waits for the store initialisation.
171-
wait_for_initial_pass(0) ->
172-
ok;
173-
wait_for_initial_pass(N) ->
174-
case rabbit_db:is_init_finished() of
175-
false ->
176-
timer:sleep(1000),
177-
wait_for_initial_pass(N - 1);
178-
true ->
179-
ok
180-
end.
181-
182-
setup_proc(
183-
#{id := Id,
184-
config := #{exchange := Exchange}} = Config) ->
170+
setup_proc(#{id := Id} = Config) ->
185171
%% We register this process using the logger handler ID. It makes
186172
%% debugging convenient but it's not critical. That's why we catch any
187173
%% exceptions and ignore the return value.
188174
_ = catch erlang:register(Id, self()),
189-
190-
case declare_exchange(Config) of
191-
ok ->
192-
?LOG_INFO(
193-
"Logging to ~ts ready", [rabbit_misc:rs(Exchange)],
194-
#{domain => ?RMQLOG_DOMAIN_GLOBAL}),
195-
loop(Config);
196-
error ->
197-
?LOG_DEBUG(
198-
"Logging to ~ts not ready, trying again in ~b second(s)",
199-
[rabbit_misc:rs(Exchange), ?DECL_EXCHANGE_INTERVAL_SECS],
200-
#{domain => ?RMQLOG_DOMAIN_GLOBAL}),
201-
receive
202-
stop -> ok
203-
after ?DECL_EXCHANGE_INTERVAL_SECS * 1000 ->
204-
setup_proc(Config)
205-
end
206-
end.
175+
loop(Config).
207176

208177
loop(#{config := #{exchange := Exchange}} = Config) ->
209178
receive
@@ -214,7 +183,13 @@ loop(#{config := #{exchange := Exchange}} = Config) ->
214183
ok
215184
end.
216185

217-
declare_exchange(#{config := #{exchange := Exchange}}) ->
186+
exchange() ->
187+
{ok, DefaultVHost} = application:get_env(rabbit, default_vhost),
188+
Exchange = rabbit_misc:r(DefaultVHost, exchange, ?LOG_EXCH_NAME),
189+
Exchange.
190+
191+
declare_exchange() ->
192+
Exchange = exchange(),
218193
try rabbit_exchange:declare(
219194
Exchange, topic, true, false, true, [], ?INTERNAL_USER) of
220195
{ok, #exchange{}} ->
@@ -242,16 +217,6 @@ unconfigure_exchange(
242217
#{config := #{exchange := Exchange,
243218
setup_proc := Pid}}) ->
244219
Pid ! stop,
245-
case rabbit_exchange:ensure_deleted(Exchange, false, ?INTERNAL_USER) of
246-
ok ->
247-
ok;
248-
{error, timeout} ->
249-
?LOG_ERROR(
250-
"Could not delete ~ts due to a timeout",
251-
[rabbit_misc:rs(Exchange)],
252-
#{domain => ?RMQLOG_DOMAIN_GLOBAL}),
253-
ok
254-
end,
255220
?LOG_INFO(
256221
"Logging to ~ts disabled",
257222
[rabbit_misc:rs(Exchange)],

deps/rabbit/test/exchanges_SUITE.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ from_mnesia_to_khepri(Config) ->
307307
rabbit_misc:r(<<"/">>, exchange, <<"amq.fanout">>),
308308
rabbit_misc:r(<<"/">>, exchange, <<"amq.headers">>),
309309
rabbit_misc:r(<<"/">>, exchange, <<"amq.match">>),
310+
rabbit_misc:r(<<"/">>, exchange, <<"amq.rabbitmq.log">>),
310311
rabbit_misc:r(<<"/">>, exchange, <<"amq.rabbitmq.trace">>),
311312
rabbit_misc:r(<<"/">>, exchange, <<"amq.topic">>),
312313
rabbit_misc:r(<<"/">>, exchange, X)]),

deps/rabbit/test/metadata_store_migration_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ from_mnesia_to_khepri(Config) ->
117117
Queues = lists:sort(rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_amqqueue, list, [])),
118118
?assertMatch([_, _], Queues),
119119
Exchanges = lists:sort(rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_exchange, list, [])),
120-
?assertEqual(14, length(Exchanges)),
120+
?assertEqual(15, length(Exchanges)),
121121
Bindings = lists:sort(rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_binding, list, [<<"/">>])),
122122
?assertEqual(4, length(Bindings)),
123123
Server = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),

deps/rabbit/test/unit_connection_tracking_SUITE.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ end_per_testcase(Testcase, Config) ->
6868
%% ---------------------------------------------------------------------------
6969

7070
exchange_count(Config) ->
71-
%% Default exchanges == 7
72-
?assertEqual(7, rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_exchange, count, [])).
71+
%% Default exchanges == 8
72+
?assertEqual(8, rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_exchange, count, [])).
7373

7474
queue_count(Config) ->
7575
Conn = rabbit_ct_client_helpers:open_connection(Config, 0),

0 commit comments

Comments
 (0)