1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2021 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openError_monadmoduleList=structincludeListincludeTezos_stdlib.TzListendmoduleString=structincludeStringincludeTezos_stdlib.TzStringendletvalid_charc=matchcwith|'0'..'9'|'a'..'z'|'A'..'Z'|'@'|'-'|'_'|'+'|'='|'~'->true|_->falseletcheck_name_exn:string->(string->char->exn)->unit=funnamemake_exn->String.iter(func->ifvalid_charcthen()elseraise(make_exnnamec))name;()(* Levels are declared from the lowest to the highest so that
polymorphic comparison can be used to check whether a message
should be printed. *)typelevel=Lwt_log_core.level=|Debug|Info|Notice|Warning|Error|Fatalletshould_log~level~sink_level=(* Same criteria as [Lwt_log_core.log] *)level>=sink_levelmoduleLevel=structtypet=levelletdefault=Infoletto_lwt_logt=tletto_string=Lwt_log_core.string_of_levelletof_string=Lwt_log_core.level_of_stringletencoding=letopenData_encodinginstring_enum(List.map(funl->(to_stringl,l))[Debug;Info;Notice;Warning;Error;Fatal])includeCompare.Make(structtypenonrect=tletcompare=Stdlib.compareend)endmoduleSection:sigtypetincludeCompare.Swithtypet:=tvalempty:tvalmake:stringlist->tvalmake_sanitized:stringlist->tvalto_lwt_log:t->Lwt_log_core.sectionvalencoding:tData_encoding.tvalto_string_list:t->stringlistvalpp:Format.formatter->t->unitvalequal:t->t->boolend=structtypet={path:stringlist;lwt_log_section:Lwt_log_core.section}includeCompare.Make(structtypenonrect=tletcompare=Stdlib.compareend)letempty={path=[];lwt_log_section=Lwt_log_core.Section.make""}letmakesl=List.iter(funs->check_name_exns(funnamechar->Printf.ksprintf(funs->Invalid_arguments)"Internal_event.Section: invalid name %S (contains %c)"namechar))sl;{path=sl;lwt_log_section=Lwt_log_core.Section.make(String.concat"."sl);}letmake_sanitizedsl=List.map(String.map(func->ifvalid_charcthencelse'_'))sl|>makeletto_string_lists=s.pathletto_lwt_logs=s.lwt_log_sectionletencoding=letopenData_encodinginconv(fun{path;_}->path)(funl->makel)(liststring)letppfmtsection=Format.fprintffmt"%s"(String.concat"."section.path)endletregistered_sections=refTzString.Set.emptyletget_registered_sections()=!registered_sectionsletregister_sectionsection=registered_sections:=TzString.Set.add(Lwt_log_core.Section.name(Section.to_lwt_logsection))!registered_sectionsmoduletypeEVENT_DEFINITION=sigtypetvalsection:Section.toptionvalname:stringvaldoc:stringvalpp:short:bool->Format.formatter->t->unitvalencoding:tData_encoding.tvallevel:t->levelendmoduletypeEVENT=sigincludeEVENT_DEFINITIONvalemit:?section:Section.t->(unit->t)->unittzresultLwt.tendtype'aevent_definition=(moduleEVENT_DEFINITIONwithtypet='a)moduletypeSINK=sigtypetvaluri_scheme:stringvalconfigure:Uri.t->ttzresultLwt.tvalhandle:t->'aevent_definition->?section:Section.t->(unit->'a)->unittzresultLwt.tvalclose:t->unittzresultLwt.tendtype'asink_definition=(moduleSINKwithtypet='a)moduleAll_sinks=structtyperegistered=|Registered:{scheme:string;definition:'asink_definition;}->registeredtypeactive=|Active:{scheme:string;configuration:Uri.t;sink:'a;definition:'asink_definition;}->activeletregistered:registeredlistref=ref[]letactive:activelistref=ref[]letfind_registeredscheme_to_find=List.find(functionRegistered{scheme;_}->String.equalschemescheme_to_find)!registeredletregister(typea)m=letmoduleS=(valm:SINKwithtypet=a)inmatchfind_registeredS.uri_schemewith|None->registered:=Registered{scheme=S.uri_scheme;definition=m}::!registered|Some_->(* This should be considered a programming error: *)Printf.ksprintfStdlib.invalid_arg"Internal_event: registering duplicate URI scheme: %S"S.uri_schemetypeactivation_error_reason=|Missing_uri_schemeofstring|Uri_scheme_not_registeredofstringtypeerror+=Activation_errorofactivation_error_reasonlet()=letdescription="Activation of an Internal Event SINK with an URI failed"inlettitle="Internal Event Sink: Wrong Activation URI"inregister_error_kind`Permanent~id:"internal-event-activation-error"~title~description~pp:(funppf->function|Missing_uri_schemeuri->Format.fprintfppf"%s: Missing URI scheme %S"titleuri|Uri_scheme_not_registereduri->Format.fprintfppf"%s: URI scheme not registered %S"titleuri)Data_encoding.(union[case~title:"missing-uri-scheme"(Tag0)(obj1(req"missing-uri-scheme"(obj1(req"uri"string))))(functionMissing_uri_schemeuri->Someuri|_->None)(funuri->Missing_uri_schemeuri);case~title:"non-registered-uri-scheme"(Tag2)(obj1(req"non-registered-uri-scheme"(obj1(req"uri"string))))(functionUri_scheme_not_registereduri->Someuri|_->None)(funuri->Uri_scheme_not_registereduri);])(functionActivation_errorreason->Somereason|_->None)(funreason->Activation_errorreason)letactivateuri=matchUri.schemeuriwith|None->fail(Activation_error(Missing_uri_scheme(Uri.to_stringuri)))|Somescheme_to_activate->letactivate(typea)schemedefinition=letmoduleS=(valdefinition:SINKwithtypet=a)inS.configureuri>>=?funsink->return(Active{scheme;configuration=uri;definition;sink})in(matchfind_registeredscheme_to_activatewith|Some(Registered{scheme;definition})->activateschemedefinition|None->fail(Activation_error(Uri_scheme_not_registered(Uri.to_stringuri))))>>=?funact->active:=act::!active;return_unitletclose()=letclose_one(typea)sinkdefinition=letmoduleS=(valdefinition:SINKwithtypet=a)inS.closesinkinList.iter_es(fun(Active{sink;definition;_})->close_onesinkdefinition)!activelethandledefsectionv=lethandle(typea)sinkdefinition=letmoduleS=(valdefinition:SINKwithtypet=a)inS.handle?sectionsinkdefvinList.iter_es(functionActive{sink;definition;_}->handlesinkdefinition)!activeletpp_statefmt()=letopenFormatinletpp_list_of_sinksnamelistpp=pp_open_boxfmt2;pp_print_if_newlinefmt();pp_print_stringfmt"* ";fprintffmt"%s: ["name;pp_print_cutfmt();pp_print_list~pp_sep:(funfmt()->pp_print_stringfmt",";pp_print_spacefmt())ppfmtlist;pp_close_boxfmt();pp_print_cutfmt();pp_print_stringfmt"]"inpp_open_boxfmt0;pp_list_of_sinks"Registered sinks"!registered(funfmt(Registered{scheme;_})->fprintffmt"\"%s://..\""scheme);pp_print_breakfmt20;pp_list_of_sinks"Active sinks"!active(funfmt(Active{configuration;_})->fprintffmt"\"%a\""Uri.pp_humconfiguration);pp_print_cutfmt();pp_close_boxfmt();()endmoduleGeneric=structtypedefinition=|Definition:(Section.toption*string*'aevent_definition)->definitiontypeevent=Event:(string*'aevent_definition*'a)->eventtypewith_name=<doc:string;name:string>letjson_schema(Definition(_,_,d)):<schema:Json_schema.schema;with_name>=letaux(typea)(ev:aevent_definition)=letmoduleE=(valev:EVENT_DEFINITIONwithtypet=a)inobjectmethodname=E.namemethoddoc=E.docmethodschema=Data_encoding.Json.schemaE.encodingendinauxdletexplode_event(Event(_,def,ev))=letaux(typea)defev=letmoduleM=(valdef:EVENT_DEFINITIONwithtypet=a)inobjectmethodname=M.namemethoddoc=M.docmethodppfmt()=M.pp~short:falsefmtevmethodjson=Data_encoding.Json.constructM.encodingevendinauxdefevendmoduleAll_definitions=structopenGenericletall:definitionlistref=ref[]letregistration_exnfmt=Format.kasprintf(funs->(* This should be considered a programming error: *)Invalid_argument("Internal_event registration error: "^s))fmtletadd(typea)ev=letmoduleE=(valev:EVENT_DEFINITIONwithtypet=a)inmatchList.find(functionDefinition(s,n,_)->E.section=s&&E.name=n)!allwith|Some_->raise(registration_exn"duplicate Event name: %a %S"(Format.pp_print_option(funfmtss->Format.fprintffmt"%s"(String.concat"."(Section.to_string_listss))))E.sectionE.name)|None->check_name_exnE.name(registration_exn"invalid event name: %S contains '%c'");all:=Definition(E.section,E.name,ev)::!allletget()=!allletfindmatch_name=List.find(functionDefinition(_,n,_)->match_namen)!allendmoduleMake(E:EVENT_DEFINITION):EVENTwithtypet=E.t=structincludeEletemit?sectionx=(* In order to evaluate the event at most once, we wrap it in a
`Lazy.t`: *)letx=lazy(x())inAll_sinks.handle(moduleE)section(fun()->Lazy.forcex)let()=All_definitions.add(moduleE)endmoduleSimple=struct(* This type is mostly there to make usage less error-prone, by
explicitly splitting the place where the partial application
takes place. Indeed, it is important that events are declared
only once. *)type'at='a->unittzresultLwt.tletemitsimple_eventparameters=Lwt.try_bind(fun()->simple_eventparameters)(function|Ok()->Lwt.return_unit|Errortrace->(* Having to handle errors when sending events would make the
code very heavy. We are much more likely to just use [>>=?]
to propagate the error, assuming that sending events cannot
fail. But consider this example:
- we log that we are going to do some cleanup, like remove
temporary directories...
- and then because we failed to log, we don't actually
clean the temporary directories.
Instead we just print the error on stderr. *)Format.eprintf"@[<hv 2>Failed to send event:@ %a@]@."Error_monad.pp_print_errortrace;Lwt.return_unit)(funexc->(* For the same reason we also just print exceptions *)Format.eprintf"@[<hv 2>Failed to send event:@ %s@]@."(Printexc.to_stringexc);Lwt.return_unit)letemit__dont_wait__use_with_caresimple_eventparameters=Lwt_utils.dont_wait(funexc->raiseexc)(* emit never lets exceptions escape *)(fun()->emitsimple_eventparameters)letmake_sectionnames=matchnameswith|None->None|Somenames->letsection=Section.make_sanitizednamesinregister_sectionsection;Somesectionletpp_print_compact_floatfmtvalue=Format.fprintffmt"%g"valueletmax_shortened_string_length=64letellipsis="[...]"letpp_print_shortened_stringfmtvalue=letlen=String.lengthvalueiniflen=0thenFormat.pp_print_stringfmt"\"\""elseletescapelen=letrecloopi=ifi>=lenthenfalseelsematchvalue.[i]with|'\000'..'\032'|'\127'..'\255'->(* invisible character (including space) or non-ASCII: needs to be escaped *)true|'\033'..'\126'->(* visible, non-space character *)loop(i+1)inloop0inifString.lengthvalue>max_shortened_string_lengththenletlength_without_ellipsis=max_shortened_string_length-String.lengthellipsisinletprefix=String.subvalue0length_without_ellipsisinifescapelength_without_ellipsisthenFormat.fprintffmt"\"%s%s\""prefixellipsiselseFormat.fprintffmt"%s%s"prefixellipsiselseifescapelenthenFormat.fprintffmt"%S"valueelseFormat.pp_print_stringfmtvalue(* Default pretty-printer for parameters.
Simple types are printed in a compact way.
Structured types are not printed.
If [never_empty] is [false], do not print anything for:
- structured values, like objects;
- empty values, like null.
This is useful to ignore non-inline parameters in log messages.
If [never_empty] is [true], always print something.
This is useful for inline parameters. *)letrecpp_human_readable:'a.never_empty:bool->'aData_encoding.t->_->'a->_=fun(typea)~never_empty(encoding:aData_encoding.t)fmt(value:a)->matchencoding.encodingwith|Null->ifnever_emptythenFormat.pp_print_stringfmt"N/A"|Empty->ifnever_emptythenFormat.pp_print_stringfmt"N/A"|Ignore->ifnever_emptythenFormat.pp_print_stringfmt"N/A"|Constantname->pp_print_shortened_stringfmtname|Bool->Format.pp_print_boolfmtvalue|Int8->Format.pp_print_intfmtvalue|Uint8->Format.pp_print_intfmtvalue|Int16->Format.pp_print_intfmtvalue|Uint16->Format.pp_print_intfmtvalue|Int31->Format.pp_print_intfmtvalue|Int32->Format.fprintffmt"%ld"value|Int64->Format.fprintffmt"%Ld"value|N->Format.pp_print_stringfmt(Z.to_stringvalue)|Z->Format.pp_print_stringfmt(Z.to_stringvalue)|RangedInt_->Format.pp_print_intfmtvalue|RangedFloat_->pp_print_compact_floatfmtvalue|Float->pp_print_compact_floatfmtvalue|Bytes_->pp_print_shortened_stringfmt(Bytes.unsafe_to_stringvalue)|String_->pp_print_shortened_stringfmtvalue|Padded(encoding,_)->pp_human_readable~never_emptyencodingfmtvalue|String_enum(table,_)->(matchStdlib.Hashtbl.find_opttablevaluewith|None->ifnever_emptythenFormat.pp_print_stringfmt"N/A"|Some(name,_)->pp_print_shortened_stringfmtname)|Array_->ifnever_emptythenFormat.pp_print_stringfmt"<array>"|List_->ifnever_emptythenFormat.pp_print_stringfmt"<list>"|Obj(Req{encoding;_}|Dft{encoding;_})->pp_human_readable~never_emptyencodingfmtvalue|Obj(Opt{encoding;_})->Option.iter(pp_human_readable~never_emptyencodingfmt)value|Objs_->ifnever_emptythenFormat.pp_print_stringfmt"<obj>"|Tupencoding->pp_human_readable~never_emptyencodingfmtvalue|Tups_->ifnever_emptythenFormat.pp_print_stringfmt"<tuple>"|Union{cases=[Case{encoding;proj;_};Case{encoding={encoding=Null;_};_};];_;}->((* Probably an [option] type or similar.
We only print the value if it is not null,
unless [never_empty] is [true]. *)matchprojvaluewith|None->ifnever_emptythenFormat.pp_print_stringfmt"null"|Somevalue->pp_human_readable~never_emptyencodingfmtvalue)|Union_->ifnever_emptythenFormat.pp_print_stringfmt"<union>"|Mu_->ifnever_emptythenFormat.pp_print_stringfmt"<recursive>"|Conv{proj;encoding;_}->(* TODO: it may be worth it to take a look at [encoding]
before calling [proj], to try and predict whether the value
will actually be printed. *)pp_human_readable~never_emptyencodingfmt(projvalue)|Describe{encoding;_}->pp_human_readable~never_emptyencodingfmtvalue|Splitted{json_encoding;_}->((* Generally, [Splitted] nodes imply that the JSON encoding
is more human-friendly, as JSON is a human-friendly
format. A typical example is Blake2B hashes.
So for log outputs we use the JSON encoding.
Unfortunately, [Json_encoding.t] is abstract so we have
to [construct] the JSON value and continue from here. *)(* TODO: it may be worth it to take a look at [encoding]
before constructing the JSON value, to try and predict
whether the value will actually be printed (same as [Conv]). *)matchJson_encoding.constructjson_encodingvaluewith|`Null->ifnever_emptythenFormat.pp_print_stringfmt"N/A"|`Boolvalue->Format.pp_print_boolfmtvalue|`Floatvalue->pp_print_compact_floatfmtvalue|`Stringvalue->pp_print_shortened_stringfmtvalue|`A_->ifnever_emptythenFormat.pp_print_stringfmt"<list>"|`O_->ifnever_emptythenFormat.pp_print_stringfmt"<obj>")|Dynamic_size{encoding;_}->pp_human_readable~never_emptyencodingfmtvalue|Check_size{encoding;_}->pp_human_readable~never_emptyencodingfmtvalue|Delayedmake_encoding->pp_human_readable~never_empty(make_encoding())fmtvaluetypeparameter=|Parameter:string*'aData_encoding.t*'a*(Format.formatter->'a->unit)option->parametertypemsg_atom=Textofstring|Variableofint|Spaceletinvalid_msgreasonmsg=invalid_arg(Printf.sprintf"Internal_event.Simple: invalid message string: %S: %s"msgreason)letparse_msgvariable_namesmsg=letlen=String.lengthmsginletrecfind_variable_beginaccatom_starti=letadd_text()=ifi<=atom_startthenaccelseText(String.submsgatom_start(i-atom_start))::accinifi>=lenthenadd_text()elseifmsg.[i]='{'thenletacc=add_text()inleti=i+1infind_variable_endacciielseifmsg.[i]=' 'thenletacc=Space::add_text()inleti=i+1infind_variable_beginacciielsefind_variable_beginaccatom_start(i+1)andfind_variable_endaccatom_starti=ifi>=lentheninvalid_msg"unmatched '{'"msgelseifmsg.[i]='}'thenletvariable_name=String.submsgatom_start(i-atom_start)inmatchTzList.index_ofvariable_namevariable_nameswith|None->invalid_msg(Printf.sprintf"unbound variable: %S"variable_name)msg|Someindex->letacc=Variableindex::accinleti=i+1infind_variable_beginacciielsefind_variable_endaccatom_start(i+1)infind_variable_begin[]00|>List.revletpp_log_message~short(msg:msg_atomlist)fmtfields=(* Add a boolean reference to each field telling whether the field was used. *)letfields=List.map(funfield->(field,reffalse))fieldsinFormat.fprintffmt"@[<hov 2>";(* First, print [msg], including interpolated variables. *)letpp_msg_atom=function|Texttext->Format.pp_print_stringfmttext|Variableindex->(matchList.nth_optfieldsindexwith|None->(* Not supposed to happen, by construction.
But it's just logging, no need to fail here. *)Format.pp_print_stringfmt"???"|Some(Parameter(_name,enc,value,pp),used)->(used:=true;matchppwith|None->pp_human_readable~never_empty:trueencfmtvalue|Somepp->ppfmtvalue))|Space->Format.pp_print_spacefmt()inList.iterpp_msg_atommsg;(* Then, print variables that were not used by [msg]. *)letfirst_field=reftrueinletprint_field(Parameter(name,enc,value,pp),used)=ifnot!usedthenletvalue=letpp=matchppwith|None->pp_human_readable~never_empty:falseenc|Somepp->ppinFormat.asprintf"%a"ppvalueinifString.lengthvalue>0thenif!first_fieldthen(first_field:=false;Format.fprintffmt"@ (%s = %s"namevalue)elseFormat.fprintffmt",@ %s = %s"namevalueinifnotshortthenList.iterprint_fieldfields;if!first_fieldthenFormat.fprintffmt"@]"elseFormat.fprintffmt")@]"letwith_version~nameencoding=Data_encoding.With_version.encoding~name(Data_encoding.With_version.first_versionencoding)letdeclare_0?section~name~msg?(level=Info)()=letsection=make_sectionsectioninletparsed_msg=parse_msg[]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=unit=structtypet=unitletdoc=msgletsection=sectionletname=nameletpp~shortfmt()=pp_log_message~shortparsed_msgfmt[]letencoding=with_version~nameData_encoding.unitletlevel_=levelendinletmoduleEvent=Make(Definition)infun()->Event.emit?section(fun()->())letdeclare_1(typea)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a=structtypet=aletdoc=msgletsection=sectionletname=nameletpp~shortfmtf1=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1)]letencoding=with_version~namef1_encletlevel_=levelendinletmoduleEvent=Make(Definition)infunparameter->Event.emit?section(fun()->parameter)letdeclare_2(typeab)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b=structtypet=a*bletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);]letencoding=with_version~name@@Data_encoding.obj2(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_3(typeabc)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c=structtypet=a*b*cletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);]letencoding=with_version~name@@Data_encoding.obj3(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_4(typeabcd)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))?pp4(f4_name,(f4_enc:dData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name;f4_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c*d=structtypet=a*b*c*dletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3,f4)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);Parameter(f4_name,f4_enc,f4,pp4);]letencoding=with_version~name@@Data_encoding.obj4(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)(Data_encoding.reqf4_namef4_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_5(typeabcde)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))?pp4(f4_name,(f4_enc:dData_encoding.t))?pp5(f5_name,(f5_enc:eData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name;f4_name;f5_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c*d*e=structtypet=a*b*c*d*eletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3,f4,f5)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);Parameter(f4_name,f4_enc,f4,pp4);Parameter(f5_name,f5_enc,f5,pp5);]letencoding=with_version~name@@Data_encoding.obj5(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)(Data_encoding.reqf4_namef4_enc)(Data_encoding.reqf5_namef5_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_6(typeabcdef)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))?pp4(f4_name,(f4_enc:dData_encoding.t))?pp5(f5_name,(f5_enc:eData_encoding.t))?pp6(f6_name,(f6_enc:fData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name;f4_name;f5_name;f6_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c*d*e*f=structtypet=a*b*c*d*e*fletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3,f4,f5,f6)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);Parameter(f4_name,f4_enc,f4,pp4);Parameter(f5_name,f5_enc,f5,pp5);Parameter(f6_name,f6_enc,f6,pp6);]letencoding=with_version~name@@Data_encoding.obj6(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)(Data_encoding.reqf4_namef4_enc)(Data_encoding.reqf5_namef5_enc)(Data_encoding.reqf6_namef6_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_7(typeabcdefg)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))?pp4(f4_name,(f4_enc:dData_encoding.t))?pp5(f5_name,(f5_enc:eData_encoding.t))?pp6(f6_name,(f6_enc:fData_encoding.t))?pp7(f7_name,(f7_enc:gData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name;f4_name;f5_name;f6_name;f7_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c*d*e*f*g=structtypet=a*b*c*d*e*f*gletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3,f4,f5,f6,f7)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);Parameter(f4_name,f4_enc,f4,pp4);Parameter(f5_name,f5_enc,f5,pp5);Parameter(f6_name,f6_enc,f6,pp6);Parameter(f7_name,f7_enc,f7,pp7);]letencoding=with_version~name@@Data_encoding.obj7(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)(Data_encoding.reqf4_namef4_enc)(Data_encoding.reqf5_namef5_enc)(Data_encoding.reqf6_namef6_enc)(Data_encoding.reqf7_namef7_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)letdeclare_8(typeabcdefgh)?section~name~msg?(level=Info)?pp1(f1_name,(f1_enc:aData_encoding.t))?pp2(f2_name,(f2_enc:bData_encoding.t))?pp3(f3_name,(f3_enc:cData_encoding.t))?pp4(f4_name,(f4_enc:dData_encoding.t))?pp5(f5_name,(f5_enc:eData_encoding.t))?pp6(f6_name,(f6_enc:fData_encoding.t))?pp7(f7_name,(f7_enc:gData_encoding.t))?pp8(f8_name,(f8_enc:hData_encoding.t))=letsection=make_sectionsectioninletparsed_msg=parse_msg[f1_name;f2_name;f3_name;f4_name;f5_name;f6_name;f7_name;f8_name]msginletmoduleDefinition:EVENT_DEFINITIONwithtypet=a*b*c*d*e*f*g*h=structtypet=a*b*c*d*e*f*g*hletdoc=msgletsection=sectionletname=nameletpp~shortfmt(f1,f2,f3,f4,f5,f6,f7,f8)=pp_log_message~shortparsed_msgfmt[Parameter(f1_name,f1_enc,f1,pp1);Parameter(f2_name,f2_enc,f2,pp2);Parameter(f3_name,f3_enc,f3,pp3);Parameter(f4_name,f4_enc,f4,pp4);Parameter(f5_name,f5_enc,f5,pp5);Parameter(f6_name,f6_enc,f6,pp6);Parameter(f7_name,f7_enc,f7,pp7);Parameter(f8_name,f8_enc,f8,pp8);]letencoding=with_version~name@@Data_encoding.obj8(Data_encoding.reqf1_namef1_enc)(Data_encoding.reqf2_namef2_enc)(Data_encoding.reqf3_namef3_enc)(Data_encoding.reqf4_namef4_enc)(Data_encoding.reqf5_namef5_enc)(Data_encoding.reqf6_namef6_enc)(Data_encoding.reqf7_namef7_enc)(Data_encoding.reqf8_namef8_enc)letlevel_=levelendinletmoduleEvent=Make(Definition)infunparameters->Event.emit?section(fun()->parameters)endmoduleLegacy_logging=structmoduletypeLOG=sigvaldebug:('a,Format.formatter,unit,unit)format4->'avallog_info:('a,Format.formatter,unit,unit)format4->'avallog_notice:('a,Format.formatter,unit,unit)format4->'avalwarn:('a,Format.formatter,unit,unit)format4->'avallog_error:('a,Format.formatter,unit,unit)format4->'avalfatal_error:('a,Format.formatter,unit,unit)format4->'avallwt_debug:('a,Format.formatter,unit,unitLwt.t)format4->'avallwt_log_info:('a,Format.formatter,unit,unitLwt.t)format4->'avallwt_log_notice:('a,Format.formatter,unit,unitLwt.t)format4->'avallwt_warn:('a,Format.formatter,unit,unitLwt.t)format4->'avallwt_log_error:('a,Format.formatter,unit,unitLwt.t)format4->'avallwt_fatal_error:('a,Format.formatter,unit,unitLwt.t)format4->'aendopenTezos_stdlibtype('a,'b)msgf=(('a,Format.formatter,unit,'b)format4->?tags:Tag.set->'a)->?tags:Tag.set->'btype('a,'b)log=('a,'b)msgf->'bmoduletypeSEMLOG=sigmoduleTag=Tagvaldebug:('a,unit)logvallog_info:('a,unit)logvallog_notice:('a,unit)logvalwarn:('a,unit)logvallog_error:('a,unit)logvalfatal_error:('a,unit)logvallwt_debug:('a,unitLwt.t)logvallwt_log_info:('a,unitLwt.t)logvallwt_log_notice:('a,unitLwt.t)logvallwt_warn:('a,unitLwt.t)logvallwt_log_error:('a,unitLwt.t)logvallwt_fatal_error:('a,unitLwt.t)logvalevent:stringTag.defvalexn:exnTag.defendmoduleMake_event(P:sigvalname:stringend)=structletname_split=String.split_on_char'.'P.nameletsection=Section.makename_splitmoduleDefinition=structletname="legacy_logging_event-"^String.concat"-"name_splittypet={message:string;section:Section.t;level:level;tags:Tag.set;}letmake?(tags=Tag.empty)levelmessage={message;section;level;tags}letv0_encoding=letopenData_encodinginconv(fun{message;section;level;tags}->(message,section,level,tags))(fun(message,section,level,tags)->{message;section;level;tags})(obj4(req"message"string)(req"section"Section.encoding)(req"level"Level.encoding)(dft"tags"(conv(funtags->Format.asprintf"%a"Tag.pp_settags)(fun_->Tag.empty)string)Tag.empty))letencoding=Data_encoding.With_version.(encoding~name(first_versionv0_encoding))letpp~short:_ppf{message;_}=letopenFormatinfprintfppf"%s"messageletdoc="Generic event legacy / string-based information logging."letlevel{level;_}=levelletsection=Somesectionendlet()=registered_sections:=TzString.Set.addP.name!registered_sectionsmoduleEvent=Make(Definition)letemit_asynclevelfmt?tags=(* Prevent massive calls to kasprintf *)letlog_section=Section.to_lwt_logsectioninifshould_log~level~sink_level:(Lwt_log_core.Section.levellog_section)thenFormat.kasprintf(funmessage->Lwt.ignore_result(Event.emit~section(fun()->Definition.make?tagslevelmessage)))fmtelseFormat.ifprintfFormat.std_formatterfmtletemit_lwtlevelfmt?tags=(* Prevent massive calls to kasprintf *)letlog_section=Section.to_lwt_logsectioninifshould_log~level~sink_level:(Lwt_log_core.Section.levellog_section)thenFormat.kasprintf(funmessage->Event.emit~section(fun()->Definition.make?tagslevelmessage)>>=function|Ok()->Lwt.return_unit|Errorel->Format.kasprintfLwt.fail_with"%a"pp_print_errorel)fmtelseFormat.ikfprintf(fun_->Lwt.return_unit)Format.std_formatterfmtendmoduleMake(P:sigvalname:stringend)=structincludeMake_event(P)letemit_async=emit_async?tags:Noneletdebugf=emit_asyncDebugfletlog_infof=emit_asyncInfofletlog_noticef=emit_asyncNoticefletwarnf=emit_asyncWarningfletlog_errorf=emit_asyncErrorfletfatal_errorf=emit_asyncFatalfletemit_lwt=emit_lwt?tags:Noneletlwt_debugf=emit_lwtDebugfletlwt_log_infof=emit_lwtInfofletlwt_log_noticef=emit_lwtNoticefletlwt_warnf=emit_lwtWarningfletlwt_log_errorf=emit_lwtErrorfletlwt_fatal_errorf=emit_lwtFatalfendmoduleMake_semantic(P:sigvalname:stringend)=structincludeMake_event(P)letdebug(f:('a,unit)msgf)=f(emit_asyncDebug)?tags:Noneletlog_infof=f(emit_asyncInfo)?tags:Noneletlog_noticef=f(emit_asyncNotice)?tags:Noneletwarnf=f(emit_asyncWarning)?tags:Noneletlog_errorf=f(emit_asyncError)?tags:Noneletfatal_errorf=f(emit_asyncFatal)?tags:Noneletlwt_debugf=f(emit_lwtDebug)?tags:Noneletlwt_log_infof=f(emit_lwtInfo)?tags:Noneletlwt_log_noticef=f(emit_lwtNotice)?tags:Noneletlwt_warnf=f(emit_lwtWarning)?tags:Noneletlwt_log_errorf=f(emit_lwtError)?tags:Noneletlwt_fatal_errorf=f(emit_lwtFatal)?tags:NonemoduleTag=Tagletevent=Tag.def~doc:"String identifier for the class of event being logged""event"Format.pp_print_textletexn=Tag.def~doc:"Exception which was detected""exception"(funfe->Format.pp_print_textf(Printexc.to_stringe))endendmoduleError_event=structtypet={message:stringoption;severity:[`Fatal|`Recoverable];trace:Error_monad.errorlist;}letmake?message?(severity=`Recoverable)trace()={message;trace;severity}moduleDefinition=structletsection=Noneletname="error-event"typenonrect=tletencoding=letopenData_encodinginletv0_encoding=conv(fun{message;trace;severity}->(message,severity,trace))(fun(message,severity,trace)->{message;severity;trace})(obj3(opt"message"string)(req"severity"(string_enum[("fatal",`Fatal);("recoverable",`Recoverable)]))(req"trace"(listError_monad.error_encoding)))inWith_version.(encoding~name(first_versionv0_encoding))letpp~short:_fx=Format.fprintff"%s:@ %s"name(matchx.messagewithSomex->x|None->"")letdoc="Generic event for any kind of error."letlevel{severity;_}=matchseveritywith`Fatal->Fatal|`Recoverable->Errorendinclude(Make(Definition):EVENTwithtypet:=t)letlog_error_and_recover?section?message?severityf=f()>>=function|Ok()->Lwt.return_unit|Errorel->(emit?section(fun()->make?message?severityel())>>=function|Ok()->Lwt.return_unit|Errorel->Format.kasprintfLwt_log_core.error"Error while emitting error logging event !! %a"pp_print_errorel)endmoduleDebug_event=structtypet={message:string;attachment:Data_encoding.Json.t}letmake?(attach=`Null)message()={message;attachment=attach}letv0_encoding=letopenData_encodinginconv(fun{message;attachment}->(message,attachment))(fun(message,attachment)->{message;attachment})(obj2(req"message"string)(req"attachment"json))moduleDefinition=structletsection=Noneletname="debug-event"typenonrect=tletencoding=Data_encoding.With_version.(encoding~name(first_versionv0_encoding))letpp~short:_ppf{message;attachment}=letopenFormatinfprintfppf"%s:@ %s@ %a"namemessageData_encoding.Json.ppattachmentletdoc="Generic event for semi-structured debug information."letlevel_=Debugendinclude(Make(Definition):EVENTwithtypet:=t)endmoduleLwt_worker_event=structtypet={name:string;event:[`Started|`Ended|`Failedofstring]}letv0_encoding=letopenData_encodinginconv(fun{name;event}->(name,event))(fun(name,event)->{name;event})(obj2(req"name"string)(req"event"(union[case~title:"started"(Tag0)(obj1(req"kind"(constant"started")))(function`Started->Some()|_->None)(fun()->`Started);case~title:"ended"(Tag1)(obj1(req"kind"(constant"ended")))(function`Ended->Some()|_->None)(fun()->`Ended);case~title:"failed"(Tag2)(obj2(req"kind"(constant"failed"))(req"exception"string))(function`Faileds->Some((),s)|_->None)(fun((),s)->`Faileds);])))moduleDefinition=structletsection=Noneletname="lwt-worker-event"typenonrect=tletencoding=Data_encoding.With_version.(encoding~name(first_versionv0_encoding))letpp~short:_ppf{name;event}=letopenFormatinfprintfppf"Worker %s:@ %a"name(funfmt->function|`Failedmsg->fprintfppf"Failed with %s"msg|`Ended->fprintffmt"Ended"|`Started->fprintffmt"Started")eventletdoc="Generic event for callers of the function Lwt_utils.worker."letlevel{event;_}=matcheventwith`Failed_->Error|`Started|`Ended->Debugendinclude(Make(Definition):EVENTwithtypet:=t)leton_eventnameevent=letsection=Section.make_sanitized["lwt-worker";name]inError_event.log_error_and_recover~message:(Printf.sprintf"Trying to emit worker event for %S"name)~severity:`Fatal(fun()->emit~section(fun()->{name;event}))leton_eventnameevent=Lwt.catch(fun()->on_eventnameevent)(funexc->Format.eprintf"@[<hv 2>Failed to log event:@ %s@]@."(Printexc.to_stringexc);Lwt.return_unit)endmoduleLwt_log_sink=struct(* let default_template = "$(date) - $(section): $(message)" *)letdefault_section=Lwt_log_core.Section.mainmoduleSink:SINK=structtypet=unitleturi_scheme="lwt-log"letconfigure_=return_unitlethandle(typea)()m?section(v:unit->a)=letmoduleM=(valm:EVENT_DEFINITIONwithtypet=a)inprotect(fun()->letev=v()inletlevel=M.levelevinletsection=Option.fold~some:Section.to_lwt_logsection~none:default_sectionin(* Only call printf if the event is to be printed. *)ifshould_log~level~sink_level:(Lwt_log_core.Section.levelsection)thenFormat.kasprintf(Lwt_log_core.log~section~level)"%a"(M.pp~short:false)ev>>=fun()->return_unitelsereturn_unit)letclose_=Lwt_log_core.close!Lwt_log_core.default>>=fun()->return_unitendincludeSinklet()=All_sinks.register(moduleSink)end