From 2356f4e8c89b61b71d1afd88161b8418a47dde0b Mon Sep 17 00:00:00 2001
From: Alvaro Videla
Date: Mon, 21 Dec 2009 22:42:16 +0800
Subject: Fix minor typo in read_report/1
---
lib/sasl/src/rb.erl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 00d86285e5..84b98537ae 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -415,7 +415,7 @@ read_report(Fd) ->
Ref = make_ref(),
case (catch {Ref,binary_to_term(Bin)}) of
{'EXIT',_} ->
- {error, "Inclomplete erlang term in log"};
+ {error, "Incomplete erlang term in log"};
{Ref,Term} ->
{ok, Term}
end
--
cgit v1.2.3
From 501b9236450bc1f38d3daf9d9f0dc60b72299d6c Mon Sep 17 00:00:00 2001
From: Alvaro Videla
Date: Mon, 21 Dec 2009 22:35:56 +0800
Subject: Modify rb:grep/1 to grep reports using the re module
---
lib/sasl/doc/src/rb.xml | 13 +++++++------
lib/sasl/src/rb.erl | 33 ++++++++++++++++++++++++++-------
2 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index 5b49a7bced..810f7dca6b 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -46,17 +46,18 @@
grep(RegExp)
Search the reports for a regular expression
- RegExp = string()
+ RegExp = string() | {string, Options} | mp(), {mp(), Options}
All reports containing the regular expression RegExp
are printed.
- RegExp is a string containing the regular
- expression. Refer to the module regexp in the STDLIB
- reference manual
- for a definition of valid regular expressions. They are
- essentially the same as the UNIX command egrep.
+
RegExp can be a string containing the regular
+ expression; a tuple with the string and the options for
+ compilation; a compiled regular expression; a compiled
+ regular expression and the options for running it.
+ Refer to the module re and specially the function re:run/3
+ for a definition of valid regular expressions and options.
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 84b98537ae..05f1230dd1 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -90,7 +90,9 @@ help() ->
io:format("rb:list(Type) - list all reports of type Type~n"),
io:format(" currently supported types are:~n"),
print_types(),
- io:format("rb:grep(RegExp) - print reports containing RegExp~n"),
+ io:format("rb:grep(RegExp) - print reports containing RegExp.~n"),
+ io:format(" RegExp must be a valid argument for ~n"),
+ io:format(" the function re:run/2 or re:run/3.~n"),
io:format("rb:rescan() - rescans the report directory with same~n"),
io:format(" options.~n"),
io:format("rb:rescan(Options) - rescans the report directory with new~n"),
@@ -133,7 +135,6 @@ print_types() ->
io:format(" - progress~n"),
io:format(" - error~n").
-
init(Options) ->
process_flag(priority, low),
process_flag(trap_exit, true),
@@ -190,8 +191,13 @@ handle_call(show, _From, State) ->
{reply, ok, State#state{device = NewDevice}};
handle_call({grep, RegExp}, _From, State) ->
#state{dir = Dir, data = Data, device = Device, abort = Abort, log = Log} = State,
- NewDevice = print_grep_reports(Dir, Data, RegExp, Device, Abort, Log),
- {reply, ok, State#state{device = NewDevice}}.
+ try print_grep_reports(Dir, Data, RegExp, Device, Abort, Log) of
+ NewDevice ->
+ {reply, ok, State#state{device = NewDevice}}
+ catch
+ error:Error ->
+ {reply, {error, Error}, State}
+ end.
terminate(_Reason, #state{device = Device}) ->
close_device(Device).
@@ -622,15 +628,15 @@ check_rep(Fd, FilePosition, Device, RegExp, Number, Abort, Log) ->
case read_rep_msg(Fd, FilePosition) of
{Date, Msg} ->
MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
- case regexp:match(MsgStr, RegExp) of
- {match, _, _} ->
+ case run_re(MsgStr, RegExp) of
+ match ->
io:format("Found match in report number ~w~n", [Number]),
case catch rb_format_supp:print(Date, Msg, Device) of
{'EXIT', _} ->
handle_bad_form(Date, Msg, Device, Abort, Log);
_ ->
{proceed,Device}
- end;
+ end;
_ ->
{proceed,Device}
end;
@@ -639,6 +645,19 @@ check_rep(Fd, FilePosition, Device, RegExp, Number, Abort, Log) ->
{proceed,Device}
end.
+run_re(Subject, {Regexp, Options}) ->
+ run_re(Subject, Regexp, Options);
+run_re(Subject, Regexp) ->
+ run_re(Subject, Regexp, []).
+
+run_re(Subject, Regexp, Options) ->
+ case re:run(Subject, Regexp, Options) of
+ nomatch ->
+ nomatch;
+ _ ->
+ match
+ end.
+
read_rep(Fd, FilePosition, Device, Abort, Log) ->
case read_rep_msg(Fd, FilePosition) of
{Date, Msg} ->
--
cgit v1.2.3
From e99ec8e235beb16d35e5a940b814061fb87db989 Mon Sep 17 00:00:00 2001
From: Alvaro Videla
Date: Tue, 22 Dec 2009 22:54:07 +0800
Subject: New rb:filter/1 function to ease report filtering
Currently in the rb module the only way to filter
reports is by using the grep/1 or re/1 functions
that use Regular Expressions.
This new function allow us to specify detailed
filters that will match against our reports.
Since the reports are proplists the filters are
tuples of the form {Key, Value}. If the report
contains that tuple, it will be displayed.
Usage:
1> rb:filter([{"foo", "bar"}, {"abc", "value"}]).
2> rb:filter([{"foo", "bar", no}]).
% excludes reports containing {"foo", "bar"}
3> rb:filter([{"foo", RegExp, re}]).
% the report must contain an element with Key = "foo"
% and Value must match RegExp
---
lib/sasl/doc/src/rb.xml | 26 +++++++++++
lib/sasl/src/rb.erl | 117 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index 810f7dca6b..0b5df29333 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -42,6 +42,32 @@
+
+ filter(Filters)
+ Filter reports and displays them on the screen
+
+ Filters = [filter()]
+ filter() = {Key, Value} | {Key, Value, no} | {Key, RegExp, re} | {Key, RegExp, re, no}
+ Key = term()
+ Value = term()
+ RegExp = string() | {string, Options} | mp(), {mp(), Options}
+
+
+ This function displays the reports that match the provided filters.
+
+ When a filter includes the no atom it will exclude the reports that match
+ that filter.
+
+
+ The reports are matched using the proplists module. The report must be a proplist
+ to be matched against any of the filters().
+
+
+ If the filter is of the form {Key, RegExp, re} the report must contain an element with
+ key = Key and Value must match the RegExp regular expression.
+
+
+
grep(RegExp)
Search the reports for a regular expression
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 05f1230dd1..5167f961ec 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -22,7 +22,7 @@
%% External exports
-export([start/0, start/1, stop/0, rescan/0, rescan/1]).
--export([list/0, list/1, show/0, show/1, grep/1, start_log/1, stop_log/0]).
+-export([list/0, list/1, show/0, show/1, grep/1, filter/1, start_log/1, stop_log/0]).
-export([h/0, help/0]).
%% Internal exports
@@ -73,6 +73,9 @@ show(Type) when is_atom(Type) ->
grep(RegExp) -> gen_server:call(rb_server, {grep, RegExp}, infinity).
+filter(Filters) when is_list(Filters) ->
+ gen_server:call(rb_server, {filter, Filters}, infinity).
+
start_log(FileName) -> gen_server:call(rb_server, {start_log, FileName}).
stop_log() -> gen_server:call(rb_server, stop_log).
@@ -93,6 +96,10 @@ help() ->
io:format("rb:grep(RegExp) - print reports containing RegExp.~n"),
io:format(" RegExp must be a valid argument for ~n"),
io:format(" the function re:run/2 or re:run/3.~n"),
+ io:format("rb:filter(Filters) - print reports matching Filters.~n"),
+ io:format(" reports must be proplists.~n"),
+ io:format(" Filters is a list of tuples of the following form:~n"),
+ print_filters(),
io:format("rb:rescan() - rescans the report directory with same~n"),
io:format(" options.~n"),
io:format("rb:rescan(Options) - rescans the report directory with new~n"),
@@ -135,6 +142,17 @@ print_types() ->
io:format(" - progress~n"),
io:format(" - error~n").
+print_filters() ->
+ io:format(" - {Key, Value}~n"),
+ io:format(" includes report containing {Key, Value}~n"),
+ io:format(" - {Key, Value, no}~n"),
+ io:format(" excludes report containing {Key, Value}~n"),
+ io:format(" - {Key, RegExp, re}~n"),
+ io:format(" RegExp must be a valid argument for ~n"),
+ io:format(" the function re:run/2 or re:run/3.~n"),
+ io:format(" - {Key, RegExp, re, no}~n"),
+ io:format(" excludes report containing {Key, RegExp}~n").
+
init(Options) ->
process_flag(priority, low),
process_flag(trap_exit, true),
@@ -197,7 +215,11 @@ handle_call({grep, RegExp}, _From, State) ->
catch
error:Error ->
{reply, {error, Error}, State}
- end.
+ end;
+handle_call({filter, Filters}, _From, State) ->
+ #state{dir = Dir, data = Data, device = Device, abort = Abort, log = Log} = State,
+ NewDevice = filter_all_reports(Dir, Data, Filters, Device, Abort, Log),
+ {reply, ok, State#state{device = NewDevice}}.
terminate(_Reason, #state{device = Device}) ->
close_device(Device).
@@ -658,6 +680,97 @@ run_re(Subject, Regexp, Options) ->
match
end.
+filter_all_reports(_Dir, [], _Filters, Device, _Abort, _Log) ->
+ Device;
+filter_all_reports(Dir, Data, Filters, Device, Abort, Log) ->
+ {Next,Device1} = filter_report(Dir, Data, Filters, element(1, hd(Data)),
+ Device, Abort, Log),
+ if Next == abort ->
+ Device1;
+ true ->
+ filter_all_reports(Dir, tl(Data), Filters, Device1, Abort, Log)
+ end.
+
+filter_report(Dir, Data, Filters, Number, Device, Abort, Log) ->
+ case find_report(Data, Number) of
+ {Fname, FilePosition} ->
+ FileName = lists:concat([Dir, Fname]),
+ case file:open(FileName, [read]) of
+ {ok, Fd} ->
+ filter_rep(Filters, Fd, FilePosition, Device, Abort, Log);
+ _ ->
+ io:format("rb: can't open file ~p~n", [Fname]),
+ {proceed,Device}
+ end;
+ no_report ->
+ {proceed,Device}
+ end.
+
+filter_rep(Filters, Fd, FilePosition, Device, Abort, Log) ->
+ case read_rep_msg(Fd, FilePosition) of
+ {Date, Msg} ->
+ % io:format("Date: ~p Message: ~p~n", [Date, Msg]),
+ {_D, M} = Msg,
+ {_, _, M2} = M,
+ case M2 of
+ {_, _, Report} ->
+ case filter_report(Filters, Report) of
+ true ->
+ case catch rb_format_supp:print(Date, Msg, Device) of
+ {'EXIT', _} ->
+ handle_bad_form(Date, Msg, Device, Abort, Log);
+ _ ->
+ {proceed,Device}
+ end;
+ _ ->
+ {proceed, Device}
+ end;
+ _ ->
+ {proceed,Device}
+ end;
+ _ ->
+ io:format("rb: Cannot read from file~n"),
+ {proceed,Device}
+ end.
+
+filter_report([], _Msg) ->
+ true;
+filter_report([{Key, Value}|T], Msg) ->
+ case proplists:get_value(Key, Msg) of
+ Value ->
+ filter_report(T, Msg);
+ _ ->
+ false
+ end;
+filter_report([{Key, Value, no}|T], Msg) ->
+ case proplists:get_value(Key, Msg) of
+ Value ->
+ false;
+ _ ->
+ filter_report(T, Msg)
+ end;
+filter_report([{Key, RegExp, re}|T], Msg) ->
+ case proplists:get_value(Key, Msg) of
+ undefined ->
+ false;
+ Value ->
+ case re:run(Value, RegExp) of
+ {match, _} ->
+ filter_report(T, Msg);
+ _ -> false
+ end
+ end;
+filter_report([{Key, RegExp, re, no}|T], Msg) ->
+ case proplists:get_value(Key, Msg) of
+ undefined ->
+ false;
+ Value ->
+ case re:run(Value, RegExp) of
+ {match, _} -> false;
+ _ -> filter_report(T, Msg)
+ end
+ end.
+
read_rep(Fd, FilePosition, Device, Abort, Log) ->
case read_rep_msg(Fd, FilePosition) of
{Date, Msg} ->
--
cgit v1.2.3
From 242c70ed5f0e2b84e9608bace183052e745614ed Mon Sep 17 00:00:00 2001
From: Alvaro Videla
Date: Fri, 25 Dec 2009 16:58:47 +0800
Subject: New rb:filter/2 to filter reports by date
The function filter/2 expects a second parameter
Dates that can be used to return reports that
occurred between the provided dates.
Usage:
Dec22 = {{2009,12,22},{0,0,0}}.
Dec24 = {{2009,12,24},{0,0,0}}.
rb:filter(Filters, {Dec22, from}).
%will return reports that occurred from Dec22.
rb:filter(Filters, {Dec22, to}).
%will return reports that occurred before Dec22.
rb:filter(Filters, {Dec22, Dec24}).
%will return reports that occurred between Dec22
% and Dec24
---
lib/sasl/doc/src/rb.xml | 23 +++++++++
lib/sasl/src/rb.erl | 126 ++++++++++++++++++++++++++++++++++++++----------
2 files changed, 123 insertions(+), 26 deletions(-)
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index 0b5df29333..bb205c0554 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -44,6 +44,7 @@
filter(Filters)
+ filter(Filters, Dates)
Filter reports and displays them on the screen
Filters = [filter()]
@@ -51,6 +52,9 @@
Key = term()
Value = term()
RegExp = string() | {string, Options} | mp(), {mp(), Options}
+ Dates = {DateFrom, DateTo} | {DateFrom, from} | {DateTo, to}
+ DateFrom = DateTo = {date(), time()}
+ date() and time() are the same type as in the calendar module
This function displays the reports that match the provided filters.
@@ -66,6 +70,25 @@
If the filter is of the form {Key, RegExp, re} the report must contain an element with
key = Key and Value must match the RegExp regular expression.
+
+ If the Dates parameter is provided, then the reports are filtered according to the date
+ when they occurred. If Dates is of the form {DateFrom, from} then reports that occurred
+ after DateFrom are displayed.
+
+
+ If Dates is of the form {DateTo, to} then reports that occurred before DateTo
+ are displayed.
+
+
+ If two Dates are provided, then reports that occurred between those dates are returned.
+
+
+ If you only want to filter only by dates, then you can provide the empty list as the Filters
+ parameter.
+
+
+ See rb:grep/1 for more information on the RegExp parameter.
+
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 5167f961ec..3299921cc9 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -22,7 +22,7 @@
%% External exports
-export([start/0, start/1, stop/0, rescan/0, rescan/1]).
--export([list/0, list/1, show/0, show/1, grep/1, filter/1, start_log/1, stop_log/0]).
+-export([list/0, list/1, show/0, show/1, grep/1, filter/1, filter/2, start_log/1, stop_log/0]).
-export([h/0, help/0]).
%% Internal exports
@@ -76,6 +76,9 @@ grep(RegExp) -> gen_server:call(rb_server, {grep, RegExp}, infinity).
filter(Filters) when is_list(Filters) ->
gen_server:call(rb_server, {filter, Filters}, infinity).
+filter(Filters, FDates) when is_list(Filters) andalso is_tuple(FDates) ->
+ gen_server:call(rb_server, {filter, {Filters, FDates}}, infinity).
+
start_log(FileName) -> gen_server:call(rb_server, {start_log, FileName}).
stop_log() -> gen_server:call(rb_server, stop_log).
@@ -100,6 +103,10 @@ help() ->
io:format(" reports must be proplists.~n"),
io:format(" Filters is a list of tuples of the following form:~n"),
print_filters(),
+ io:format("rb:filter(Filters, Dates) -~n"),
+ io:format(" same as rb:filter/1 but accepts date ranges to filter reports.~n"),
+ io:format(" Dates must be of the following form:~n"),
+ print_dates(),
io:format("rb:rescan() - rescans the report directory with same~n"),
io:format(" options.~n"),
io:format("rb:rescan(Options) - rescans the report directory with new~n"),
@@ -153,6 +160,15 @@ print_filters() ->
io:format(" - {Key, RegExp, re, no}~n"),
io:format(" excludes report containing {Key, RegExp}~n").
+print_dates() ->
+ io:format(" - {StartDate, EndDate}~n"),
+ io:format(" StartDate = EndDate = {{Y-M-D},{H,M,S}} ~n"),
+ io:format(" prints the reports with date between StartDate and EndDate~n"),
+ io:format(" - {StartDate, from}~n"),
+ io:format(" prints the reports with date greater than StartDate~n"),
+ io:format(" - {EndDate, to}~n"),
+ io:format(" prints the reports with date lesser than StartDate~n").
+
init(Options) ->
process_flag(priority, low),
process_flag(trap_exit, true),
@@ -218,8 +234,13 @@ handle_call({grep, RegExp}, _From, State) ->
end;
handle_call({filter, Filters}, _From, State) ->
#state{dir = Dir, data = Data, device = Device, abort = Abort, log = Log} = State,
- NewDevice = filter_all_reports(Dir, Data, Filters, Device, Abort, Log),
- {reply, ok, State#state{device = NewDevice}}.
+ try filter_all_reports(Dir, Data, Filters, Device, Abort, Log) of
+ NewDevice ->
+ {reply, ok, State#state{device = NewDevice}}
+ catch
+ error:Error ->
+ {reply, {error, Error}, State}
+ end.
terminate(_Reason, #state{device = Device}) ->
close_device(Device).
@@ -706,31 +727,28 @@ filter_report(Dir, Data, Filters, Number, Device, Abort, Log) ->
{proceed,Device}
end.
-filter_rep(Filters, Fd, FilePosition, Device, Abort, Log) ->
- case read_rep_msg(Fd, FilePosition) of
- {Date, Msg} ->
- % io:format("Date: ~p Message: ~p~n", [Date, Msg]),
- {_D, M} = Msg,
- {_, _, M2} = M,
- case M2 of
- {_, _, Report} ->
- case filter_report(Filters, Report) of
- true ->
- case catch rb_format_supp:print(Date, Msg, Device) of
- {'EXIT', _} ->
- handle_bad_form(Date, Msg, Device, Abort, Log);
- _ ->
- {proceed,Device}
- end;
- _ ->
- {proceed, Device}
- end;
+filter_rep({Filters, FDates}, Fd, FilePosition, Device, Abort, Log) ->
+ RepMsg = read_rep_msg(Fd, FilePosition),
+ case RepMsg of
+ {_DateStr, {Date, _Msg}} ->
+ case compare_dates(Date, FDates) of
+ true ->
+ print_filter_report(RepMsg, Filters, Device, Abort, Log);
_ ->
{proceed,Device}
end;
_ ->
io:format("rb: Cannot read from file~n"),
{proceed,Device}
+ end;
+filter_rep(Filters, Fd, FilePosition, Device, Abort, Log) ->
+ RepMsg = read_rep_msg(Fd, FilePosition),
+ case RepMsg of
+ {Date, Msg} ->
+ print_filter_report({Date, Msg}, Filters, Device, Abort, Log);
+ _ ->
+ io:format("rb: Cannot read from file~n"),
+ {proceed,Device}
end.
filter_report([], _Msg) ->
@@ -754,8 +772,9 @@ filter_report([{Key, RegExp, re}|T], Msg) ->
undefined ->
false;
Value ->
- case re:run(Value, RegExp) of
- {match, _} ->
+ Subject = lists:flatten(io_lib:format("~p",[Value])),
+ case run_re(Subject, RegExp) of
+ match ->
filter_report(T, Msg);
_ -> false
end
@@ -765,12 +784,67 @@ filter_report([{Key, RegExp, re, no}|T], Msg) ->
undefined ->
false;
Value ->
- case re:run(Value, RegExp) of
- {match, _} -> false;
+ Subject = lists:flatten(io_lib:format("~p",[Value])),
+ case run_re(Subject, RegExp) of
+ match -> false;
_ -> filter_report(T, Msg)
end
end.
+get_compare_dates(Date, CompareDate) ->
+ case application:get_env(sasl, utc_log) of
+ {ok, true} ->
+ {local_time_to_universal_time(Date),
+ local_time_to_universal_time(CompareDate)};
+ _ ->
+ {Date, CompareDate}
+ end.
+get_compare_dates(Date, From, To) ->
+ case application:get_env(sasl, utc_log) of
+ {ok, true} ->
+ {local_time_to_universal_time(Date),
+ local_time_to_universal_time(From),
+ local_time_to_universal_time(To)};
+ _ ->
+ {Date, From, To}
+ end.
+
+compare_dates(Date, {CompareDate, from}) ->
+ {Date2, DateFrom} = get_compare_dates(Date, CompareDate),
+ calendar:datetime_to_gregorian_seconds(Date2) >=
+ calendar:datetime_to_gregorian_seconds(DateFrom);
+compare_dates(Date, {CompareDate, to}) ->
+ {Date2, DateTo} = get_compare_dates(Date, CompareDate),
+ calendar:datetime_to_gregorian_seconds(Date2) =<
+ calendar:datetime_to_gregorian_seconds(DateTo);
+compare_dates(Date, {From, To}) ->
+ {Date2, DateFrom, DateTo} = get_compare_dates(Date, From, To),
+ calendar:datetime_to_gregorian_seconds(Date2) >=
+ calendar:datetime_to_gregorian_seconds(DateFrom)
+ andalso
+ calendar:datetime_to_gregorian_seconds(Date2) =<
+ calendar:datetime_to_gregorian_seconds(DateTo).
+
+print_filter_report({Date, Msg}, Filters, Device, Abort, Log) ->
+ {_D, M} = Msg,
+ {_, _, M2} = M,
+ case M2 of
+ {_, _, Report} ->
+ case filter_report(Filters, Report) of
+ true ->
+ case catch rb_format_supp:print(Date, Msg, Device) of
+ {'EXIT', _} ->
+ handle_bad_form(Date, Msg, Device, Abort, Log);
+ _ ->
+ {proceed,Device}
+ end;
+ _ ->
+ {proceed, Device}
+ end;
+ _ ->
+ {proceed,Device}
+ end.
+
read_rep(Fd, FilePosition, Device, Abort, Log) ->
case read_rep_msg(Fd, FilePosition) of
{Date, Msg} ->
--
cgit v1.2.3