Use external configuration for the log to monitor
This commit is contained in:
parent
fa1bfa9d25
commit
1e26998649
3
TODO.md
3
TODO.md
|
@ -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?
|
||||||
|
|
|
@ -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]),
|
||||||
|
GroupsPartitions = compare_groups(Groups),
|
||||||
|
manage_deleted_groups(proplists:get_value(deleted, GroupsPartitions)),
|
||||||
|
manage_existing_groups(proplists:get_value(existing, GroupsPartitions)),
|
||||||
|
manage_new_groups(proplists:get_value(new, GroupsPartitions)),
|
||||||
|
LogfilesPartitions = compare_logfiles(Logfiles),
|
||||||
|
manage_deleted_logfiles(proplists:get_value(deleted, LogfilesPartitions), Statuses),
|
||||||
|
manage_existing_logfiles(proplists:get_value(existing, LogfilesPartitions)),
|
||||||
|
manage_new_logfiles(proplists:get_value(new, LogfilesPartitions), Statuses),
|
||||||
{reply, ok, State};
|
{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]),
|
|
||||||
{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).
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
[kernel,
|
[kernel,
|
||||||
stdlib,
|
stdlib,
|
||||||
gen_smtp,
|
gen_smtp,
|
||||||
mnesia
|
mnesia,
|
||||||
|
%% Observer
|
||||||
|
observer, wx, runtime_tools
|
||||||
]},
|
]},
|
||||||
{env,[]},
|
{env,[]},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
10
apps/log_monitor/src/utils.erl
Normal file
10
apps/log_monitor/src/utils.erl
Normal 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]) .
|
|
@ -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
12
config/logfiles.config
Normal 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
1
config/rebar.lock
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[].
|
Loading…
Reference in New Issue
Block a user