123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106(**
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*)openCorelettimestamp_string()=letopenUnixinlettm=localtime(time())inletyear=tm.tm_year+1900inPrintf.sprintf"[%d-%02d-%02d %02d:%02d:%02d]"year(tm.tm_mon+1)tm.tm_mdaytm.tm_hourtm.tm_mintm.tm_sec(* We might want to log to both stderr and a file. Shelling out to tee isn't cross-platform.
* We could dup2 stderr to a pipe and have a child process write to both original stderr and the
* file, but that's kind of overkill. This is good enough *)letdupe_log:(string*out_channel)optionref=refNoneletset_logfilenamefd=dupe_log:=Some(filename,fd)letget_log_name()=Option.map!dupe_log~f:fstletprint_raws=lettime=timestamp_string()inbeginmatch!dupe_logwith|None->()|Some(_,dupe_log_oc)->Printf.fprintfdupe_log_oc"%s %s%!"timesend;Printf.eprintf"%s %s%!"times(* wraps print_raw in order to take a format string & add a newline *)letprintfmt=Printf.ksprintfprint_raw(fmt^^"\n")letprint_durationnamet=print_raw(name^": ");lett2=Unix.gettimeofday()inPrintf.eprintf"%f\n%!"(t2-.t);t2letexc?(prefix="")e=print_raw(prefix^Exn.to_stringe^"\n");Printexc.print_backtracestderr;()moduleLevel:sigtypet=|Off|Fatal|Error|Warn|Info|Debugvalmin_level:unit->tvalset_min_level:t->unitvalpasses_min_level:t->boolvallog:t->('a,unit,string,string,string,unit)format6->'avallog_duration:t->string->float->floatend=structtypet=|Off|Fatal|Error|Warn|Info|Debugletint_of_level=function|Off->6|Fatal->5|Error->4|Warn->3|Info->2|Debug->1letmin_level_ref=refInfoletmin_level()=!min_level_refletset_min_levellevel=min_level_ref:=levelletpasses_min_levellevel=int_of_levellevel>=int_of_level!min_level_refletloglevelfmt=ifpasses_min_levellevelthenprintfmtelsePrintf.ifprintf()fmtletlog_durationlevelfmtt=ifpasses_min_levellevelthenprint_durationfmttelsetend(* Default log instructions to INFO level *)letlog?(lvl=Level.Info)fmt=Level.loglvlfmtletlog_durationfmtt=Level.log_durationLevel.Infofmttletfatalfmt=Level.logLevel.Fatalfmtleterrorfmt=Level.logLevel.Errorfmtletwarnfmt=Level.logLevel.Warnfmtletinfofmt=Level.logLevel.Infofmtletdebugfmt=Level.logLevel.Debugfmt