Use Mnesia to store monitored log files
This commit is contained in:
parent
af8fad987d
commit
9b13aa6cbc
|
@ -1,31 +1,43 @@
|
||||||
-module(config).
|
-module(config).
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
-export([monitor_log/2, unmonitor_log/1]).
|
-export([create_group/2, monitor_log/3, unmonitor_log/1]).
|
||||||
-export([logfiles/0]).
|
-export([logfiles/0]).
|
||||||
-export([start_link/0, init/1, terminate/2]).
|
-export([start_link/0, init/1, terminate/2]).
|
||||||
-export([handle_info/2, handle_cast/2, handle_call/3]).
|
-export([handle_info/2, handle_cast/2, handle_call/3]).
|
||||||
-export([code_change/3]).
|
-export([code_change/3]).
|
||||||
|
|
||||||
|
-record(state, {statuses}).
|
||||||
|
|
||||||
|
%% Mnesia tables
|
||||||
|
-record(log_monitor_group, {name, email_receivers=[]}).
|
||||||
|
-record(log_monitor_file, {file, error_regex, status, group}).
|
||||||
|
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link(?MODULE, [], []).
|
gen_server:start_link(?MODULE, [], []).
|
||||||
|
|
||||||
init([]) ->
|
init([]) ->
|
||||||
register(config, self()),
|
register(config, self()),
|
||||||
{ok, Storage} = application:get_env(log_monitor, storage),
|
|
||||||
{ok, Logfiles} = dets:open_file(Storage, [{auto_save, 1000}]),
|
|
||||||
Statuses = ets:new(log_statuses, []),
|
Statuses = ets:new(log_statuses, []),
|
||||||
lists:foreach(fun({File, ErrorRegex}) ->
|
start_mnesia(),
|
||||||
ets:insert(Statuses, {File, disabled}),
|
mnesia:activity(
|
||||||
logfiles_sup:add_child([File, ErrorRegex])
|
transaction,
|
||||||
end, dets:foldl(fun(X, L) -> [X|L] end, [], Logfiles)),
|
fun() ->
|
||||||
{ok, [Logfiles, Statuses]}.
|
mnesia:foldl(
|
||||||
|
fun(#log_monitor_file{file = File, error_regex = ErrorRegex}, _Acc) ->
|
||||||
|
ets:insert(Statuses, {File, inactive}),
|
||||||
|
logfiles_sup:add_child([File, ErrorRegex]),
|
||||||
|
ok
|
||||||
|
end, [], log_monitor_file)
|
||||||
|
end),
|
||||||
|
{ok, #state{statuses = Statuses}}.
|
||||||
|
|
||||||
handle_info({watcher_init, File}, State = [_Logfiles, Statuses]) ->
|
handle_info({watcher_init, File}, State = #state{statuses = Statuses}) ->
|
||||||
ets:insert(Statuses, {File, enabled}),
|
ets:insert(Statuses, {File, active}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({watcher_terminate, File}, State = [_Logfiles, Statuses]) ->
|
handle_info({watcher_terminate, File}, State = #state{statuses = Statuses}) ->
|
||||||
ets:insert(Statuses, {File, disabled}),
|
%% TODO: do not update it if not present
|
||||||
|
ets:insert(Statuses, {File, inactive}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Msg, State) ->
|
handle_info(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
@ -33,21 +45,51 @@ handle_info(_Msg, State) ->
|
||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_call({monitor, File, ErrorRegex}, _From, State = [Logfiles, Statuses]) ->
|
handle_call({create_group, Name, EmailReceivers}, _From, State) ->
|
||||||
case dets:lookup(Logfiles, File) of
|
mnesia:activity(
|
||||||
|
transaction,
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read(log_monitor_group, Name) of
|
||||||
[] ->
|
[] ->
|
||||||
dets:insert(Logfiles, {File, ErrorRegex}),
|
mnesia:write(#log_monitor_group{name = Name, email_receivers = EmailReceivers}),
|
||||||
ets:insert(Statuses, {File, disabled}),
|
{reply, ok, State};
|
||||||
|
_ -> {reply, {error, "Duplicate"}, State}
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
handle_call({monitor, Group, File, ErrorRegex}, _From, State) ->
|
||||||
|
mnesia:activity(
|
||||||
|
transaction,
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read(log_monitor_group, Group) of
|
||||||
|
[{log_monitor_group, Group, _}] ->
|
||||||
|
case mnesia:read(log_monitor_file, File) of
|
||||||
|
[] ->
|
||||||
|
mnesia:write(#log_monitor_file{
|
||||||
|
file = File,
|
||||||
|
error_regex = ErrorRegex,
|
||||||
|
group = Group,
|
||||||
|
status = enabled}),
|
||||||
logfiles_sup:add_child([File, ErrorRegex]),
|
logfiles_sup:add_child([File, ErrorRegex]),
|
||||||
{reply, ok, State};
|
{reply, ok, State};
|
||||||
_ -> {reply, duplicate, State}
|
_ -> {reply, {error, "Duplicate"}, State}
|
||||||
end;
|
end;
|
||||||
handle_call({unmonitor, File}, _From, State = [Logfiles, Statuses]) ->
|
[] -> {reply, {error, "Unknown group"}, State}
|
||||||
logfiles_sup:remove_child(File),
|
end
|
||||||
|
end);
|
||||||
|
handle_call({unmonitor, File}, _From, State = #state{statuses = Statuses}) ->
|
||||||
|
mnesia:activity(
|
||||||
|
transaction,
|
||||||
|
fun() ->
|
||||||
|
case mnesia:read(log_monitor_file, File) of
|
||||||
|
[{log_monitor_file, File, _, _, _}] ->
|
||||||
|
mnesia:delete({log_monitor_file, File}),
|
||||||
ets:delete(Statuses, File),
|
ets:delete(Statuses, File),
|
||||||
dets:delete(Logfiles, File),
|
logfiles_sup:remove_child(File),
|
||||||
{reply, ok, State};
|
{reply, ok, State};
|
||||||
handle_call({get_statuses}, _From, State = [_Logfiles, Statuses]) ->
|
_ -> {reply, {error, "File not found"}, State}
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
handle_call({get_statuses}, _From, State = #state{statuses = Statuses}) ->
|
||||||
{reply, ets:tab2list(Statuses), State}.
|
{reply, ets:tab2list(Statuses), State}.
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
terminate(_Reason, _State) ->
|
||||||
|
@ -56,11 +98,33 @@ terminate(_Reason, _State) ->
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
monitor_log(File, ErrorRegex) ->
|
create_group(Name, EmailReceivers) ->
|
||||||
gen_server:call(config, {monitor, File, ErrorRegex}).
|
gen_server:call(config, {create_group, Name, EmailReceivers}).
|
||||||
|
|
||||||
|
monitor_log(Group, File, ErrorRegex) ->
|
||||||
|
gen_server:call(config, {monitor, Group, File, ErrorRegex}).
|
||||||
|
|
||||||
unmonitor_log(File) ->
|
unmonitor_log(File) ->
|
||||||
gen_server:call(config, {unmonitor, File}).
|
gen_server:call(config, {unmonitor, File}).
|
||||||
|
|
||||||
logfiles() ->
|
logfiles() ->
|
||||||
gen_server:call(config, {get_statuses}).
|
gen_server:call(config, {get_statuses}).
|
||||||
|
|
||||||
|
start_mnesia() ->
|
||||||
|
Nodes = [node()],
|
||||||
|
%% Stop Mnesia if is running, cannot create schema otherwise.
|
||||||
|
mnesia:stop(),
|
||||||
|
mnesia:create_schema(Nodes),
|
||||||
|
mnesia:start(),
|
||||||
|
mnesia:create_table(log_monitor_group,
|
||||||
|
[
|
||||||
|
{attributes, record_info(fields, log_monitor_group)},
|
||||||
|
{disc_copies, Nodes}
|
||||||
|
]),
|
||||||
|
mnesia:create_table(log_monitor_file,
|
||||||
|
[
|
||||||
|
{attributes, record_info(fields, log_monitor_file)},
|
||||||
|
{index, [#log_monitor_file.group]},
|
||||||
|
{disc_copies, Nodes}
|
||||||
|
]),
|
||||||
|
ok = mnesia:wait_for_tables([log_monitor_group, log_monitor_file], 30000).
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
{applications,
|
{applications,
|
||||||
[kernel,
|
[kernel,
|
||||||
stdlib,
|
stdlib,
|
||||||
gen_smtp
|
gen_smtp,
|
||||||
|
mnesia
|
||||||
]},
|
]},
|
||||||
{env,[]},
|
{env,[]},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
[
|
[
|
||||||
{ log_monitor,
|
{ log_monitor,
|
||||||
[
|
[
|
||||||
%% File where the list of monitored log files is stored.
|
|
||||||
%% WARNING: If you leave it inside /tmp, every time the node is restarted the log files will be lost.
|
|
||||||
{storage, "/tmp/logfiles"},
|
|
||||||
{email_config,
|
{email_config,
|
||||||
[
|
[
|
||||||
{sender, "log@monitor.com"},
|
{sender, "log@monitor.com"},
|
||||||
|
@ -16,5 +13,12 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
%% Directory where the application data is stored.
|
||||||
|
%% WARNING: If you leave it inside /tmp, every time the node is restarted the
|
||||||
|
%% application will reset.
|
||||||
|
{ mnesia , [
|
||||||
|
{dir, "/tmp/mnesia"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
].
|
].
|
||||||
|
|
Loading…
Reference in New Issue
Block a user