1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2017. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(sasl_report). 21 22-export([write_report/3, format_report/3]). 23 24format_report(Fd, What, Report) -> 25 io_report(io_lib, Fd, What, Report). 26 27write_report(Fd, What, Report) -> 28 io_report(io, Fd, What, Report). 29 30io_report(IO, Fd, What, {Time, {error_report, _GL, {Pid, Type, Report}}}) -> 31 case is_my_error_report(What, Type) of 32 true -> 33 Head = write_head(Type, Time, Pid), 34 write_report2(IO, Fd, Head, Type, Report); 35 _ -> true 36 end; 37io_report(IO, Fd, What, {Time, {info_report, _GL, {Pid, Type, Report}}}) -> 38 case is_my_info_report(What, Type) of 39 true -> 40 Head = write_head(Type, Time, Pid), 41 write_report2(IO, Fd, Head, Type, Report); 42 _ -> true 43 end; 44io_report(_IO, _Fd, _, _) -> 45 false. 46 47is_my_error_report(all, Type) -> is_my_error_report(Type); 48is_my_error_report(error, Type) -> is_my_error_report(Type); 49is_my_error_report(_, _Type) -> false. 50 51is_my_error_report(supervisor_report) -> true; 52is_my_error_report(crash_report) -> true; 53is_my_error_report(_) -> false. 54 55is_my_info_report(all, Type) -> is_my_info_report(Type); 56is_my_info_report(progress, Type) -> is_my_info_report(Type); 57is_my_info_report(_, _Type) -> false. 58 59is_my_info_report(progress) -> true; 60is_my_info_report(_) -> false. 61 62write_report2(IO, Fd, Head, supervisor_report, Report) -> 63 Name = sup_get(supervisor, Report), 64 Context = sup_get(errorContext, Report), 65 Reason = sup_get(reason, Report), 66 Offender = sup_get(offender, Report), 67 Enc = encoding(Fd), 68 {FmtString,Args} = supervisor_format([Name,Context,Reason,Offender], Enc), 69 String = io_lib:format(FmtString, Args), 70 write_report_action(IO, Fd, Head, String); 71write_report2(IO, Fd, Head, progress, Report) -> 72 Encoding = encoding(Fd), 73 Depth = error_logger:get_format_depth(), 74 String = format_key_val(Report, Encoding, Depth), 75 write_report_action(IO, Fd, Head, String); 76write_report2(IO, Fd, Head, crash_report, Report) -> 77 Encoding = encoding(Fd), 78 Depth = error_logger:get_format_depth(), 79 String = proc_lib:format(Report, Encoding, Depth), 80 write_report_action(IO, Fd, Head, String). 81 82supervisor_format(Args0, Encoding) -> 83 {P, Tl} = p(Encoding, error_logger:get_format_depth()), 84 [A,B,C,D] = Args0, 85 Args = [A|Tl] ++ [B|Tl] ++ [C|Tl] ++ [D|Tl], 86 {" Supervisor: ~" ++ P ++ "\n" 87 " Context: ~" ++ P ++ "\n" 88 " Reason: ~80.18" ++ P ++ "\n" 89 " Offender: ~80.18" ++ P ++ "\n~n", 90 Args}. 91 92write_report_action(IO, Fd, Head, String) -> 93 S = [Head|String], 94 case IO of 95 io -> io:put_chars(Fd, S); 96 io_lib -> S 97 end. 98 99format_key_val(Rep, Encoding, Depth) -> 100 {P, Tl} = p(Encoding, Depth), 101 format_key_val1(Rep, P, Tl). 102 103format_key_val1([{Tag,Data}|Rep], P, Tl) -> 104 (io_lib:format(" ~16w: ~" ++ P ++ "\n", [Tag, Data|Tl]) ++ 105 format_key_val1(Rep, P, Tl)); 106format_key_val1(_, _, _) -> 107 []. 108 109p(Encoding, Depth) -> 110 {Letter, Tl} = case Depth of 111 unlimited -> {"p", []}; 112 _ -> {"P", [Depth]} 113 end, 114 P = modifier(Encoding) ++ Letter, 115 {P, Tl}. 116 117encoding(IO) -> 118 case lists:keyfind(encoding, 1, io:getopts(IO)) of 119 false -> latin1; 120 {encoding, Enc} -> Enc 121 end. 122 123modifier(latin1) -> ""; 124modifier(_) -> "t". 125 126sup_get(Tag, Report) -> 127 case lists:keysearch(Tag, 1, Report) of 128 {value, {_, Value}} -> 129 Value; 130 _ -> 131 "" 132 end. 133 134maybe_utc(Time) -> 135 case application:get_env(sasl,utc_log) of 136 {ok,true} -> 137 case calendar:local_time_to_universal_time_dst(Time) of 138 [UTC] -> 139 {utc,UTC}; 140 [UTC1,_UTC2] -> 141 {utc,UTC1}; 142 [] -> % should not happen 143 Time 144 end; 145 _ -> 146 Time 147 end. 148 149write_head(supervisor_report, Time, Pid) -> 150 write_head1("SUPERVISOR REPORT", maybe_utc(Time), Pid); 151write_head(crash_report, Time, Pid) -> 152 write_head1("CRASH REPORT", maybe_utc(Time), Pid); 153write_head(progress, Time, Pid) -> 154 write_head1("PROGRESS REPORT", maybe_utc(Time), Pid). 155 156write_head1(Type, {utc,{{Y,Mo,D},{H,Mi,S}}}, Pid) when node(Pid) /= node() -> 157 io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC (~p) ===~n", 158 [Type,D,month(Mo),Y,t(H),t(Mi),t(S),node(Pid)]); 159write_head1(Type, {utc,{{Y,Mo,D},{H,Mi,S}}}, _) -> 160 io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", 161 [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); 162write_head1(Type, {{Y,Mo,D},{H,Mi,S}}, Pid) when node(Pid) /= node() -> 163 io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s (~p) ===~n", 164 [Type,D,month(Mo),Y,t(H),t(Mi),t(S),node(Pid)]); 165write_head1(Type, {{Y,Mo,D},{H,Mi,S}}, _) -> 166 io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", 167 [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). 168 169t(X) when is_integer(X) -> 170 t1(integer_to_list(X)); 171t(_) -> 172 "". 173t1([X]) -> [$0,X]; 174t1(X) -> X. 175 176month(1) -> "Jan"; 177month(2) -> "Feb"; 178month(3) -> "Mar"; 179month(4) -> "Apr"; 180month(5) -> "May"; 181month(6) -> "Jun"; 182month(7) -> "Jul"; 183month(8) -> "Aug"; 184month(9) -> "Sep"; 185month(10) -> "Oct"; 186month(11) -> "Nov"; 187month(12) -> "Dec". 188