30
30
31
31
-export ([start /2 , stop /1 , prep_stop /1 ]).
32
32
-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 ]).
33
38
-export ([log_locations /0 , config_files /0 ]). % % for testing and mgmt-agent
34
39
-export ([is_booted /1 , is_booted /0 , is_booting /1 , is_booting /0 ]).
35
40
@@ -435,10 +440,12 @@ stop() ->
435
440
ok ->
436
441
case rabbit_boot_state :get () of
437
442
ready ->
438
- rabbit_log :info (" RabbitMQ is asked to stop..." ),
443
+ Product = product_name (),
444
+ rabbit_log :info (" ~s is asked to stop..." , [Product ]),
439
445
do_stop (),
440
446
rabbit_log :info (
441
- " Successfully stopped RabbitMQ and its dependencies" ),
447
+ " Successfully stopped ~s and its dependencies" ,
448
+ [Product ]),
442
449
ok ;
443
450
stopped ->
444
451
ok
@@ -462,7 +469,9 @@ stop_and_halt() ->
462
469
try
463
470
stop ()
464
471
catch Type :Reason ->
465
- rabbit_log :error (" Error trying to stop RabbitMQ: ~p :~p " , [Type , Reason ]),
472
+ rabbit_log :error (
473
+ " Error trying to stop ~s : ~p :~p " ,
474
+ [product_name (), Type , Reason ]),
466
475
error ({Type , Reason })
467
476
after
468
477
% % Enclose all the logging in the try block.
@@ -518,9 +527,9 @@ stop_apps([]) ->
518
527
ok ;
519
528
stop_apps (Apps ) ->
520
529
rabbit_log :info (
521
- lists :flatten ([" Stopping RabbitMQ applications and their dependencies in the following order:~n " ,
530
+ lists :flatten ([" Stopping ~s applications and their dependencies in the following order:~n " ,
522
531
[" ~p~n " || _ <- Apps ]]),
523
- lists :reverse (Apps )),
532
+ [ product_name () | lists :reverse (Apps )] ),
524
533
ok = app_utils :stop_applications (
525
534
Apps , handle_app_error (error_during_shutdown )),
526
535
case lists :member (rabbit , Apps ) of
@@ -663,7 +672,7 @@ maybe_print_boot_progress(true, IterationsLeft) ->
663
672
{memory , any ()}].
664
673
665
674
status () ->
666
- { ok , Version } = application : get_key ( rabbit , vsn ),
675
+ Version = product_version ( ),
667
676
S1 = [{pid , list_to_integer (os :getpid ())},
668
677
% % The timeout value used is twice that of gen_server:call/2.
669
678
{running_applications , rabbit_misc :which_applications ()},
@@ -816,9 +825,10 @@ start(normal, []) ->
816
825
try
817
826
run_prelaunch_second_phase (),
818
827
819
- rabbit_log :info (" ~n Starting RabbitMQ ~s on Erlang ~s~n ~s~n ~s~n " ,
820
- [rabbit_misc : version (), rabbit_misc :otp_release (),
828
+ rabbit_log :info (" ~n Starting ~s ~s on Erlang ~s~n ~s~n ~s~n " ,
829
+ [product_name (), product_version (), rabbit_misc :otp_release (),
821
830
? COPYRIGHT_MESSAGE , ? INFORMATION_MESSAGE ]),
831
+ log_motd (),
822
832
{ok , SupPid } = rabbit_sup :start_link (),
823
833
824
834
% % Compatibility with older RabbitMQ versions + required by
@@ -904,7 +914,7 @@ do_run_postlaunch_phase() ->
904
914
end
905
915
end , Plugins ),
906
916
907
- rabbit_log_prelaunch :debug (" Marking RabbitMQ as running" ),
917
+ rabbit_log_prelaunch :debug (" Marking ~s as running" , [ product_name ()] ),
908
918
rabbit_boot_state :set (ready ),
909
919
910
920
ok = rabbit_lager :broker_is_started (),
@@ -1058,8 +1068,8 @@ log_broker_started(Plugins) ->
1058
1068
" ~n " ? BG32_START " " ? C_END " ~s " ).
1059
1069
1060
1070
print_banner () ->
1061
- { ok , Product } = application : get_key ( description ),
1062
- { ok , Version } = application : get_key ( vsn ),
1071
+ Product = product_name ( ),
1072
+ Version = product_version ( ),
1063
1073
LineListFormatter = fun (Placeholder , [_ | Tail ] = LL ) ->
1064
1074
LF = lists :flatten ([Placeholder || _ <- lists :seq (1 , length (Tail ))]),
1065
1075
{LF , LL };
@@ -1082,8 +1092,21 @@ print_banner() ->
1082
1092
% % padded list lines
1083
1093
{LogFmt , LogLocations } = LineListFormatter (" ~n ~ts " , log_locations ()),
1084
1094
{CfgFmt , CfgLocations } = LineListFormatter (" ~n ~ts " , config_locations ()),
1095
+ {MOTDFormat , MOTDArgs } = case motd () of
1096
+ undefined ->
1097
+ {" " , []};
1098
+ MOTD ->
1099
+ Lines = string :split (MOTD , " \n " , all ),
1100
+ Padded = [case Line of
1101
+ <<>> -> " \n " ;
1102
+ _ -> [" " , Line , " \n " ]
1103
+ end
1104
+ || Line <- Lines ],
1105
+ {" ~n~ts " , [Padded ]}
1106
+ end ,
1085
1107
io :format (Logo ++
1086
- " ~n "
1108
+ " ~n " ++
1109
+ MOTDFormat ++
1087
1110
" ~n Doc guides: https://rabbitmq.com/documentation.html"
1088
1111
" ~n Support: https://rabbitmq.com/contact.html"
1089
1112
" ~n Tutorials: https://rabbitmq.com/getstarted.html"
@@ -1093,9 +1116,24 @@ print_banner() ->
1093
1116
" ~n Config file(s): ~ts " ++ CfgFmt ++ " ~n "
1094
1117
" ~n Starting broker..." ,
1095
1118
[Product , Version , ? COPYRIGHT_MESSAGE , ? INFORMATION_MESSAGE ] ++
1119
+ MOTDArgs ++
1096
1120
LogLocations ++
1097
1121
CfgLocations ).
1098
1122
1123
+ log_motd () ->
1124
+ case motd () of
1125
+ undefined ->
1126
+ ok ;
1127
+ MOTD ->
1128
+ Lines = string :split (MOTD , " \n " , all ),
1129
+ Padded = [case Line of
1130
+ <<>> -> " \n " ;
1131
+ _ -> [" " , Line , " \n " ]
1132
+ end
1133
+ || Line <- Lines ],
1134
+ rabbit_log :info (" ~n~ts " , [string :trim (Padded , trailing , [$\r , $\n ])])
1135
+ end .
1136
+
1099
1137
log_banner () ->
1100
1138
{FirstLog , OtherLogs } = case log_locations () of
1101
1139
[Head | Tail ] ->
@@ -1235,6 +1273,123 @@ validate_msg_store_io_batch_size_and_credit_disc_bound(CreditDiscBound,
1235
1273
end
1236
1274
end .
1237
1275
1276
+ - spec product_name () -> string ().
1277
+
1278
+ product_name () ->
1279
+ #{name := ProductName } = product_info (),
1280
+ ProductName .
1281
+
1282
+ - spec product_version () -> string ().
1283
+
1284
+ product_version () ->
1285
+ #{version := ProductVersion } = product_info (),
1286
+ ProductVersion .
1287
+
1288
+ - spec product_info () -> #{name := string (),
1289
+ version := string ()}.
1290
+
1291
+ product_info () ->
1292
+ PTKey = {? MODULE , product },
1293
+ try
1294
+ % % The value is cached the first time to avoid calling the
1295
+ % % application master many times just for that.
1296
+ persistent_term :get (PTKey )
1297
+ catch
1298
+ error :badarg ->
1299
+ {NameFromEnv , VersionFromEnv } =
1300
+ case rabbit_env :get_context () of
1301
+ #{product_name := NFE ,
1302
+ product_version := VFE } -> {NFE , VFE };
1303
+ _ -> {undefined , undefined }
1304
+ end ,
1305
+
1306
+ Info =
1307
+ if
1308
+ NameFromEnv =/= undefined andalso
1309
+ VersionFromEnv =/= undefined ->
1310
+ #{name => NameFromEnv ,
1311
+ version => VersionFromEnv };
1312
+ true ->
1313
+ Name = case NameFromEnv of
1314
+ undefined ->
1315
+ string_from_app_env (
1316
+ product_name ,
1317
+ base_product_name ());
1318
+ _ ->
1319
+ NameFromEnv
1320
+ end ,
1321
+ Version = case VersionFromEnv of
1322
+ undefined ->
1323
+ string_from_app_env (
1324
+ product_version ,
1325
+ base_product_version ());
1326
+ _ ->
1327
+ VersionFromEnv
1328
+ end ,
1329
+ #{name => Name ,
1330
+ version => Version }
1331
+ end ,
1332
+ persistent_term :put (PTKey , Info ),
1333
+ Info
1334
+ end .
1335
+
1336
+ string_from_app_env (Key , Default ) ->
1337
+ case application :get_env (rabbit , Key ) of
1338
+ {ok , Val } ->
1339
+ case io_lib :deep_char_list (Val ) of
1340
+ true ->
1341
+ case lists :flatten (Val ) of
1342
+ " " -> Default ;
1343
+ String -> String
1344
+ end ;
1345
+ false ->
1346
+ Default
1347
+ end ;
1348
+ undefined ->
1349
+ Default
1350
+ end .
1351
+
1352
+ base_product_name () ->
1353
+ % % This function assumes the `rabbit` application was loaded in
1354
+ % % product_info().
1355
+ {ok , Product } = application :get_key (rabbit , description ),
1356
+ Product .
1357
+
1358
+ base_product_version () ->
1359
+ % % This function assumes the `rabbit` application was loaded in
1360
+ % % product_info().
1361
+ rabbit_misc :version ().
1362
+
1363
+ motd_file () ->
1364
+ % % Precendence is:
1365
+ % % 1. The environment variable;
1366
+ % % 2. The `motd_file` configuration parameter;
1367
+ % % 3. The default value.
1368
+ Context = rabbit_env :get_context (),
1369
+ case Context of
1370
+ #{motd_file := File ,
1371
+ var_origins := #{motd_file := environment }}
1372
+ when File =/= undefined ->
1373
+ File ;
1374
+ _ ->
1375
+ Default = case Context of
1376
+ #{motd_file := File } -> File ;
1377
+ _ -> undefined
1378
+ end ,
1379
+ string_from_app_env (motd_file , Default )
1380
+ end .
1381
+
1382
+ motd () ->
1383
+ case motd_file () of
1384
+ undefined ->
1385
+ undefined ;
1386
+ File ->
1387
+ case file :read_file (File ) of
1388
+ {ok , MOTD } -> string :trim (MOTD , trailing , [$\r ,$\n ]);
1389
+ {error , _ } -> undefined
1390
+ end
1391
+ end .
1392
+
1238
1393
home_dir () ->
1239
1394
case init :get_argument (home ) of
1240
1395
{ok , [[Home ]]} -> Home ;
0 commit comments