Skip to content

Commit ff2a4f2

Browse files
committed
Add ability to customize product name, version & banner
To override the product name (defaulting to "RabbitMQ"): * set the `$RABBITMQ_PRODUCT_NAME` environment variable, or * set the `rabbit` application `product_name` variable. To override the product version: * set the `$RABBITMQ_PRODUCT_VERSION` environment variable, or * set the `rabbit` application `product_version` variable. To add content to the banner (both the copy logged and the one printed to stdout), indicate the filename which contains it, à la `/etc/motd` using: * the `$RABBITMQ_MOTD_FILE` environment variable, or * the `rabbit` application `motd` variable. Here is an example of the printed banner with name, version & motd configured: ## ## WeatherMQ 1.2.3 ## ## ########## Copyright (c) 2007-2020 Pivotal Software, Inc. ###### ## ########## Licensed under the MPL 1.1. Website: https://rabbitmq.com This is an example of a RabbitMQ message of the day. The message is written in Paris, France. \ / It is partly cloudy outside, with a _ /"".-. temperature of 12°C. Wind is around \_( ). 30-40 km/h, from south-west. /(___(__) Doc guides: https://rabbitmq.com/documentation.html Support: https://rabbitmq.com/contact.html Tutorials: https://rabbitmq.com/getstarted.html Monitoring: https://rabbitmq.com/monitoring.html Logs: /tmp/rabbitmq-test-instances/rabbit/log/[email protected] /tmp/rabbitmq-test-instances/rabbit/log/rabbit@cassini_upgrade.log Config file(s): /tmp/rabbitmq-test-instances/test.config Starting broker... completed with 0 plugins. New APIS are available to query those product informations and use them in e.g. plugins such as the management API/UI: * rabbit:product_info/0 * rabbit:product_name/0 * rabbit:product_version/0 * rabbit:motd_file/0 * rabbit:motd/0
1 parent 3aa744f commit ff2a4f2

File tree

1 file changed

+162
-15
lines changed

1 file changed

+162
-15
lines changed

src/rabbit.erl

Lines changed: 162 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030

3131
-export([start/2, stop/1, prep_stop/1]).
3232
-export([start_apps/1, start_apps/2, stop_apps/1]).
33+
-export([product_info/0,
34+
product_name/0,
35+
product_version/0,
36+
motd_file/0,
37+
motd/0]).
3338
-export([log_locations/0, config_files/0]). %% for testing and mgmt-agent
3439
-export([is_booted/1, is_booted/0, is_booting/1, is_booting/0]).
3540

@@ -376,8 +381,9 @@ run_prelaunch_second_phase() ->
376381
start_it(StartType) ->
377382
case spawn_boot_marker() of
378383
{ok, Marker} ->
384+
Product = product_name(),
379385
T0 = erlang:timestamp(),
380-
rabbit_log:info("RabbitMQ is asked to start...", []),
386+
rabbit_log:info("~s is asked to start...", [Product]),
381387
try
382388
{ok, _} = application:ensure_all_started(rabbitmq_prelaunch,
383389
StartType),
@@ -387,8 +393,8 @@ start_it(StartType) ->
387393

388394
T1 = erlang:timestamp(),
389395
rabbit_log_prelaunch:debug(
390-
"Time to start RabbitMQ: ~p µs",
391-
[timer:now_diff(T1, T0)]),
396+
"Time to start ~s: ~p µs",
397+
[Product, timer:now_diff(T1, T0)]),
392398
stop_boot_marker(Marker),
393399
ok
394400
catch
@@ -436,10 +442,12 @@ stop() ->
436442
ok ->
437443
case rabbit_boot_state:get() of
438444
ready ->
439-
rabbit_log:info("RabbitMQ is asked to stop..."),
445+
Product = product_name(),
446+
rabbit_log:info("~s is asked to stop...", [Product]),
440447
do_stop(),
441448
rabbit_log:info(
442-
"Successfully stopped RabbitMQ and its dependencies"),
449+
"Successfully stopped ~s and its dependencies",
450+
[Product]),
443451
ok;
444452
stopped ->
445453
ok
@@ -463,7 +471,9 @@ stop_and_halt() ->
463471
try
464472
stop()
465473
catch Type:Reason ->
466-
rabbit_log:error("Error trying to stop RabbitMQ: ~p:~p", [Type, Reason]),
474+
rabbit_log:error(
475+
"Error trying to stop ~s: ~p:~p",
476+
[product_name(), Type, Reason]),
467477
error({Type, Reason})
468478
after
469479
%% Enclose all the logging in the try block.
@@ -519,9 +529,9 @@ stop_apps([]) ->
519529
ok;
520530
stop_apps(Apps) ->
521531
rabbit_log:info(
522-
lists:flatten(["Stopping RabbitMQ applications and their dependencies in the following order:~n",
532+
lists:flatten(["Stopping ~s applications and their dependencies in the following order:~n",
523533
[" ~p~n" || _ <- Apps]]),
524-
lists:reverse(Apps)),
534+
[product_name() | lists:reverse(Apps)]),
525535
ok = app_utils:stop_applications(
526536
Apps, handle_app_error(error_during_shutdown)),
527537
case lists:member(rabbit, Apps) of
@@ -664,7 +674,7 @@ maybe_print_boot_progress(true, IterationsLeft) ->
664674
{memory, any()}].
665675

