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.

162 lines
6.0 KiB

преди 12 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 14 години
преди 13 години
преди 13 години
преди 13 години
  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. -ifdef(TEST).
  22. -include_lib("eunit/include/eunit.hrl").
  23. -endif.
  24. %% callbacks
  25. -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
  26. code_change/3]).
  27. -export([start_link/3, start/3]).
  28. -record(state, {
  29. module,
  30. config,
  31. event
  32. }).
  33. start_link(Event, Module, Config) ->
  34. gen_server:start_link(?MODULE, [Event, Module, Config], []).
  35. start(Event, Module, Config) ->
  36. gen_server:start(?MODULE, [Event, Module, Config], []).
  37. init([Event, Module, Config]) ->
  38. install_handler(Event, Module, Config),
  39. {ok, #state{event=Event, module=Module, config=Config}}.
  40. handle_call(_Call, _From, State) ->
  41. {reply, ok, State}.
  42. handle_cast(_Request, State) ->
  43. {noreply, State}.
  44. handle_info({gen_event_EXIT, Module, normal}, #state{module=Module} = State) ->
  45. {stop, normal, State};
  46. handle_info({gen_event_EXIT, Module, shutdown}, #state{module=Module} = State) ->
  47. {stop, normal, State};
  48. handle_info({gen_event_EXIT, Module, Reason}, #state{module=Module,
  49. config=Config, event=Event} = State) ->
  50. case lager:log(error, self(), "Lager event handler ~p exited with reason ~s",
  51. [Module, error_logger_lager_h:format_reason(Reason)]) of
  52. ok ->
  53. install_handler(Event, Module, Config);
  54. {error, _} ->
  55. %% lager is not working, so installing a handler won't work
  56. ok
  57. end,
  58. {noreply, State};
  59. handle_info(reinstall_handler, #state{module=Module, config=Config, event=Event} = State) ->
  60. install_handler(Event, Module, Config),
  61. {noreply, State};
  62. handle_info(_Info, State) ->
  63. {noreply, State}.
  64. terminate(_Reason, _State) ->
  65. ok.
  66. code_change(_OldVsn, State, _Extra) ->
  67. {ok, State}.
  68. %% internal
  69. install_handler(Event, Module, Config) ->
  70. case gen_event:add_sup_handler(Event, Module, Config) of
  71. ok ->
  72. _ = lager:log(debug, self(), "Lager installed handler ~p into ~p", [Module, Event]),
  73. lager:update_loglevel_config(),
  74. ok;
  75. Error ->
  76. %% try to reinstall it later
  77. _ = lager:log(error, self(), "Lager failed to install handler ~p into"
  78. " ~p, retrying later : ~p", [Module, Event, Error]),
  79. erlang:send_after(5000, self(), reinstall_handler),
  80. ok
  81. end.
  82. -ifdef(TEST).
  83. from_now(Seconds) ->
  84. {Mega, Secs, Micro} = os:timestamp(),
  85. {Mega, Secs + Seconds, Micro}.
  86. reinstall_on_initial_failure_test_() ->
  87. {timeout, 60000,
  88. [
  89. fun() ->
  90. error_logger:tty(false),
  91. application:load(lager),
  92. application:set_env(lager, handlers, [{lager_test_backend, info}, {lager_crash_backend, [from_now(2), undefined]}]),
  93. application:set_env(lager, error_logger_redirect, false),
  94. application:unset_env(lager, crash_log),
  95. application:start(lager),
  96. try
  97. ?assertEqual(1, lager_test_backend:count()),
  98. {_Level, _Time, Message, _Metadata} = lager_test_backend:pop(),
  99. ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Message)),
  100. ?assertEqual(0, lager_test_backend:count()),
  101. timer:sleep(6000),
  102. ?assertEqual(0, lager_test_backend:count()),
  103. ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event)))
  104. after
  105. application:stop(lager),
  106. error_logger:tty(true)
  107. end
  108. end
  109. ]
  110. }.
  111. reinstall_on_runtime_failure_test_() ->
  112. {timeout, 60000,
  113. [
  114. fun() ->
  115. error_logger:tty(false),
  116. application:load(lager),
  117. application:set_env(lager, handlers, [{lager_test_backend, info}, {lager_crash_backend, [undefined, from_now(5)]}]),
  118. application:set_env(lager, error_logger_redirect, false),
  119. application:unset_env(lager, crash_log),
  120. application:start(lager),
  121. try
  122. ?assertEqual(0, lager_test_backend:count()),
  123. ?assert(lists:member(lager_crash_backend, gen_event:which_handlers(lager_event))),
  124. timer:sleep(6000),
  125. ?assertEqual(2, lager_test_backend:count()),
  126. {_Level, _Time, Message, _Metadata} = lager_test_backend:pop(),
  127. ?assertEqual("Lager event handler lager_crash_backend exited with reason crash", lists:flatten(Message)),
  128. {_Level2, _Time2, Message2, _Metadata} = lager_test_backend:pop(),
  129. ?assertMatch("Lager failed to install handler lager_crash_backend into lager_event, retrying later :"++_, lists:flatten(Message2)),
  130. ?assertEqual(false, lists:member(lager_crash_backend, gen_event:which_handlers(lager_event)))
  131. after
  132. application:stop(lager),
  133. error_logger:tty(true)
  134. end
  135. end
  136. ]
  137. }.
  138. -endif.