123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164(* Ocsigen
* Copyright (C) 2005 Vincent Balat
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)(** Writing messages in the logs *)let(>>=)=Lwt.bindletaccess_file="access.log"letwarning_file="warnings.log"leterror_file="errors.log"letaccess_sect=Lwt_log.Section.make"ocsigen:access"letfull_pathf=Filename.concat(Ocsigen_config.get_logdir())fleterror_log_path()=full_patherror_fileletstderr=Lwt_log.channel~close_mode:`Keep~channel:Lwt_io.stderr()letstdout=Lwt_log.channel~close_mode:`Keep~channel:Lwt_io.stdout()letloggers=ref[]letaccess_logger=refLwt_log_core.nullletopen_files?(user=Ocsigen_config.get_user())?(group=Ocsigen_config.get_group())()=(* CHECK: we are closing asynchronously! That should be ok, though. *)List.iter(funl->ignore(Lwt_log.closel:unitLwt.t))!loggers;matchOcsigen_config.get_syslog_facility()with|Somefacility->(* log to syslog *)letsyslog=Lwt_log.syslog~facility()inloggers:=[syslog];Lwt_log.default:=Lwt_log.broadcast[syslog;stderr];Lwt.return()|None->(* log to files *)letopen_logpath=letpath=full_pathpathinLwt.catch(fun()->Lwt_log.file~file_name:path())(function|Unix.Unix_error(error,_,_)->Lwt.fail(Ocsigen_config.Config_file_error(Printf.sprintf"can't open log file %s: %s"path(Unix.error_messageerror)))|exn->Lwt.failexn)inopen_logaccess_file>>=funacc->access_logger:=acc;open_logwarning_file>>=funwar->open_logerror_file>>=funerr->loggers:=[acc;war;err];Lwt_log.default:=Lwt_log.broadcast[Lwt_log.dispatch(fun_sectlev->matchlevwith|Lwt_log.Error|Lwt_log.Fatal->err|Lwt_log.Warning->war|_->Lwt_log.null);Lwt_log.dispatch(fun_sectlev->ifOcsigen_config.get_silent()thenLwt_log.nullelsematchlevwith|Lwt_log.Warning|Lwt_log.Error|Lwt_log.Fatal->stderr|_->stdout)];letgid=matchgroupwith|None->Unix.getgid()|Somegroup->(try(Unix.getgrnamgroup).Unix.gr_gidwithNot_foundase->ignore(Lwt_log.error"Error: Wrong group");raisee)inletuid=matchuserwith|None->Unix.getuid()|Someuser->(try(Unix.getpwnamuser).Unix.pw_uidwithNot_foundase->ignore(Lwt_log.error"Error: Wrong user");raisee)inLwt.catch(fun()->Lwt_unix.chown(full_pathaccess_file)uidgid>>=fun()->Lwt_unix.chown(full_pathwarning_file)uidgid>>=fun()->Lwt_unix.chown(full_patherror_file)uidgid)(fune->matchewith|Unix.Unix_error(Unix.EPERM,_,_)->(* to allow for symlinks to /dev/null *)Lwt.return_unit|_->Lwt.faile)(****)letaccesslogs=(* not really fatal, but log in all cases; does not affect console *)Lwt_log.ign_fatal~section:access_sect~logger:!access_loggers;Lwt_log.ign_notice~section:access_sectsleterrlog?sections=Lwt_log.ign_error?sectionsletwarning?sections=Lwt_log.ign_warning?sectionsletunexpected_exceptiones=Lwt_log.ign_warning_f~exn:e"Unexpected exception in %s"s(****)letconsole=if(not(Ocsigen_config.get_silent()))then(funs->print_endline(s()))else(fun_s->())letlevel_of_string=function|"debug"->SomeLwt_log.Debug|"info"->SomeLwt_log.Info|"notice"->SomeLwt_log.Notice|"warning"->SomeLwt_log.Warning|"error"->SomeLwt_log.Error|"fatal"->SomeLwt_log.Fatal|_->Noneletcommand_fexc_=function|[sect_name]->(* Lwt_log.Section.make :
if a section with the same name
already exists, it is returned. *)letsect=Lwt_log.Section.makesect_nameinLwt_log.Section.reset_levelsect;Lwt.return_unit|[sect_name;level_name]->(* Lwt_log.Section.make :
if a section with the same name
already exists, it is returned. *)letsect=Lwt_log.Section.makesect_namein(matchlevel_of_string(String.lowercase_asciilevel_name)with|None->Lwt_log.Section.reset_levelsect|Somel->Lwt_log.Section.set_levelsectl);Lwt.return()|_->Lwt.failexc