diff options
Diffstat (limited to 'deps/rabbit_common/src/rabbit_error_logger_handler.erl')
-rw-r--r-- | deps/rabbit_common/src/rabbit_error_logger_handler.erl | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/deps/rabbit_common/src/rabbit_error_logger_handler.erl b/deps/rabbit_common/src/rabbit_error_logger_handler.erl new file mode 100644 index 0000000000..714790a449 --- /dev/null +++ b/deps/rabbit_common/src/rabbit_error_logger_handler.erl @@ -0,0 +1,169 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. +%% + +-module(rabbit_error_logger_handler). + +-behaviour(gen_event). + +%% API +-export([start_link/0, add_handler/0]). + +%% gen_event callbacks +-export([init/1, handle_event/2, handle_call/2, + handle_info/2, terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, {report = []}). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @doc +%% Creates an event manager +%% +%% @spec start_link() -> {ok, Pid} | {error, Error} +%% @end +%%-------------------------------------------------------------------- +start_link() -> + gen_event:start_link({local, ?SERVER}). + +%%-------------------------------------------------------------------- +%% @doc +%% Adds an event handler +%% +%% @spec add_handler() -> ok | {'EXIT', Reason} | term() +%% @end +%%-------------------------------------------------------------------- +add_handler() -> + gen_event:add_handler(?SERVER, ?MODULE, []). + +%%%=================================================================== +%%% gen_event callbacks +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Whenever a new event handler is added to an event manager, +%% this function is called to initialize the event handler. +%% +%% @spec init(Args) -> {ok, State} +%% @end +%%-------------------------------------------------------------------- +init([]) -> + {ok, #state{}}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Whenever an event manager receives an event sent using +%% gen_event:notify/2 or gen_event:sync_notify/2, this function is +%% called for each installed event handler to handle the event. +%% +%% @spec handle_event(Event, State) -> +%% {ok, State} | +%% {swap_handler, Args1, State1, Mod2, Args2} | +%% remove_handler +%% @end +%%-------------------------------------------------------------------- + +handle_event({info_report, _Gleader, {_Pid, _Type, + {net_kernel, {'EXIT', _, Reason}}}}, + #state{report = Report} = State) -> + NewReport = case format(Reason) of + [] -> Report; + Formatted -> [Formatted | Report] + end, + {ok, State#state{report = NewReport}}; +handle_event(_Event, State) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Whenever an event manager receives a request sent using +%% gen_event:call/3,4, this function is called for the specified +%% event handler to handle the request. +%% +%% @spec handle_call(Request, State) -> +%% {ok, Reply, State} | +%% {swap_handler, Reply, Args1, State1, Mod2, Args2} | +%% {remove_handler, Reply} +%% @end +%%-------------------------------------------------------------------- +handle_call(get_connection_report, State) -> + {ok, lists:reverse(State#state.report), State#state{report = []}}; +handle_call(_Request, State) -> + Reply = ok, + {ok, Reply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% This function is called for each installed event handler when +%% an event manager receives any other message than an event or a +%% synchronous request (or a system message). +%% +%% @spec handle_info(Info, State) -> +%% {ok, State} | +%% {swap_handler, Args1, State1, Mod2, Args2} | +%% remove_handler +%% @end +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Whenever an event handler is deleted from an event manager, this +%% function is called. It should be the opposite of Module:init/1 and +%% do any necessary cleaning up. +%% +%% @spec terminate(Reason, State) -> void() +%% @end +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Convert process state when code is changed +%% +%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState} +%% @end +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +format({check_dflag_xnc_failed, _What}) -> + {" * Remote node uses an incompatible Erlang version ~n", []}; +format({recv_challenge_failed, no_node, Node}) -> + {" * Node name (or hostname) mismatch: node ~p believes its node name is not ~p but something else.~n" + " All nodes and CLI tools must refer to node ~p using the same name the node itself uses (see its logs to find out what it is)~n", + [Node, Node, Node]}; +format({recv_challenge_failed, Error}) -> + {" * Distribution failed unexpectedly while waiting for challenge: ~p~n", [Error]}; +format({recv_challenge_ack_failed, bad_cookie}) -> + {" * Authentication failed (rejected by the local node), please check the Erlang cookie~n", []}; +format({recv_challenge_ack_failed, {error, closed}}) -> + {" * Authentication failed (rejected by the remote node), please check the Erlang cookie~n", []}; +format({recv_status_failed, not_allowed}) -> + {" * This node is not on the list of nodes authorised by remote node (see net_kernel:allow/1)~n", []}; +format({recv_status_failed, {error, closed}}) -> + {" * Remote host closed TCP connection before completing authentication. Is the Erlang distribution using TLS?~n", []}; +format(setup_timer_timeout) -> + {" * TCP connection to remote host has timed out. Is the Erlang distribution using TLS?~n", []}; +format(_) -> + []. |