123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101openCoreopenAsyncincludeLogmoduleConsole=structmoduleAnsi=Console.Ansiletwith_style~debug~info~errormsg=letstyle,prefix=matchLog.Message.levelmsgwith|None->info,""|Some`Debug->debug,"[DEBUG]"|Some`Info->info," [INFO]"|Some`Error->error,"[ERROR]"inString.concat~sep:" "[prefix;Log.Message.messagemsg]|>Ansi.string_with_attrstyleletoutput?(debug=([`Yellow]:>Ansi.attrlist))?(info=([]:>Ansi.attrlist))?(error=([`Red]:>Ansi.attrlist))writer=Log.Output.create~flush:(fun()->return())(funmsgs->Queue.itermsgs~f:(funmsg->with_style~debug~info~errormsg|>(funstyled_msg->Writer.writewriterstyled_msg;Writer.newlinewriter));Writer.flushedwriter)moduleBlocking=structletoutput?(debug=([`Yellow]:>Ansi.attrlist))?(info=([]:>Ansi.attrlist))?(error=([`Red]:>Ansi.attrlist))outc=Log.Blocking.Output.create(funmsg->(with_style~debug~info~errormsg)|>funline->Out_channel.output_linesoutc[line])endendmoduleSyslog=structletto_syslogmsg=letprefix=matchLog.Message.levelmsgwith|None->""|Somel->Log.Level.to_stringl^" "inprefix^Log.Message.messagemsg;;letto_levelmsg=matchLog.Message.levelmsgwith(* syslog is generally not configured to show `LOG_DEBUG *)|None->Syslog.Level.INFO|Some`Debug->Syslog.Level.INFO|Some`Info->Syslog.Level.INFO|Some`Error->Syslog.Level.ERR;;letdefault_options=[Syslog.Open_option.PID;Syslog.Open_option.CONS]letopenlog?id?(options=default_options)?facility()=Syslog.openlog?id~options?facility();;letoutput?id?options?facility()=letready=letd=Ivar.create()in(* openlog () shouldn't block by default, but In_thread.run's a
cheap cure for paranoia *)upon(In_thread.run(openlog?id?options?facility))(fun()->Ivar.filld());Ivar.readdinLog.Output.create~flush:(fun()->return())(funmsgs->ready>>=fun()->In_thread.run(fun()->Queue.itermsgs~f:(funmsg->letsyslog_level=to_levelmsginletmsg=to_syslogmsginSyslog.syslog~level:syslog_level(msg^"\n"))));;moduleBlocking=structletoutput()=openlog();Log.Blocking.Output.create(funmsg->letsyslog_level=to_levelmsginletmsg=to_syslogmsginSyslog.syslog~level:syslog_level(msg^"\n"));;endend