diff options
author | Hubert Plociniczak <hubert@lshift.net> | 2008-08-27 11:18:53 +0100 |
---|---|---|
committer | Hubert Plociniczak <hubert@lshift.net> | 2008-08-27 11:18:53 +0100 |
commit | 47ff9bab0753cd0f601cbe9bd18a2017fcdbf8c3 (patch) | |
tree | ded564973eb3ab38b3a8a2c8b9d59655d3d8f04e | |
parent | b96ea77fb2e2993ba53368021a5f6f1434cc16d3 (diff) | |
parent | 816763d0da3e3f27dd80a7dd0ccfbae70496cbb8 (diff) | |
download | rabbitmq-server-47ff9bab0753cd0f601cbe9bd18a2017fcdbf8c3.tar.gz |
Merged bug19200 into bug19193
-rw-r--r-- | docs/rabbitmqctl.pod | 15 | ||||
-rw-r--r-- | src/rabbit.erl | 92 | ||||
-rw-r--r-- | src/rabbit_control.erl | 12 | ||||
-rw-r--r-- | src/rabbit_error_logger_file_h.erl | 66 | ||||
-rw-r--r-- | src/rabbit_misc.erl | 21 | ||||
-rw-r--r-- | src/rabbit_sasl_report_file_h.erl | 78 |
6 files changed, 219 insertions, 65 deletions
diff --git a/docs/rabbitmqctl.pod b/docs/rabbitmqctl.pod index eb1750d0..927fd8af 100644 --- a/docs/rabbitmqctl.pod +++ b/docs/rabbitmqctl.pod @@ -66,12 +66,13 @@ force_reset It should only be used as a last resort if the database or cluster configuration has been corrupted. -reopen_logs [suffix] - instruct the RabbitMQ node to close and reopen the log files. - When the I<suffix> value is provided, the RabbitMQ broker will - attempt to append the current contents of the log file to the file - with name composed of the original name and the suffix. It will - create a new file if such a file does not already exist. +rotate_logs [suffix] + instruct the RabbitMQ node to rotate the log files. The RabbitMQ + broker will attempt to append the current contents of the log file + to the file with name composed of the original name and the suffix. + It will create a new file if such a file does not already exist. + When no I<suffix> is specified, the log file is simply reopened; + no rotation takes place. This command might be helpful when you are e.g. writing your own logrotate script and you do not want to restart the RabbitMQ node. @@ -131,7 +132,7 @@ default Erlang node: Append current logs' content to the files with ".1" suffix and reopen them: - rabbitmqctl reopen_logs .1 + rabbitmqctl rotate_logs .1 =head1 SEE ALSO diff --git a/src/rabbit.erl b/src/rabbit.erl index 3de40378..d4b21c43 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -27,7 +27,7 @@ -behaviour(application). --export([start/0, stop/0, stop_and_halt/0, status/0, reopen_logs/0, reopen_logs/1]). +-export([start/0, stop/0, stop_and_halt/0, status/0, rotate_logs/1]). -export([start/2, stop/1]). @@ -39,7 +39,6 @@ -include("rabbit_framing.hrl"). -include("rabbit.hrl"). --include_lib("kernel/include/file.hrl"). -define(APPS, [os_mon, mnesia, rabbit]). @@ -50,8 +49,7 @@ -spec(start/0 :: () -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(stop_and_halt/0 :: () -> 'ok'). --spec(reopen_logs/0 :: () -> 'ok'). --spec(reopen_logs/1 :: name() -> 'ok' | {'error', 'cannot_append_logfile'}). +-spec(rotate_logs/1 :: name() -> 'ok' | {'error', any()}). -spec(status/0 :: () -> [{running_applications, [{atom(), string(), string()}]} | {nodes, [node()]} | @@ -88,16 +86,11 @@ status() -> [{running_applications, application:which_applications()}] ++ rabbit_mnesia:status(). -reopen_logs() -> - ok = reopen_logs(error_log_location(), [], main_log), - ok = reopen_logs(sasl_log_location(), [], sasl_log). - -reopen_logs(Suffix) -> - LSuffix = binary_to_list(Suffix), - case reopen_logs(error_log_location(), LSuffix, main_log) of - ok -> reopen_logs(sasl_log_location(), LSuffix, sasl_log); - Error -> Error - end. +rotate_logs(BinarySuffix) -> + Suffix = binary_to_list(BinarySuffix), + log_rotation_result( + rotate_logs(error_log_location(wrapper), Suffix, rabbit_error_logger_file_h), + rotate_logs(sasl_log_location(), Suffix, rabbit_sasl_report_file_h)). %%-------------------------------------------------------------------- @@ -176,7 +169,15 @@ start(normal, []) -> {ok, DefaultVHost} = application:get_env(default_vhost), ok = error_logger:add_report_handler( rabbit_error_logger, [DefaultVHost]), - ok = start_builtin_amq_applications() + ok = start_builtin_amq_applications(), + %% Swap default handlers with rabbit wrappers + %% to simplify swapping of log handlers later + ok = rotate_logs(error_log_location(default), "", + error_logger_file_h, + rabbit_error_logger_file_h), + ok = rotate_logs(sasl_log_location(), "", + sasl_report_file_h, + rabbit_sasl_report_file_h) end}, {"TCP listeners", fun () -> @@ -208,7 +209,7 @@ print_banner() -> ?PROTOCOL_VERSION_MAJOR, ?PROTOCOL_VERSION_MINOR, ?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE]), io:format("Logging to ~p~nSASL logging to ~p~n~n", - [error_log_location(), sasl_log_location()]). + [error_log_location(default), sasl_log_location()]). start_child(Mod) -> {ok,_} = supervisor:start_child(rabbit_sup, @@ -260,10 +261,13 @@ ensure_working_log_config() -> _Filename -> ok end. -error_log_location() -> - case error_logger:logfile(filename) of - {error,no_log_file} -> tty; - File -> File +error_log_location(Type) -> + case case Type of + default -> error_logger:logfile(filename); + wrapper -> gen_event:call(error_logger, rabbit_error_logger_file_h, filename) + end of + {error, no_log_file} -> tty; + File -> File end. sasl_log_location() -> @@ -275,41 +279,25 @@ sasl_log_location() -> _ -> undefined end. -reopen_logs(File, Suffix,Swap) -> +rotate_logs(File, Suffix, Handler) -> + rotate_logs(File, Suffix, Handler, Handler). + +rotate_logs(File, Suffix, OldHandler, NewHandler) -> case File of undefined -> ok; tty -> ok; - _ -> case append_to_log_file(File, Suffix) of - omit -> swap_handler(Swap, File); - ok -> swap_handler(Swap, File); - Error -> Error - end + _ -> gen_event:swap_handler( + error_logger, + {OldHandler, swap}, + {NewHandler, {File, Suffix}}) end. -swap_handler(main_log, File) -> - error_logger:swap_handler({logfile, File}), - error_logger:delete_report_handler(error_logger_file_h), - ok; -swap_handler(sasl_log, File ) -> - gen_event:swap_handler(error_logger, - {error_logger, swap}, - {sasl_report_file_h, File}), - gen_event:add_handler(error_logger, error_logger, []), - error_logger:delete_report_handler(sasl_report_file_h), +log_rotation_result({error, MainLogError}, {error, SaslLogError}) -> + {error, {{cannot_rotate_main_logs, MainLogError}, + {cannot_rotate_sasl_logs, SaslLogError}}}; +log_rotation_result({error, MainLogError}, ok) -> + {error, {cannot_rotate_main_logs, MainLogError}}; +log_rotation_result(ok, {error, SaslLogError}) -> + {error, {cannot_rotate_sasl_logs, SaslLogError}}; +log_rotation_result(ok, ok) -> ok. - -append_to_log_file(File, Suffix) -> - case file:read_file_info(File) of - {ok, FInfo} -> append_file(File, FInfo#file_info.size, Suffix); - {error, _} -> ok - end. - -append_file(_, 0, _) -> - omit; -append_file(_, _, []) -> - omit; -append_file(File, _, Suffix) -> - case file:read_file(File) of - {ok, Data} -> file:write_file([File, Suffix], Data, [append]); - {error, _} -> {error, cannot_append_logfile} - end. diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl index 4c1b92bb..bc588279 100644 --- a/src/rabbit_control.erl +++ b/src/rabbit_control.erl @@ -73,7 +73,7 @@ Available commands: force_reset cluster <ClusterNode> ... status - reopen_logs [Suffix] + rotate_logs [Suffix] add_user <UserName> <Password> delete_user <UserName> @@ -130,12 +130,12 @@ action(status, Node, []) -> io:format("~n~p~n", [Res]), ok; -action(reopen_logs, Node, []) -> +action(rotate_logs, Node, []) -> io:format("Reopening logs for node ~p ...", [Node]), - call(Node, {rabbit, reopen_logs, []}); -action(reopen_logs, Node, Args = [Suffix]) -> - io:format("Moving logs to files with suffix ~p and reopening logs ...", [Suffix]), - call(Node, {rabbit, reopen_logs, Args}); + call(Node, {rabbit, rotate_logs, [""]}); +action(rotate_logs, Node, Args = [Suffix]) -> + io:format("Rotating logs to files with suffix ~p ...", [Suffix]), + call(Node, {rabbit, rotate_logs, Args}); action(add_user, Node, Args = [Username, _Password]) -> io:format("Creating user ~p ...", [Username]), diff --git a/src/rabbit_error_logger_file_h.erl b/src/rabbit_error_logger_file_h.erl new file mode 100644 index 00000000..20c6b778 --- /dev/null +++ b/src/rabbit_error_logger_file_h.erl @@ -0,0 +1,66 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developers of the Original Code are LShift Ltd., +%% Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd. +%% +%% Portions created by LShift Ltd., Cohesive Financial Technologies +%% LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007-2008 +%% LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit +%% Technologies Ltd.; +%% +%% All Rights Reserved. +%% +%% Contributor(s): ______________________________________. +%% + +-module(rabbit_error_logger_file_h). + +-behaviour(gen_event). + +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). + +%% rabbit_error_logger_file_h is a wrapper around error_logger_file_h +%% module because the original's init/1 does not match properly +%% with the result of closing the old handler when swapping handlers. +%% The first init/1 additionally allows for simple log rotation +%% when suffix is not "" + +%% Used only when swapping handlers in log rotation +init({{File, Suffix}, []}) -> + case rabbit_misc:append_file(File, Suffix) of + ok -> error_logger_file_h:init(File); + Error -> Error + end; +%% Used only when swapping handlers without performing +%% log rotation +init({File, []}) -> + error_logger_file_h:init(File); +init({_File, _Type} = FileInfo) -> + error_logger_file_h:init(FileInfo); +init(File) -> + error_logger_file_h:init(File). + +handle_event(Event, State) -> + error_logger_file_h:handle_event(Event, State). + +handle_info(Event, State) -> + error_logger_file_h:handle_info(Event, State). + +handle_call(Event, State) -> + error_logger_file_h:handle_call(Event, State). + +terminate(Reason, State) -> + error_logger_file_h:terminate(Reason, State). + +code_change(OldVsn, State, Extra) -> + error_logger_file_h:code_change(OldVsn, State, Extra). diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 11ab0caf..d7d1ff14 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -26,6 +26,7 @@ -module(rabbit_misc). -include("rabbit.hrl"). -include("rabbit_framing.hrl"). +-include_lib("kernel/include/file.hrl"). -export([method_record_type/1, polite_pause/0, polite_pause/1]). -export([die/1, frame_error/2, protocol_error/3, protocol_error/4]). @@ -41,6 +42,7 @@ -export([intersperse/2, upmap/2, map_in_order/2]). -export([guid/0, string_guid/1, binstring_guid/1]). -export([dirty_read_all/1, dirty_foreach_key/2, dirty_dump_log/1]). +-export([append_file/2]). -import(mnesia). -import(lists). @@ -92,6 +94,7 @@ -spec(dirty_foreach_key/2 :: (fun ((any()) -> any()), atom()) -> 'ok' | 'aborted'). -spec(dirty_dump_log/1 :: (string()) -> 'ok' | {'error', any()}). +-spec(append_file/2 :: (string(), string()) -> 'ok' | {'error', any()}). -endif. @@ -333,3 +336,21 @@ dirty_dump_log1(LH, {K, Terms}) -> dirty_dump_log1(LH, {K, Terms, BadBytes}) -> io:format("Bad Chunk, ~p: ~p~n", [BadBytes, Terms]), dirty_dump_log1(LH, disk_log:chunk(LH, K)). + + +append_file(File, Suffix) -> + case catch file:read_file_info(File) of + {ok, FInfo} -> append_file(File, FInfo#file_info.size, Suffix); + {error, enoent} -> ok; + Error -> Error + end. + +append_file(_, 0, _) -> + ok; +append_file(_, _, "") -> + ok; +append_file(File, _, Suffix) -> + case file:read_file(File) of + {ok, Data} -> file:write_file([File, Suffix], Data, [append]); + Error -> Error + end. diff --git a/src/rabbit_sasl_report_file_h.erl b/src/rabbit_sasl_report_file_h.erl new file mode 100644 index 00000000..eb5bf091 --- /dev/null +++ b/src/rabbit_sasl_report_file_h.erl @@ -0,0 +1,78 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developers of the Original Code are LShift Ltd., +%% Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd. +%% +%% Portions created by LShift Ltd., Cohesive Financial Technologies +%% LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007-2008 +%% LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit +%% Technologies Ltd.; +%% +%% All Rights Reserved. +%% +%% Contributor(s): ______________________________________. +%% + +-module(rabbit_sasl_report_file_h). + +-behaviour(gen_event). + +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). + +%% rabbit_sasl_report_file_h is a wrapper around sasl_report_file_h +%% module because the original's init/1 does not match properly +%% with the result of closing the old handler when swapping handlers. +%% The first init/1 additionally allows for simple log rotation +%% when suffix is not "" + +%% Used only when swapping handlers and performing +%% log rotation +init({{File, Suffix}, []}) -> + case rabbit_misc:append_file(File, Suffix) of + ok -> sasl_report_file_h:init({File, sasl_error_logger_type()}); + Error -> Error + end; +%% Used only when swapping handlers without +%% doing any log rotation +init({File, []}) -> + sasl_report_file_h:init({File, sasl_error_logger_type()}); +init({_File, _Type} = FileInfo) -> + sasl_report_file_h:init(FileInfo); +init(File) -> + sasl_report_file_h:init({File, sasl_error_logger_type()}). + +handle_event(Event, State) -> + sasl_report_file_h:handle_event(Event, State). + +handle_info(Event, State) -> + sasl_report_file_h:handle_info(Event, State). + +handle_call(Event, State) -> + sasl_report_file_h:handle_call(Event, State). + +terminate(Reason, State) -> + sasl_report_file_h:terminate(Reason, State). + +code_change(OldVsn, State, Extra) -> + sasl_report_file_h:code_change(OldVsn, State, Extra). + +%%---------------------------------------------------------------------- + +sasl_error_logger_type() -> + case application:get_env(sasl, errlog_type) of + {ok, error} -> error; + {ok, progress} -> progress; + {ok, all} -> all; + {ok, Bad} -> throw({error, {wrong_errlog_type, Bad}}); + _ -> all + end. |