1% Licensed under the Apache License, Version 2.0 (the "License"); you may not 2% use this file except in compliance with the License. You may obtain a copy of 3% the License at 4% 5% http://www.apache.org/licenses/LICENSE-2.0 6% 7% Unless required by applicable law or agreed to in writing, software 8% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10% License for the specific language governing permissions and limitations under 11% the License. 12 13-module(couch_io_logger). 14 15-export([ 16 start/1, 17 log_output/1, 18 log_input/1, 19 stop_noerror/0, 20 stop_error/1 21]). 22 23 24start(undefined) -> 25 ok; 26start(Dir) -> 27 case filelib:is_dir(Dir) of 28 true -> 29 Name = log_name(), 30 Path = Dir ++ "/" ++ Name, 31 OPath = Path ++ ".out.log_", 32 IPath = Path ++ ".in.log_", 33 {ok, OFd} = file:open(OPath, [read, write, raw]), 34 {ok, IFd} = file:open(IPath, [read, write, raw]), 35 ok = file:delete(OPath), 36 ok = file:delete(IPath), 37 put(logger_path, Path), 38 put(logger_out_fd, OFd), 39 put(logger_in_fd, IFd), 40 ok; 41 false -> 42 ok 43 end. 44 45 46stop_noerror() -> 47 case get(logger_path) of 48 undefined -> 49 ok; 50 _Path -> 51 close_logs() 52 end. 53 54 55stop_error(Err) -> 56 case get(logger_path) of 57 undefined -> 58 ok; 59 Path -> 60 save_error_logs(Path, Err), 61 close_logs() 62 end. 63 64 65log_output(Data) -> 66 log(get(logger_out_fd), Data). 67 68 69log_input(Data) -> 70 log(get(logger_in_fd), Data). 71 72 73unix_time() -> 74 {Mega, Sec, USec} = os:timestamp(), 75 UnixTs = (Mega * 1000000 + Sec) * 1000000 + USec, 76 integer_to_list(UnixTs). 77 78 79log_name() -> 80 Ts = unix_time(), 81 Pid0 = erlang:pid_to_list(self()), 82 Pid1 = string:strip(Pid0, left, $<), 83 Pid2 = string:strip(Pid1, right, $>), 84 lists:flatten(io_lib:format("~s_~s", [Ts, Pid2])). 85 86 87close_logs() -> 88 file:close(get(logger_out_fd)), 89 file:close(get(logger_in_fd)). 90 91 92save_error_logs(Path, Err) -> 93 Otp = erlang:system_info(otp_release), 94 Msg = io_lib:format("Error: ~p~nNode: ~p~nOTP: ~p~n", [Err, node(), Otp]), 95 file:write_file(Path ++ ".meta", Msg), 96 IFd = get(logger_out_fd), 97 OFd = get(logger_in_fd), 98 file:position(IFd, 0), 99 file:position(OFd, 0), 100 file:copy(IFd, Path ++ ".out.log"), 101 file:copy(OFd, Path ++ ".in.log"). 102 103 104log(undefined, _Data) -> 105 ok; 106log(Fd, Data) -> 107 ok = file:write(Fd, [Data, io_lib:nl()]). 108