📄 rb.erl
字号:
lists:sublist([Problem|Res], 1, Max); true -> [Problem|Res] end, add_report_data(NewRes, No, Fname); Else -> io:format("err ~p~n", [Else]), [{No, unknown, "Can't read reports from file " ++ Fname, "???", Fname, 0}] end.%%-----------------------------------------------------------------%% Func: add_report_data(Res, No, FName)%% Args: Res is a list of {Type, ShortDescr, Date, FilePos}%% Purpose: Convert a list of {Type, ShortDescr, Date, FilePos} to%% a list of {No, Type, ShortDescr, Date, FileName, FilePos}%% Returns: A list of {No, Type, ShortDescr, Date, FileName, FilePos}%%-----------------------------------------------------------------add_report_data(Res, No, FName) -> add_report_data(Res, No, FName, []).add_report_data([{Type, ShortDescr, Date, FilePos}|T], No, FName, Res) -> add_report_data(T, No+1, FName, [{No, Type, ShortDescr, Date, FName, FilePos}|Res]);add_report_data([], _No, _FName, Res) -> Res.read_reports(Fd, Res, Type) -> {ok, FilePos} = file:position(Fd, cur), case catch read_report(Fd) of {ok, Report} -> RealType = get_type(Report), {ShortDescr, Date} = get_short_descr(Report), Rep = {RealType, ShortDescr, Date, FilePos}, if Type == all-> read_reports(Fd, [Rep | Res], Type); RealType == Type -> read_reports(Fd, [Rep | Res], Type); is_list(Type) -> case lists:member(RealType, Type) of true -> read_reports(Fd, [Rep | Res], Type); _ -> read_reports(Fd, Res, Type) end; true -> read_reports(Fd, Res, Type) end; {error, Error} -> {error, [{unknown, Error, [], FilePos} | Res]}; eof -> {ok, Res}; {'EXIT', Reason} -> [{unknown, Reason, [], FilePos} | Res] end.read_report(Fd) -> case io:get_chars(Fd,'',2) of [Hi,Lo] -> Size = get_int16(Hi,Lo), case io:get_chars(Fd,'',Size) of eof -> {error,"Premature end of file"}; List -> Bin = list_to_binary(List), Ref = make_ref(), case (catch {Ref,binary_to_term(Bin)}) of {'EXIT',_} -> {error, "Inclomplete erlang term in log"}; {Ref,Term} -> {ok, Term} end end; eof -> eof end. get_int16(Hi,Lo) -> ((Hi bsl 8) band 16#ff00) bor (Lo band 16#ff).%%-----------------------------------------------------------------%% Update these functions with the reports that should be possible%% to browse with rb.%%-----------------------------------------------------------------get_type({_Time, {error_report, _Pid, {_, crash_report, _}}}) -> crash_report;get_type({_Time, {error_report, _Pid, {_, supervisor_report, _}}}) -> supervisor_report;get_type({_Time, {info_report, _Pid, {_, progress, _}}}) -> progress;get_type({_Time, {Type, _, _}}) -> Type;get_type(_) -> unknown.get_short_descr({{Date, Time}, {error_report, Pid, {_, crash_report, Rep}}}) -> [OwnRep | _] = Rep, Name = case lists:keysearch(registered_name, 1, OwnRep) of {value, {_Key, []}} -> case lists:keysearch(initial_call, 1, OwnRep) of {value, {_K, {M,_F,_A}}} -> M; _ -> Pid end; {value, {_Key, N}} -> N; _ -> Pid end, NameStr = lists:flatten(io_lib:format("~w", [Name])), {NameStr, date_str(Date, Time)};get_short_descr({{Date, Time}, {error_report, Pid, {_, supervisor_report,Rep}}}) -> Name = case lists:keysearch(supervisor, 1, Rep) of {value, {_Key, N}} when is_atom(N) -> N; _ -> Pid end, NameStr = lists:flatten(io_lib:format("~w", [Name])), {NameStr, date_str(Date,Time)};get_short_descr({{Date, Time}, {_Type, Pid, _}}) -> NameStr = lists:flatten(io_lib:format("~w", [Pid])), {NameStr, date_str(Date,Time)};get_short_descr(_) -> {"???", "???"}. date_str({Y,Mo,D}=Date,{H,Mi,S}=Time) -> case application:get_env(sasl,utc_log) of {ok,true} -> {{YY,MoMo,DD},{HH,MiMi,SS}} = local_time_to_universal_time({Date,Time}), lists:flatten(io_lib:format("~w-~2.2.0w-~2.2.0w ~2.2.0w:" "~2.2.0w:~2.2.0w UTC", [YY,MoMo,DD,HH,MiMi,SS])); _ -> lists:flatten(io_lib:format("~w-~2.2.0w-~2.2.0w ~2.2.0w:" "~2.2.0w:~2.2.0w", [Y,Mo,D,H,Mi,S])) end.local_time_to_universal_time({Date,Time}) -> case calendar:local_time_to_universal_time_dst({Date,Time}) of [UCT] -> UCT; [UCT1,_UCT2] -> UCT1; [] -> % should not happen {Date,Time} end.print_list(Data, Type) -> Header = {"No", "Type", "Process", "Date Time"}, Width = find_width([Header | Data], 0)+1, DateWidth = find_date_width([Header | Data], 0) +1, Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]), io:format(Format, tuple_to_list(Header)), io:format(Format, ["==", "====", "=======", "==== ===="]), print_list(Data, Type, Width, DateWidth).print_list([], _, _, _) -> true;print_list([H|T], Type, Width, DateWidth) -> print_one_report(H, Type, Width, DateWidth), print_list(T, Type, Width, DateWidth).find_width([], Width) -> Width;find_width([H|T], Width) -> Try = length(element(3, H)), if Try > Width -> find_width(T, Try); true -> find_width(T, Width) end.find_date_width([], Width) -> Width;find_date_width([H|T], Width) -> Try = length(element(4, H)), if Try > Width -> find_date_width(T, Try); true -> find_date_width(T, Width) end.print_one_report({No, RealType, ShortDescr, Date, _Fname, _FilePos}, WantedType, Width, DateWidth) -> if WantedType == all -> print_short_descr(No, RealType, ShortDescr, Date, Width, DateWidth); WantedType == RealType -> print_short_descr(No, RealType, ShortDescr, Date, Width, DateWidth); true -> ok end.print_short_descr(No, Type, ShortDescr, Date, Width, DateWidth) -> Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]), io:format(Format, [No, Type, io_lib:format("~s", [ShortDescr]), Date]).print_report_by_num(Dir, Data, Number, Device, Abort, Log) -> {_,Device1} = print_report(Dir, Data, Number, Device, Abort, Log), Device1. print_typed_reports(_Dir, [], _Type, Device, _Abort, _Log) -> Device;print_typed_reports(Dir, Data, Type, Device, Abort, Log) -> {Next,Device1} = case element(2, hd(Data)) of Type -> print_report(Dir, Data, element(1, hd(Data)), Device, Abort, Log); _ -> {proceed,Device} end, if Next == abort -> Device1; true -> print_typed_reports(Dir, tl(Data), Type, Device1, Abort, Log) end.print_all_reports(_Dir, [], Device, _Abort, _Log) -> Device;print_all_reports(Dir, Data, Device, Abort, Log) -> {Next,Device1} = print_report(Dir, Data, element(1, hd(Data)), Device, Abort, Log), if Next == abort -> Device1; true -> print_all_reports(Dir, tl(Data), Device1, Abort, Log) end.print_report(Dir, Data, 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} -> read_rep(Fd, FilePosition, Device, Abort, Log); _ -> io:format("rb: can't open file ~p~n", [Fname]), {proceed,Device} end; no_report -> {proceed,Device} end.find_report([{No, _Type, _Descr, _Date, Fname, FilePosition}|_T], No) -> {Fname, FilePosition};find_report([_H|T], No) -> find_report(T, No);find_report([], No) -> io:format("There is no report with number ~p.~n", [No]), no_report. print_grep_reports(_Dir, [], _RegExp, Device, _Abort, _Log) -> Device;print_grep_reports(Dir, Data, RegExp, Device, Abort, Log) -> {Next,Device1} = print_grep_report(Dir, Data, element(1, hd(Data)), Device, RegExp, Abort, Log), if Next == abort -> Device1; true -> print_grep_reports(Dir, tl(Data), RegExp, Device1, Abort, Log) end.print_grep_report(Dir, Data, Number, Device, RegExp, Abort, Log) -> {Fname, FilePosition} = find_report(Data, Number), FileName = lists:concat([Dir, Fname]), case file:open(FileName, read) of {ok, Fd} when is_pid(Fd) -> check_rep(Fd, FilePosition, Device, RegExp, Number, Abort, Log); _ -> io:format("rb: can't open file ~p~n", [Fname]), {proceed,Device} end.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, _, _} -> 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; _ -> {proceed,Device} end; _ -> io:format("rb: Cannot read from file~n"), {proceed,Device} end.read_rep(Fd, FilePosition, Device, Abort, Log) -> case read_rep_msg(Fd, FilePosition) of {Date, Msg} -> case catch rb_format_supp:print(Date, Msg, Device) of {'EXIT', _} -> handle_bad_form(Date, Msg, Device, Abort, Log); _ -> {proceed,Device} end; _ -> io:format("rb: Cannot read from file~n"), {proceed,Device} end. handle_bad_form(Date, Msg, Device, Abort, Log) -> io:format("rb: ERROR! A report on bad form was encountered. " ++ "It can not be printed to the log.~n~n"), io:format("Details:~n~p ~p~n~n", [Date,Msg]), case {Abort,Device,open_log_file(Log)} of {true,standard_io,standard_io} -> io:format("rb: Logging aborted.~n"), {abort,Device}; {false,standard_io,standard_io} -> io:format("rb: Logging resumed...~n~n"), {proceed,Device}; {_,_,standard_io} -> io:format("rb: Can not reopen ~p. Logging aborted.~n", [Log]), {abort,Device}; {true,_,NewDevice} -> io:format(NewDevice, "~n~n************************* RB ERROR ************************~n" ++ "A report on bad form was encountered here and the logging~n" ++ "process was aborted. Note that there may well be remaining~n" ++ "reports that haven't yet been logged. Please see the rb~n" ++ "manual for more info.~n" ++ "***********************************************************~n", []), io:format("rb: Logging aborted.~n"), {abort,NewDevice}; {false,_,NewDevice} -> io:format(NewDevice, "~n ********* RB: UNPRINTABLE REPORT ********~n~n", []), io:format("rb: Logging resumed...~n~n"), {proceed,NewDevice} end.read_rep_msg(Fd, FilePosition) -> file:position(Fd, {bof, FilePosition}), Res = case catch read_report(Fd) of {ok, Report} -> {_ShortDescr, Date} = get_short_descr(Report), {Date, Report}; _ -> error end, file:close(Fd), Res.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -