Error regex as external parameter and monitoring
This commit is contained in:
parent
37a16d1924
commit
810b6c0ada
|
@ -1,13 +1,12 @@
|
||||||
-module(config).
|
-module(config).
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
-export([monitor_log/1]).
|
-export([monitor_log/2]).
|
||||||
|
-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]).
|
||||||
|
|
||||||
-define(INTERVAL, 60000). % One minute
|
|
||||||
|
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link(?MODULE, [], []).
|
gen_server:start_link(?MODULE, [], []).
|
||||||
|
|
||||||
|
@ -15,11 +14,14 @@ init([]) ->
|
||||||
register(config, self()),
|
register(config, self()),
|
||||||
{ok, Storage} = application:get_env(log_monitor, storage),
|
{ok, Storage} = application:get_env(log_monitor, storage),
|
||||||
{ok, Logfiles} = dets:open_file(Storage, []),
|
{ok, Logfiles} = dets:open_file(Storage, []),
|
||||||
%% erlang:send_after(?INTERVAL, self(), trigger),
|
Statuses = ets:new(log_statuses, []),
|
||||||
{ok, [Logfiles]}.
|
{ok, [Logfiles, Statuses]}.
|
||||||
|
|
||||||
handle_info(trigger, State) ->
|
handle_info({watcher_init, File}, State = [_Logfiles, Statuses]) ->
|
||||||
erlang:send_after(?INTERVAL, self(), trigger),
|
ets:insert(Statuses, {File, enabled}),
|
||||||
|
{noreply, State};
|
||||||
|
handle_info({watcher_terminate, File}, State = [_Logfiles, Statuses]) ->
|
||||||
|
ets:insert(Statuses, {File, disabled}),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Msg, State) ->
|
handle_info(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
@ -27,14 +29,17 @@ handle_info(_Msg, State) ->
|
||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_call({monitor, File}, _From, [Logfiles]) ->
|
handle_call({monitor, File, ErrorRegex}, _From, State = [Logfiles, Statuses]) ->
|
||||||
case dets:lookup(Logfiles, File) of
|
case dets:lookup(Logfiles, File) of
|
||||||
[] ->
|
[] ->
|
||||||
dets:insert(Logfiles, {File, "ERROR"}),
|
dets:insert(Logfiles, {File, ErrorRegex}),
|
||||||
supervisor:start_child(logfiles_sup, [File]),
|
ets:insert(Statuses, {File, disabled}),
|
||||||
{reply, ok, [Logfiles]};
|
supervisor:start_child(logfiles_sup, [File, ErrorRegex]),
|
||||||
_ -> {reply, duplicate, [Logfiles]}
|
{reply, ok, State};
|
||||||
end.
|
_ -> {reply, duplicate, State}
|
||||||
|
end;
|
||||||
|
handle_call({get_statuses}, _From, State = [_Logfiles, Statuses]) ->
|
||||||
|
{reply, ets:tab2list(Statuses), State}.
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
terminate(_Reason, _State) ->
|
||||||
shutdown.
|
shutdown.
|
||||||
|
@ -42,6 +47,8 @@ terminate(_Reason, _State) ->
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
monitor_log(File) ->
|
monitor_log(File, ErrorRegex) ->
|
||||||
config ! {monitor, File},
|
gen_server:call(config, {monitor, File, ErrorRegex}).
|
||||||
gen_server:call(config, {monitor, File}).
|
|
||||||
|
logfiles() ->
|
||||||
|
gen_server:call(config, {get_statuses}).
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
-module(gatherer).
|
-module(gatherer).
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
-export([start_link/1, init/1, terminate/2]).
|
-export([start_link/2, 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(log, {file, error_regex}).
|
-record(log, {file, error_regex}).
|
||||||
|
|
||||||
%% start_link(File, ErrorRegex) ->
|
start_link(File, ErrorRegex) ->
|
||||||
start_link(File) ->
|
|
||||||
ErrorRegex = "ERROR",
|
|
||||||
gen_server:start_link(?MODULE, [#log{file = File, error_regex = ErrorRegex}], []).
|
gen_server:start_link(?MODULE, [#log{file = File, error_regex = ErrorRegex}], []).
|
||||||
|
|
||||||
init([Log]) ->
|
init([Log]) ->
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
-module(log_sup).
|
-module(log_sup).
|
||||||
-behaviour(supervisor).
|
-behaviour(supervisor).
|
||||||
|
|
||||||
-export([start_link/1]).
|
-export([start_link/2]).
|
||||||
-export([init/1]).
|
-export([init/1]).
|
||||||
|
|
||||||
start_link(File) ->
|
start_link(File, ErrorRegex) ->
|
||||||
supervisor:start_link(?MODULE, [File]).
|
supervisor:start_link(?MODULE, [File, ErrorRegex]).
|
||||||
|
|
||||||
init(File) ->
|
init([File, ErrorRegex]) ->
|
||||||
SupFlags = #{strategy => one_for_one},
|
SupFlags = #{strategy => one_for_one},
|
||||||
ChildSpecs = [#{
|
ChildSpecs = [#{
|
||||||
id => gatherer,
|
id => gatherer,
|
||||||
start => {gatherer, start_link, [File]},
|
start => {gatherer, start_link, [File, ErrorRegex]},
|
||||||
restart => permanent,
|
restart => permanent,
|
||||||
shutdown => 5000
|
shutdown => 5000
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,18 +10,19 @@ start_link(SupPid, File) ->
|
||||||
|
|
||||||
init([SupPid, File]) ->
|
init([SupPid, File]) ->
|
||||||
timer:sleep(1000),
|
timer:sleep(1000),
|
||||||
|
config ! {watcher_init, File},
|
||||||
Cmd = "/usr/bin/tail -n0 --follow=name " ++ File,
|
Cmd = "/usr/bin/tail -n0 --follow=name " ++ File,
|
||||||
Port = open_port({spawn, Cmd}, [stderr_to_stdout, exit_status, binary]),
|
Port = open_port({spawn, Cmd}, [stderr_to_stdout, exit_status, binary]),
|
||||||
{ok, [SupPid, Port]}.
|
{ok, [File, SupPid, Port]}.
|
||||||
|
|
||||||
handle_info(Msg, [SupPid, Port]) ->
|
handle_info(Msg, [File, SupPid, Port]) ->
|
||||||
case Msg of
|
case Msg of
|
||||||
{Port, {data, Text}} ->
|
{Port, {data, Text}} ->
|
||||||
GathererPid = gatherer_pid(SupPid),
|
GathererPid = gatherer_pid(SupPid),
|
||||||
GathererPid ! {log_line, Text},
|
GathererPid ! {log_line, Text},
|
||||||
{noreply, [SupPid, Port]};
|
{noreply, [File, SupPid, Port]};
|
||||||
{Port, {exit_status, _Status}} ->
|
{Port, {exit_status, _Status}} ->
|
||||||
{stop, tail_exit, []}
|
{stop, tail_exit, [File]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
|
@ -30,7 +31,8 @@ handle_cast(_Msg, State) ->
|
||||||
handle_call(_Request, _From, State) ->
|
handle_call(_Request, _From, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
terminate(_Reason, _State) ->
|
terminate(_Reason, [File]) ->
|
||||||
|
config ! {watcher_terminate, File},
|
||||||
shutdown.
|
shutdown.
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
|
Loading…
Reference in New Issue
Block a user