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_log_writer_syslog). 14-behavior(couch_log_writer). 15 16 17-export([ 18 init/0, 19 terminate/2, 20 write/2 21]). 22 23 24-include("couch_log.hrl"). 25 26 27-record(st, { 28 socket, 29 host, 30 port, 31 hostname, 32 os_pid, 33 appid, 34 facility 35}). 36 37 38-define(SYSLOG_VERSION, 1). 39 40 41-ifdef(TEST). 42-export([ 43 get_facility/1, 44 get_level/1 45]). 46-endif. 47 48 49init() -> 50 {ok, Socket} = gen_udp:open(0), 51 52 Host = case config:get("log", "syslog_host") of 53 undefined -> 54 undefined; 55 SysLogHost -> 56 case inet:getaddr(SysLogHost, inet) of 57 {ok, Address} -> 58 Address; 59 _ -> 60 undefined 61 end 62 end, 63 64 {ok, #st{ 65 socket = Socket, 66 host = Host, 67 port = config:get_integer("log", "syslog_port", 514), 68 hostname = net_adm:localhost(), 69 os_pid = os:getpid(), 70 appid = config:get("log", "syslog_appid", "couchdb"), 71 facility = get_facility(config:get("log", "syslog_facility", "local2")) 72 }}. 73 74 75terminate(_Reason, St) -> 76 gen_udp:close(St#st.socket). 77 78 79write(Entry, St) -> 80 #log_entry{ 81 level = Level, 82 pid = Pid, 83 msg = Msg, 84 msg_id = MsgId, 85 time_stamp = TimeStamp 86 } = Entry, 87 Fmt = "<~B>~B ~s ~s ~s ~p ~s - ", 88 Args = [ 89 St#st.facility bor get_level(Level), 90 ?SYSLOG_VERSION, 91 TimeStamp, 92 St#st.hostname, 93 St#st.appid, 94 Pid, 95 MsgId 96 ], 97 Pre = io_lib:format(Fmt, Args), 98 ok = send(St, [Pre, Msg, $\n]), 99 {ok, St}. 100 101 102send(#st{host=undefined}, Packet) -> 103 io:format(standard_error, "~s", [Packet]); 104 105send(St, Packet) -> 106 #st{ 107 socket = Socket, 108 host = Host, 109 port = Port 110 } = St, 111 gen_udp:send(Socket, Host, Port, Packet). 112 113 114get_facility(Name) -> 115 FacId = case Name of 116 "kern" -> 0; % Kernel messages 117 "user" -> 1; % Random user-level messages 118 "mail" -> 2; % Mail system 119 "daemon" -> 3; % System daemons 120 "auth" -> 4; % Security/Authorization messages 121 "syslog" -> 5; % Internal Syslog messages 122 "lpr" -> 6; % Line printer subsystem 123 "news" -> 7; % Network news subsystems 124 "uucp" -> 8; % UUCP subsystem 125 "clock" -> 9; % Clock daemon 126 "authpriv" -> 10; % Security/Authorization messages 127 "ftp" -> 11; % FTP daemon 128 "ntp" -> 12; % NTP subsystem 129 "audit" -> 13; % Log audit 130 "alert" -> 14; % Log alert 131 "cron" -> 15; % Scheduling daemon 132 "local0" -> 16; % Local use 0 133 "local1" -> 17; % Local use 1 134 "local2" -> 18; % Local use 2 135 "local3" -> 19; % Local use 3 136 "local4" -> 20; % Local use 4 137 "local5" -> 21; % Local use 5 138 "local6" -> 22; % Local use 6 139 "local7" -> 23; % Local use 7 140 _ -> 141 try list_to_integer(Name) of 142 N when N >= 0, N =< 23 -> N; 143 _ -> 23 144 catch _:_ -> 145 23 146 end 147 end, 148 FacId bsl 3. 149 150 151get_level(Name) when is_atom(Name) -> 152 case Name of 153 debug -> 7; 154 info -> 6; 155 notice -> 5; 156 warning -> 4; 157 error -> 3; 158 critical -> 2; 159 alert -> 1; 160 emergency -> 0; 161 _ -> 3 162 end. 163