666676
status() ->
667-
{ok, Version} = application:get_key(rabbit, vsn),
677+
Version = product_version(),
668678
S1 = [{pid, list_to_integer(os:getpid())},
669679
%% The timeout value used is twice that of gen_server:call/2.
670680
{running_applications, rabbit_misc:which_applications()},
@@ -817,9 +827,10 @@ start(normal, []) ->
817827
try
818828
run_prelaunch_second_phase(),
819829

820-
rabbit_log:info("~n Starting RabbitMQ ~s on Erlang ~s~n ~s~n ~s~n",
821-
[rabbit_misc:version(), rabbit_misc:otp_release(),
830+
rabbit_log:info("~n Starting ~s ~s on Erlang ~s~n ~s~n ~s~n",
831+
[product_name(), product_version(), rabbit_misc:otp_release(),
822832
?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE]),
833+
log_motd(),
823834
{ok, SupPid} = rabbit_sup:start_link(),
824835

825836
%% Compatibility with older RabbitMQ versions + required by
@@ -905,7 +916,7 @@ do_run_postlaunch_phase() ->
905916
end
906917
end, Plugins),
907918

908-
rabbit_log_prelaunch:debug("Marking RabbitMQ as running"),
919+
rabbit_log_prelaunch:debug("Marking ~s as running", [product_name()]),
909920
rabbit_boot_state:set(ready),
910921

911922
ok = rabbit_lager:broker_is_started(),
@@ -1059,8 +1070,8 @@ log_broker_started(Plugins) ->
10591070
"~n " ?BG32_START " " ?C_END " ~s").
10601071

10611072
print_banner() ->
1062-
{ok, Product} = application:get_key(description),
1063-
{ok, Version} = application:get_key(vsn),
1073+
Product = product_name(),
1074+
Version = product_version(),
10641075
LineListFormatter = fun (Placeholder, [_ | Tail] = LL) ->
10651076
LF = lists:flatten([Placeholder || _ <- lists:seq(1, length(Tail))]),
10661077
{LF, LL};
@@ -1083,8 +1094,21 @@ print_banner() ->
10831094
%% padded list lines
10841095
{LogFmt, LogLocations} = LineListFormatter("~n ~ts", log_locations()),
10851096
{CfgFmt, CfgLocations} = LineListFormatter("~n ~ts", config_locations()),
1097+
{MOTDFormat, MOTDArgs} = case motd() of
1098+
undefined ->
1099+
{"", []};
1100+
MOTD ->
1101+
Lines = string:split(MOTD, "\n", all),
1102+
Padded = [case Line of
1103+
<<>> -> "\n";
1104+
_ -> [" ", Line, "\n"]
1105+
end
1106+
|| Line <- Lines],
1107+
{"~n~ts", [Padded]}
1108+
end,
10861109
io:format(Logo ++
1087-
"~n"
1110+
"~n" ++
1111+
MOTDFormat ++
10881112
"~n Doc guides: https://rabbitmq.com/documentation.html"
10891113
"~n Support: https://rabbitmq.com/contact.html"
10901114
"~n Tutorials: https://rabbitmq.com/getstarted.html"
@@ -1094,9 +1118,24 @@ print_banner() ->
10941118
"~n Config file(s): ~ts" ++ CfgFmt ++ "~n"
10951119
"~n Starting broker...",
10961120
[Product, Version, ?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE] ++
1121+
MOTDArgs ++
10971122
LogLocations ++
10981123
CfgLocations).
10991124

1125+
log_motd() ->
1126+
case motd() of
1127+
undefined ->
1128+
ok;
1129+
MOTD ->
1130+
Lines = string:split(MOTD, "\n", all),
1131+
Padded = [case Line of
1132+
<<>> -> "\n";
1133+
_ -> [" ", Line, "\n"]
1134+
end
1135+
|| Line <- Lines],
1136+
rabbit_log:info("~n~ts", [string:trim(Padded, trailing, [$\r, $\n])])
1137+
end.
1138+
11001139
log_banner() ->
11011140
{FirstLog, OtherLogs} = case log_locations() of
11021141
[Head | Tail] ->
@@ -1236,6 +1275,114 @@ validate_msg_store_io_batch_size_and_credit_disc_bound(CreditDiscBound,
12361275
end
12371276
end.
12381277

1278+
-spec product_name() -> string().
1279+
1280+
product_name() ->
1281+
#{name := ProductName} = product_info(),
1282+
ProductName.
1283+
1284+
-spec product_version() -> string().
1285+
1286+
product_version() ->
1287+
#{version := ProductVersion} = product_info(),
1288+
ProductVersion.
1289+
1290+
-spec product_info() -> #{name := string(),
1291+
version := string()}.
1292+
1293+
product_info() ->
1294+
PTKey = {?MODULE, product},
1295+
try
1296+
%% The value is cached the first time to avoid calling the
1297+
%% application master many times just for that.
1298+
persistent_term:get(PTKey)
1299+
catch
1300+
error:badarg ->
1301+
{NameFromEnv, VersionFromEnv} =
1302+
case rabbit_env:get_context() of
1303+
#{product_name := NFE,
1304+
product_version := VFE} -> {NFE, VFE};
1305+
_ -> {undefined, undefined}
1306+
end,
1307+
1308+
Info =
1309+
if
1310+
NameFromEnv =/= undefined andalso
1311+
VersionFromEnv =/= undefined ->
1312+
#{name => NameFromEnv,
1313+
version => VersionFromEnv};
1314+
true ->
1315+
_ = application:load(rabbit),
1316+
Name = case NameFromEnv of
1317+
undefined ->
1318+
string_from_app_env(
1319+
product_name,
1320+
base_product_name());
1321+
_ ->
1322+
NameFromEnv
1323+
end,
1324+
Version = case VersionFromEnv of
1325+
undefined ->
1326+
string_from_app_env(
1327+
product_version,
1328+
base_product_version());
1329+
_ ->
1330+
VersionFromEnv
1331+
end,
1332+
#{name => Name,
1333+
version => Version}
1334+
end,
1335+
persistent_term:put(PTKey, Info),
1336+
Info
1337+
end.
1338+
1339+
string_from_app_env(Key, Default) ->
1340+
case application:get_env(rabbit, Key) of
1341+
{ok, Val} ->
1342+
case io_lib:deep_char_list(Val) of
1343+
true ->
1344+
case lists:flatten(Val) of
1345+
"" -> Default;
1346+
String -> String
1347+
end;
1348+
false ->
1349+
Default
1350+
end;
1351+
undefined ->
1352+
Default
1353+
end.
1354+
1355+
base_product_name() ->
1356+
%% This function assumes the `rabbit` application was loaded in
1357+
%% product_info().
1358+
{ok, Product} = application:get_key(rabbit, description),
1359+
Product.
1360+
1361+
base_product_version() ->
1362+
%% This function assumes the `rabbit` application was loaded in
1363+
%% product_info().
1364+
rabbit_misc:version().
1365+
1366+
motd_file() ->
1367+
case rabbit_env:get_context() of
1368+
#{motd_file := File} ->
1369+
File;
1370+
_ ->
1371+
_ = application:load(rabbit),
1372+
string_from_app_env(motd_file, undefined)
1373+
end.
1374+
1375+
motd() ->
1376+
case motd_file() of
1377+
undefined ->
1378+
undefined;
1379+
File ->
1380+
case file:read_file(File) of
1381+
{ok, MOTD} -> string:trim(MOTD, trailing, [$\r,$\n]);
1382+
{error, _} -> undefined
1383+
end
1384+
end.
1385+
12391386
home_dir() ->
12401387
case init:get_argument(home) of
12411388
{ok, [[Home]]} -> Home;

0 commit comments

Comments
 (0)