You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
6.4 KiB

преди 12 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 11 години
преди 13 години
преди 11 години
  1. %% Copyright (c) 2011-2012 Basho Technologies, Inc. All Rights Reserved.
  2. %%
  3. %% This file is provided to you under the Apache License,
  4. %% Version 2.0 (the "License"); you may not use this file
  5. %% except in compliance with the License. You may obtain
  6. %% a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing,
  11. %% software distributed under the License is distributed on an
  12. %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. %% KIND, either express or implied. See the License for the
  14. %% specific language governing permissions and limitations
  15. %% under the License.
  16. %% @doc A process that does a gen_event:add_sup_handler and attempts to re-add
  17. %% event handlers when they exit.
  18. %% @private
  19. -module(lager_handler_watcher).
  20. -behaviour(gen_server).
  21. -include("lager.hrl").
  22. -ifdef(TEST).
  23. -include_lib("eunit/include/eunit.hrl").
  24. -endif.
  25. %% callbacks
  26. -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
  27. code_change/3]).
  28. -export([start_link/3, start/3]).
  29. -record(state, {
  30. module :: atom(),
  31. config :: any(),
  32. event :: pid() | atom()
  33. }).
  34. start_link(Event, Module, Config) ->
  35. gen_server:start_link(?MODULE, [Event, Module, Config], []).
  36. start(Event, Module, Config) ->
  37. gen_server:start(?MODULE, [Event, Module, Config], []).
  38. init([Event, Module, Config]) ->
  39. install_handler(Event, Module, Config),
  40. {ok, #state{event=Event, module=Module, config=Config}}.
  41. handle_call(_Call, _From, State) ->
  42. {reply, ok, State}.
  43. handle_cast(_Request, State) ->
  44. {noreply, State}.
  45. handle_info({gen_event_EXIT, Module, normal}, #state{module=Module} = State) ->
  46. {stop, normal, State};
  47. handle_info({gen_event_EXIT, Module, shutdown}, #state{module=Module} = State) ->
  48. {stop, normal, State};
  49. handle_info({gen_event_EXIT, Module, Reason}, #state{module=Module,
  50. config=Config, event=Event} = State) ->
  51. case lager:log(error, self(), "Lager event handler ~p exited with reason ~s",
  52. [Module, error_logger_lager_h:format_reason(Reason)]) of
  53. ok ->
  54. install_handler(Event, Module, Config);
  55. {error, _} ->
  56. %% lager is not working, so installing a handler won't work
  57. ok
  58. end,
  59. {noreply, State};
  60. handle_info(reinstall_handler, #state{module=Module, config=Config, event=Event} = State) ->
  61. install_handler(Event, Module, Config),
  62. {noreply, State};
  63. handle_info(stop, State) ->
  64. {stop, normal, State};
  65. handle_info(_Info, State) ->
  66. {noreply, State}.
  67. terminate(_Reason, _State) ->
  68. ok.
  69. code_change(_OldVsn, State, _Extra) ->
  70. {ok, State}.
  71. %% internal
  72. install_handler(Event, Module, Config) ->
  73. case gen_event:add_sup_handler(Event, Module, Config) of
  74. ok ->
  75. ?INT_LOG(debug, "Lager installed handler ~p into ~p", [Module, Event]),
  76. lager:update_loglevel_config(),
  77. ok;
  78. {error, {fatal, Reason}} ->
  79. ?INT_LOG(error, "Lager fatally failed to install handler ~p into"
  80. " ~p, NOT retrying: ~p", [Module, Event, Reason]),
  81. %% tell ourselves to stop
  82. self() ! stop,
  83. ok;
  84. Error ->
  85. %% try to reinstall it later
  86. ?INT_LOG(error, "Lager failed to install handler ~p into"
  87. " ~p, retrying later : ~p", [Module, Event, Error]),
  88. erlang:send_after(5000, self(), reinstall_handler),
  89. ok
  90. end.
  91. -ifdef(TEST).
  92. from_now(Seconds) ->
  93. {Mega, Secs, Micro} = os:timestamp(),
  94. {Mega, Secs + Seconds, Micro}.
  95. reinstall_on_initial_failure_test_() ->
  96. {timeout, 60000,
  97. [
  98. fun() ->
  99. error_logger:tty(false),
  100. application:load(lager),
  101. application:set_env(lager, handlers, [{lager_test_backend, info}, {lager_crash_backend, [from_now(2), undefined]}]),
  102. application:set_env(lager, error_logger_redirect, false),
  103. application:unset_env(lager, crash_log),
  104. lager:start(),
  105. try
  106. ?assertEqual(1, lager_test_backend:count()),
  107. {_Level, _Time, Message, _Metadata} = lager_test_backend:pop(),
  108. ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Message)),
  109. ?assertEqual(0, lager_test_backend:count()),
  110. timer:sleep(6000),
  111. ?assertEqual(0, lager_test_backend:count()),
  112. ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event)))
  113. after
  114. application:stop(lager),
  115. application:stop(goldrush),
  116. error_logger:tty(true)
  117. end
  118. end
  119. ]
  120. }.
  121. reinstall_on_runtime_failure_test_() ->
  122. {timeout, 60000,
  123. [
  124. fun() ->
  125. error_logger:tty(false),
  126. application:load(lager),
  127. application:set_env(lager, handlers, [{lager_test_backend, info}, {lager_crash_backend, [undefined, from_now(5)]}]),
  128. application:set_env(lager, error_logger_redirect, false),
  129. application:unset_env(lager, crash_log),
  130. lager:start(),
  131. try
  132. ?assertEqual(0, lager_test_backend:count()),
  133. ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event))),
  134. timer:sleep(6000),
  135. ?assertEqual(2, lager_test_backend:count()),
  136. {_Severity, _Date, Msg, _Metadata} = lager_test_backend:pop(),
  137. ?assertEqual("Lager event handler lager_crash_backend exited with reason crash", lists:flatten(Msg)),
  138. {_Severity2, _Date2, Msg2, _Metadata2} = lager_test_backend:pop(),
  139. ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Msg2)),
  140. ?assertEqual(false, lists:member(lager_crash_backend, gen_event:which_handlers(lager_event)))
  141. after
  142. application:stop(lager),
  143. application:stop(goldrush),
  144. error_logger:tty(true)
  145. end
  146. end
  147. ]
  148. }.
  149. -endif.