summaryrefslogtreecommitdiff
path: root/src/couch_log/src/couch_log_server.erl
blob: be44af8ffe0c465a84b1c70b9882e584b5237fe8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.

-module(couch_log_server).
-behavior(gen_server).


-export([
    start_link/0,
    reconfigure/0,
    log/1
]).

-export([
   init/1,
   terminate/2,
   handle_call/3,
   handle_cast/2,
   handle_info/2,
   code_change/3
]).


-include("couch_log.hrl").


-record(st, {
    writer
}).


-ifdef(TEST).
-define(SEND(Entry), gen_server:call(?MODULE, {log, Entry})).
-else.
-define(SEND(Entry), gen_server:cast(?MODULE, {log, Entry})).
-endif.


start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).


reconfigure() ->
    gen_server:call(?MODULE, reconfigure).


log(Entry) ->
    ?SEND(Entry).


init(_) ->
    process_flag(trap_exit, true),
    {ok, #st{
        writer = couch_log_writer:init()
    }}.


terminate(Reason, St) ->
    ok = couch_log_writer:terminate(Reason, St#st.writer).


handle_call(reconfigure, _From, St) ->
    ok = couch_log_writer:terminate(reconfiguring, St#st.writer),
    {reply, ok, St#st{
        writer = couch_log_writer:init()
    }};

handle_call({log, Entry}, _From, St) ->
    % We re-check if we should log here in case an operator
    % adjusted the log level and then realized it was a bad
    % idea because it filled our message queue.
    case couch_log_util:should_log(Entry) of
        true ->
            NewWriter = couch_log_writer:write(Entry, St#st.writer),
            {reply, ok, St#st{writer = NewWriter}};
        false ->
            {reply, ok, St}
    end;

handle_call(Ignore, From, St) ->
    Args = [?MODULE, Ignore],
    Entry = couch_log_formatter:format(error, ?MODULE, "~s ignored ~p", Args),
    handle_call({log, Entry}, From, St).


handle_cast(Msg, St) ->
    {reply, ok, NewSt} = handle_call(Msg, nil, St),
    {noreply, NewSt}.


handle_info(Msg, St) ->
    {reply, ok, NewSt} = handle_call(Msg, nil, St),
    {noreply, NewSt}.


code_change(_Vsn, St, _Extra) ->
    {ok, St}.