123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205(*
* BatLog - Simple Logging module
* Copyright (C) 2011 The Batteries Included Team
*
* This library 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; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)openBatInnerIO(** Flags enable features in logging *)typeflag=[|`Date(** Print the current date as 2011/0628 *)|`Time(** Print the current time as 01:23:45 *)|`Filepos(** Print the file and position of this log command (UNIMPLEMENTED) *)|`Customofunit->string(** Print a generated string *)]letoutput=refstderrletprefix =ref""letflags=ref[`Date;`Time]letprint_flag?fptoc=function|`Date->let{Unix.tm_year=y;tm_mon=m;tm_mday=d;_}=Lazy.forcetinBatPrintf.fprintfoc"%4d/%02d/%02d"(y+1900)(m+1)d|`Time->let{Unix.tm_hour=h;tm_min=m;tm_sec=s;_}=Lazy.forcetinBatPrintf.fprintfoc"%2d:%02d:%02d"hms|`Filepos->BatOption.may(nwriteoc)fp|`Customgen->nwriteoc(gen ())letwrite_flags ?fpocfs=iffs<>[]then(* is it better to call time in print_flag? *)lett=lazy(Unix.localtime(Unix.time()))inBatList.print~first:""~sep:" "~last:":"(print_flag?fpt)ocfs(* BatPrintf.fprintf !output "%a%s%s\n" (write_flags ?fp) !flags !prefix s *)letlog?fps=letoc=!outputin(* makes sure all output goes to a single channel when multi-threaded *)write_flags?fpoc!flags;nwriteoc!prefix;nwriteocs;writeoc'\n'(* BatPrintf.fprintf !output ("%a%s" ^^ fmt ^^"\n") (write_flags ?fp) !flags !prefix *)letlogf?fpfmt=letoc=!output inwrite_flags?fpoc!flags;nwriteoc!prefix;BatPrintf.fprintfocfmt(* BatPrintf.kfprintf (fun _ -> exit 1) !output "%a%s%s\n" (write_flags ?fp) !flags !prefix s *)letfatal?fps=letoc=!outputinwrite_flags?fpoc!flags;nwriteoc!prefix;nwriteocs;writeoc'\n';exit1letfatalf?fpfmt =BatPrintf.kfprintf (fun_->exit1)!output("%a%s"^^fmt^^"%!")(write_flags ?fp)!flags!prefixmoduletypeConfig=sigtypetvalout:toutputvalprefix:stringvalflags:flaglistendmoduleMake(S:Config)=structletlog?fps=write_flags?fpS.outS.flags;nwriteS.outS.prefix;nwriteS.outs;writeS.out'\n'letlogf ?fpfmt=write_flags?fpS.outS.flags;nwriteS.outS.prefix;BatPrintf.fprintfS.out(fmt^^"\n")letfatal?fps=write_flags?fpS.outS.flags;nwriteS.outS.prefix;nwriteS.outs;writeS.out'\n';exit 1letfatalf?fpfmt=BatPrintf.kfprintf(fun_->exit1)S.out("%a%s"^^fmt^^"\n%!")(write_flags ?fp)S.flagsS.prefixendletmake_loggerout prefixflags=objectmethod log?fps=write_flags?fpoutflags;nwriteoutprefix;nwriteouts;writeout'\n'methodlogf?fpfmt=write_flags?fpoutflags;nwriteoutprefix;BatPrintf.fprintf out(fmt^^"\n")methodfatal?fps=write_flags?fpoutflags;nwriteoutprefix;nwriteouts;writeout'\n';exit1methodfatalf?fpfmt=BatPrintf.kfprintf(fun_->exit1)out ("%a%s"^^fmt ^^"%!")(write_flags ?fp)flagsprefixend(*$= make_logger & ~printer:identity
"abcLog1\nabc34\n" \
(let oc = IO.output_string () in \
let l = make_logger oc "abc" [] in \
l#log "Log1"; l#logf "%d" 34; \
IO.close_out oc)
*)moduletypeLevel_sig=sigtypetvalto_string:t->stringvaldefault_level:tvalcompare:t-> t->intendmoduleMake_lev(L:Level_sig)(S:Config)=struct(* These are threadsafe to get/set, so no setter/getter needed;
publicly accessible *)letlevel=refL.default_levellet output=refS.out(** Main logging function *)letlog?fplm=ifL.comparel!level>=0thenletoc=!outputinwrite_flags?fpocS.flags;nwrite ocS.prefix;nwriteoc(L.to_stringl);nwriteoc": ";nwrite ocm;writeoc'\n'letlogf?fp lfmt=(* printf-style logging *)ifL.comparel!level>=0thenletoc=!outputinwrite_flags?fpocS.flags;nwrite ocS.prefix;nwriteoc(L.to_stringl);nwriteoc": ";BatPrintf.fprintfoc(fmt^^"\n")elsePrintf.ifprintf!outputfmtendtypeeasy_lev=[`trace|`debug|`info|`warn|`error|`fatal|`always]moduleBasic=structtypet=easy_levletto_string:(t->string)=function|`trace->"TRACE"|`debug->"DEBUG"|`info->"INFO"|`warn->"WARN"|`error->"ERROR"|`fatal->"FATAL"|`always->"ALWAYS"letto_int:(t->int)=function|`trace->0|`debug->1|`info->2|`warn->3|`error->4|`fatal->5|`always->6letdefault_level=`alwaysletcompareab=BatInt.compare(to_inta)(to_intb)endmoduleDefault_config=structtypet=unitletout=stderrletprefix=""letflags=[`Date;`Time]endmoduleEasy=Make_lev(Basic)(Default_config)