Use external configuration for the log to monitor

This commit is contained in:
Fabio Salvini 2017-07-01 19:57:03 +02:00
parent fa1bfa9d25
commit 1e26998649
9 changed files with 164 additions and 64 deletions

View File

@ -1,7 +1,6 @@
TODO TODO
===== =====
- Allow to enable / disabled logfiles. - gatherer.erl:29 Error on ++.
- Limit number of emails that can be sent in a period of time. - Limit number of emails that can be sent in a period of time.
- Store the logfiles in a configuration file.
- gen_fsm for gatherer? - gen_fsm for gatherer?

View File

@ -3,8 +3,8 @@
-include_lib("mnesia_tables.hrl"). -include_lib("mnesia_tables.hrl").
-export([create_group/2, monitor_log/3, unmonitor_log/1]). -export([status/0]).
-export([logfiles/0]). -export([reload/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]).
@ -17,6 +17,7 @@ start_link() ->
init([]) -> init([]) ->
register(config, self()), register(config, self()),
Statuses = ets:new(log_statuses, []), Statuses = ets:new(log_statuses, []),
%% TODO: reload?
mnesia:activity( mnesia:activity(
transaction, transaction,
fun() -> fun() ->
@ -49,50 +50,22 @@ handle_info(_Msg, State) ->
handle_cast(_Msg, State) -> handle_cast(_Msg, State) ->
{noreply, State}. {noreply, State}.
handle_call({create_group, Name, EmailReceivers}, _From, State) -> handle_call({reload}, _From, State = #state{statuses = Statuses}) ->
mnesia:activity( {ok, File} = application:get_env(log_monitor, logfiles_config),
transaction, {ok, Terms} = file:consult(File),
fun() -> MonitoredLogs = proplists:get_value(monitored_logs, Terms),
case mnesia:read(log_monitor_group, Name) of Groups = [#log_monitor_group{name = Name, email_receivers = EmailReceivers} || {{group, Name}, {email_receivers, EmailReceivers}, _} <- MonitoredLogs],
[] -> Logfiles = utils:flatten([[#log_monitor_file{file = F, error_regex = ErrorRegex, group = Name} || {{file, F}, {error_regex, ErrorRegex}} <- Logfiles]
mnesia:write(#log_monitor_group{name = Name, email_receivers = EmailReceivers}), || {{group, Name}, {email_receivers, _}, {logfiles, Logfiles}} <- MonitoredLogs]),
{reply, ok, State}; GroupsPartitions = compare_groups(Groups),
_ -> {reply, {error, "Duplicate"}, State} manage_deleted_groups(proplists:get_value(deleted, GroupsPartitions)),
end manage_existing_groups(proplists:get_value(existing, GroupsPartitions)),
end); manage_new_groups(proplists:get_value(new, GroupsPartitions)),
handle_call({monitor, Group, File, ErrorRegex}, _From, State) -> LogfilesPartitions = compare_logfiles(Logfiles),
mnesia:activity( manage_deleted_logfiles(proplists:get_value(deleted, LogfilesPartitions), Statuses),
transaction, manage_existing_logfiles(proplists:get_value(existing, LogfilesPartitions)),
fun() -> manage_new_logfiles(proplists:get_value(new, LogfilesPartitions), Statuses),
case mnesia:read(log_monitor_group, Group) of {reply, ok, State};
[{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]),
{reply, ok, State};
_ -> {reply, {error, "Duplicate"}, State}
end;
[] -> {reply, {error, "Unknown group"}, State}
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),
logfiles_sup:remove_child(File),
{reply, ok, State};
_ -> {reply, {error, "File not found"}, State}
end
end);
handle_call({get_statuses}, _From, State = #state{statuses = Statuses}) -> handle_call({get_statuses}, _From, State = #state{statuses = Statuses}) ->
{reply, ets:tab2list(Statuses), State}. {reply, ets:tab2list(Statuses), State}.
@ -102,14 +75,115 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
{ok, State}. {ok, State}.
create_group(Name, EmailReceivers) -> status() ->
gen_server:call(config, {create_group, Name, EmailReceivers}).
monitor_log(Group, File, ErrorRegex) ->
gen_server:call(config, {monitor, Group, File, ErrorRegex}).
unmonitor_log(File) ->
gen_server:call(config, {unmonitor, File}).
logfiles() ->
gen_server:call(config, {get_statuses}). gen_server:call(config, {get_statuses}).
reload() ->
gen_server:call(config, {reload}).
compare_groups(Groups) ->
Old = list_groups(),
Deleted = lists:filter(fun(Name) -> not lists:any(fun(#log_monitor_group{name = N, email_receivers = _}) -> N == Name end, Groups) end, Old),
Existing = lists:filter(fun(#log_monitor_group{name = Name, email_receivers = _}) -> lists:member(Name, Old) end, Groups),
New = lists:filter(fun(#log_monitor_group{name = Name, email_receivers = _}) -> not lists:member(Name, Old) end, Groups),
[
{deleted, Deleted},
{existing, Existing},
{new, New}
].
manage_deleted_groups(Groups) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(Name, _Acc) ->
mnesia:delete({log_monitor_group, Name})
end, [], Groups)
end).
manage_existing_groups(Groups) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(Group, _Acc) ->
mnesia:write(Group)
end, [], Groups)
end).
manage_new_groups(Groups) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(Group, _Acc) ->
mnesia:write(Group)
end, [], Groups)
end).
list_groups() ->
mnesia:activity(
transaction,
fun() ->
mnesia:foldl(
fun(#log_monitor_group{name = Name, email_receivers = _}, Acc) ->
[Name | Acc]
end, [], log_monitor_group)
end).
compare_logfiles(Logfiles) ->
Old= list_logfiles(),
Deleted = lists:filter(fun(File) -> not lists:any(fun(#log_monitor_file{file = F, error_regex = _, group = _}) -> F == File end, Logfiles) end, Old),
Existing = lists:filter(fun(#log_monitor_file{file = File, error_regex = _, group = _}) -> lists:member(File, Old) end, Logfiles),
New = lists:filter(fun(#log_monitor_file{file = File, error_regex = _, group = _}) -> not lists:member(File, Old) end, Logfiles),
[
{deleted, Deleted},
{existing, Existing},
{new, New}
].
manage_deleted_logfiles(Logfiles, Statuses) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(File, _Acc) ->
logfiles_sup:remove_child(File),
mnesia:delete({log_monitor_file, File}),
ets:delete(Statuses, File)
end, [], Logfiles)
end).
manage_existing_logfiles(Logfiles) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(Logfile = #log_monitor_file{file = File, error_regex = ErrorRegex, group = _}, _Acc) ->
mnesia:write(Logfile),
case mnesia:read(log_monitor_file, File) of
[#log_monitor_file{file = File, error_regex = ErrorRegex, group = _}] -> ok;
_ ->
%% The error regex has changed
logfiles_sup:remove_child(File),
logfiles_sup:add_child([File, ErrorRegex])
end
end, [], Logfiles)
end).
manage_new_logfiles(Logfiles, Statuses) ->
mnesia:activity(
transaction,
fun() ->
lists:foldl(fun(Logfile = #log_monitor_file{file = File, error_regex = ErrorRegex, group = _}, _Acc) ->
mnesia:write(Logfile),
ets:insert(Statuses, {File, inactive}),
logfiles_sup:add_child([File, ErrorRegex])
end, [], Logfiles)
end).
list_logfiles() ->
mnesia:activity(
transaction,
fun() ->
mnesia:foldl(
fun(#log_monitor_file{file = File, error_regex = _, group = _}, Acc) ->
[File | Acc]
end, [], log_monitor_file)
end).

View File

@ -7,7 +7,9 @@
[kernel, [kernel,
stdlib, stdlib,
gen_smtp, gen_smtp,
mnesia mnesia,
%% Observer
observer, wx, runtime_tools
]}, ]},
{env,[]}, {env,[]},
{modules, []}, {modules, []},

View File

@ -90,7 +90,7 @@ send_email(File, Text) ->
Connection Connection
) )
catch catch
_Throw -> error:_ ->
ok ok
end. end.
@ -107,10 +107,11 @@ receivers(File) ->
transaction, transaction,
fun() -> fun() ->
case mnesia:read(log_monitor_file, File) of case mnesia:read(log_monitor_file, File) of
[{log_monitor_file, File, _, _, Group}] -> [{log_monitor_file, File, _, Group}] ->
case mnesia:read(log_monitor_group, Group) of case mnesia:read(log_monitor_group, Group) of
[{log_monitor_group, Group, EmailReceivers}] -> [{log_monitor_group, Group, EmailReceivers}] ->
EmailReceivers EmailReceivers;
_ -> throw(file_group_not_found)
end; end;
_ -> throw(file_not_found) _ -> throw(file_not_found)
end end

View File

@ -3,7 +3,7 @@
%% Mnesia tables %% Mnesia tables
-record(log_monitor_group, {name, email_receivers=[]}). -record(log_monitor_group, {name, email_receivers=[]}).
-record(log_monitor_file, {file, error_regex, status, group}). -record(log_monitor_file, {file, error_regex, group}).
-record(log_monitor_error, {id, file, text}). -record(log_monitor_error, {id, file, text}).
-endif. -endif.

View File

@ -0,0 +1,10 @@
-module(utils).
-export([flatten/1]).
flatten(X) -> flatten(X,[]).
flatten([],Acc) -> Acc;
flatten([[]|T],Acc) -> flatten(T, Acc);
flatten([[_|_]=H|T],Acc) -> flatten(T, flatten(H,Acc));
flatten([H|T],Acc) -> flatten(T,Acc++[H]) .

View File

@ -16,7 +16,8 @@
{password, ""}] {password, ""}]
} }
] ]
} },
{logfiles_config, "/home/fsalvini/gitRepos/log_monitor/config/logfiles.config"}
] ]
}, },
%% Directory where the application data is stored. %% Directory where the application data is stored.

12
config/logfiles.config Normal file
View File

@ -0,0 +1,12 @@
{monitored_logs, [
{
{group, "Test"},
{email_receivers, ["user@example.com"]},
{logfiles, [
{
{file, "/tmp/lines.log"},
{error_regex, "ERROR"}
}
]}
}
]}.

1
config/rebar.lock Normal file
View File

@ -0,0 +1 @@
[].