Skip to content

Commit d3ad28a

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_file` variable. The default motd file is `/etc/rabbitmq/motd` on Unix and `%APPDATA%\RabbitMQ\motd.txt` on Windows. 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 [#170054940]
1 parent a5f8ac4 commit d3ad28a

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

@@ -375,8 +380,9 @@ run_prelaunch_second_phase() ->
375380
start_it(StartType) ->
376381
case spawn_boot_marker() of
377382
{ok, Marker} ->
383+
Product = product_name(),
378384
T0 = erlang:timestamp(),
379-
rabbit_log:info("RabbitMQ is asked to start...", []),
385+
rabbit_log:info("~s is asked to start...", [Product]),
380386
try
381387
{ok, _} = application:ensure_all_started(rabbitmq_prelaunch,
382388
StartType),
@@ -386,8 +392,8 @@ start_it(StartType) ->
386392

387393
T1 = erlang:timestamp(),
388394
rabbit_log_prelaunch:debug(
389-
"Time to start RabbitMQ: ~p µs",
390-
[timer:now_diff(T1, T0)]),
395+
"Time to start ~s: ~p µs",
396+
[Product, timer:now_diff(T1, T0)]),
391397
stop_boot_marker(Marker),
392398
ok
393399
catch
@@ -435,10 +441,12 @@ stop() ->
435441
ok ->
436442
case rabbit_boot_state:get() of
437443
ready ->
438-
rabbit_log:info("RabbitMQ is asked to stop..."),
444+
Product = product_name(),
445+
rabbit_log:info("~s is asked to stop...", [Product]),
439446
do_stop(),
440447
rabbit_log:info(
441-
"Successfully stopped RabbitMQ and its dependencies"),
448+
"Successfully stopped ~s and its dependencies",
449+
[Product]),
442450
ok;
443451
stopped ->
444452
ok
@@ -462,7 +470,9 @@ stop_and_halt() ->
462470
try
463471
stop()
464472
catch Type:Reason ->
465-
rabbit_log:error("Error trying to stop RabbitMQ: ~p:~p", [Type, Reason]),
473+
rabbit_log:error(
474+
"Error trying to stop ~s: ~p:~p",
475+
[product_name(), Type, Reason]),
466476
error({Type, Reason})
467477
after
468478
%% Enclose all the logging in the try block.
@@ -518,9 +528,9 @@ stop_apps([]) ->
518528
ok;
519529
stop_apps(Apps) ->
520530
rabbit_log:info(
521-
lists:flatten(["Stopping RabbitMQ applications and their dependencies in the following order:~n",
531+
lists:flatten(["Stopping ~s applications and their dependencies in the following order:~n",
522532
[" ~p~n" || _ <- Apps]]),
523-
lists:reverse(Apps)),
533+
[product_name() | lists:reverse(Apps)]),
524534
ok = app_utils:stop_applications(
525535
Apps, handle_app_error(error_during_shutdown)),
526536
case lists:member(rabbit, Apps) of
@@ -663,7 +673,7 @@ maybe_print_boot_progress(true, IterationsLeft) ->
663673
{memory, any()}].
664674

665675
status() ->
666-
{ok, Version} = application:get_key(rabbit, vsn),
676+
Version = product_version(),
667677
S1 = [{pid, list_to_integer(os:getpid())},
668678
%% The timeout value used is twice that of gen_server:call/2.
669679
{running_applications, rabbit_misc:which_applications()},
@@ -816,9 +826,10 @@ start(normal, []) ->
816826
try
817827
run_prelaunch_second_phase(),
818828

819-
rabbit_log:info("~n Starting RabbitMQ ~s on Erlang ~s~n ~s~n ~s~n",
820-
[rabbit_misc:version(), rabbit_misc:otp_release(),
829+
rabbit_log:info("~n Starting ~s ~s on Erlang ~s~n ~s~n ~s~n",
830+
[product_name(), product_version(), rabbit_misc:otp_release(),
821831
?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE]),
832+
log_motd(),
822833
{ok, SupPid} = rabbit_sup:start_link(),
823834

824835
%% Compatibility with older RabbitMQ versions + required by
@@ -904,7 +915,7 @@ do_run_postlaunch_phase() ->
904915
end
905916
end, Plugins),
906917

907-
rabbit_log_prelaunch:debug("Marking RabbitMQ as running"),
918+
rabbit_log_prelaunch:debug("Marking ~s as running", [product_name()]),
908919
rabbit_boot_state:set(ready),
909920

910921
ok = rabbit_lager:broker_is_started(),
@@ -1058,8 +1069,8 @@ log_broker_started(Plugins) ->
10581069
"~n " ?BG32_START " " ?C_END " ~s").
10591070

10601071
print_banner() ->
1061-
{ok, Product} = application:get_key(description),
1062-
{ok, Version} = application:get_key(vsn),
1072+
Product = product_name(),
1073+
Version = product_version(),
10631074
LineListFormatter = fun (Placeholder, [_ | Tail] = LL) ->
10641075
LF = lists:flatten([Placeholder || _ <- lists:seq(1, length(Tail))]),
10651076
{LF, LL};
@@ -1082,8 +1093,21 @@ print_banner() ->
10821093
%% padded list lines
10831094
{LogFmt, LogLocations} = LineListFormatter("~n ~ts", log_locations()),
10841095
{CfgFmt, CfgLocations} = LineListFormatter("~n ~ts", config_locations()),
1096+
{MOTDFormat, MOTDArgs} = case motd() of
1097+
undefined ->
1098+
{"", []};
1099+
MOTD ->
1100+
Lines = string:split(MOTD, "\n", all),
1101+
Padded = [case Line of
1102+
<<>> -> "\n";
1103+
_ -> [" ", Line, "\n"]
1104+
end
1105+
|| Line <- Lines],
1106+
{"~n~ts", [Padded]}
1107+
end,
10851108
io:format(Logo ++
1086-
"~n"
1109+
"~n" ++
1110+
MOTDFormat ++
10871111
"~n Doc guides: https://rabbitmq.com/documentation.html"
10881112
"~n Support: https://rabbitmq.com/contact.html"
10891113
"~n Tutorials: https://rabbitmq.com/getstarted.html"
@@ -1093,9 +1117,24 @@ print_banner() ->
10931117
"~n Config file(s): ~ts" ++ CfgFmt ++ "~n"
10941118
"~n Starting broker...",
10951119
[Product, Version, ?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE] ++
1120+
MOTDArgs ++
10961121
LogLocations ++
10971122
CfgLocations).
10981123

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

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

0 commit comments

Comments
 (0)