@@ -40,7 +40,6 @@ open Prelude
4040
4141(* * Global logger state *)
4242module State = struct
43-
4443 let all = Hashtbl. create 10
4544 let default_level = ref (`Info : Logger.level )
4645
@@ -77,30 +76,64 @@ module State = struct
7776 let output_ch ch =
7877 fun str -> try output_string ch str; flush ch with _ -> () (* logging never fails, most probably ENOSPC *)
7978
80- let format_simple level facil msg =
79+ let format_simple_full level facil ts pairs msg =
8180 let pid = Unix. getpid () in
8281 let tid = U. gettid () in
8382 let pinfo = if pid = tid then sprintf " %5u:" pid else sprintf " %5u:%u" pid tid in
84- sprintf " [%s] %s [%s:%s] %s\n "
85- (Time. to_string ~gmt: ! utc_timezone ~ms: true (Unix. gettimeofday () ))
83+ let pairs_str = match pairs with [] -> " " | _ -> " " ^ Logfmt. to_string pairs in
84+ sprintf " [%s] %s [%s:%s] %s%s\n "
85+ (Time. to_string ~gmt: ! utc_timezone ~ms: true ts)
8686 pinfo
8787 facil.Logger. name
8888 (Logger. string_level level)
8989 msg
90+ pairs_str
91+
92+ let format_logfmt level facil ts pairs msg =
93+ let pairs = (" msg" , msg) :: pairs in
94+ let pid = Unix. getpid () in
95+ let tid = U. gettid () in
96+ let pairs =
97+ if pid = tid then (" pid" , string_of_int pid) :: pairs
98+ else (" pid" , string_of_int pid) :: (" tid" , string_of_int tid) :: pairs
99+ in
100+ let pairs =
101+ (" time" , Time. to_string ~gmt: ! utc_timezone ~ms: true ts) ::
102+ (" level" , Logger. string_level level) ::
103+ (" facil" , facil.Logger. name) ::
104+ pairs
105+ in
106+ let buf = Buffer. create 32 in
107+ Logfmt. add_to_buffer buf pairs;
108+ Buffer. add_char buf '\n' ;
109+ Buffer. contents buf
110+
111+ open struct
112+ let cur_format: ([`Plain | `Logfmt ]* _) Atomic. t = Atomic. make (`Plain , format_simple_full)
113+ let set_cur_format f = Atomic. set cur_format f
114+ end
115+ let get_cur_format () = Atomic. get cur_format
116+ let is_structured_format () = match get_cur_format () with `Plain , _ -> false | `Logfmt , _ -> true
117+ let set_plaintext () = set_cur_format (`Plain , format_simple_full)
118+ let set_logfmt () = set_cur_format (`Logfmt , format_logfmt)
119+
120+ let format level facil ts pairs msg =
121+ (snd (Atomic. get cur_format)) level facil ts pairs msg
122+
123+ let format_simple level facil msg =
124+ format level facil (Unix. gettimeofday() ) [] msg
90125
91126 let log_ch = stderr
92127 let () = assert (Unix. descr_of_out_channel stderr = Unix. stderr)
93128 let base_name = ref " "
94-
95129 let hook = ref (fun _ _ _ -> () )
130+ let output_simple level facil s = ! hook level facil s; output_ch log_ch s
96131
97- module Put = Logger. PutSimple (
98- struct
99- let format = format_simple
100- let output = fun level facil s -> let () = ! hook level facil s in output_ch log_ch s
101- end)
102-
103- module M = Logger. Make (Put )
132+ (* * Main logger *)
133+ let logger = Logger. put_simple {
134+ format;
135+ output = output_simple;
136+ }
104137
105138 let self = " lib"
106139
@@ -117,12 +150,12 @@ module State = struct
117150 (fun () -> Unix. dup2 (Unix. descr_of_out_channel ch) Unix. stderr)
118151 ()
119152 with
120- e -> M. warn (facility self) " reopen_log_ch(%s) failed : %s" file (Printexc. to_string e)
153+ e ->
154+ let now = (Unix. gettimeofday () ) in
155+ logger.put `Warn (facility self) now [] (sprintf " reopen_log_ch(%s) failed : %s" file (Printexc. to_string e))
121156
122157end
123158
124- include State. M
125-
126159let facility = State. facility
127160let set_filter = State. set_filter
128161let set_loglevels = State. set_loglevels
@@ -145,47 +178,52 @@ let read_env_config = State.read_env_config
145178 param [backtrace]: whether to show backtrace if [exn] is given (default is [false])
146179
147180 param [saved_backtrace]: supply backtrace to show instead of using [Printexc.get_backtrace]
181+
182+ param [pairs] key/value pairs to add to the line, unconditionally
183+
184+ param [structured_pairs] key/value pairs to use for structured log formats only. Plain logging will discard.
148185*)
149- type 'a pr = ?exn :exn -> ?lines:bool -> ?backtrace:bool -> ?saved_backtrace:string list -> ('a , unit , string , unit ) format4 -> 'a
186+ type 'a pr = ?exn :exn -> ?lines:bool -> ?backtrace:bool -> ?saved_backtrace:string list -> ?ts: Time .t -> ?structured_pairs: Logger.Pairs .t -> ?pairs: Logger.Pairs .t -> ('a , unit , string , unit ) format4 -> 'a
150187
151188class logger facil =
152- let make_s output_line =
189+ let make_s ( output_line :Logger.facil -> Time.t -> Logger.Pairs.t -> string -> unit ) =
153190 let output = function
154191 | true ->
155- fun facil s ->
192+ fun facil ts pairs s ->
156193 if String. contains s '\n' then
157- List. iter (output_line facil) @@ String. nsplit s " \n "
194+ List. iter (output_line facil ts pairs ) @@ String. nsplit s " \n "
158195 else
159- output_line facil s
196+ output_line facil ts pairs s
160197 | false -> output_line
161198 in
162- let print_bt lines exn bt s =
163- output lines facil (s ^ " : exn " ^ Exn. str exn ^ (if bt = [] then " (no backtrace)" else " " ));
164- List. iter (fun line -> output_line facil (" " ^ line)) bt
199+ let print_bt lines exn bt ts pairs s =
200+ output lines facil ts pairs (s ^ " : exn " ^ Exn. str exn ^ (if bt = [] then " (no backtrace)" else " " ));
201+ List. iter (fun line -> output_line facil ts pairs (" " ^ line)) bt
165202 in
166- fun ?exn ?(lines =true ) ?(backtrace =false ) ?saved_backtrace s ->
203+ fun ?exn ?(lines =true ) ?(backtrace =false ) ?saved_backtrace ?(ts =Unix. gettimeofday() ) ?(structured_pairs =[] ) ?(pairs =[] ) s ->
204+ let pairs = if State. is_structured_format () then List. rev_append structured_pairs pairs else pairs in
167205 try
168206 match exn with
169- | None -> output lines facil s
207+ | None -> output lines facil ts pairs s
170208 | Some exn ->
171209 match saved_backtrace with
172- | Some bt -> print_bt lines exn bt s
210+ | Some bt -> print_bt lines exn bt ts pairs s
173211 | None ->
174212 match backtrace with
175- | true -> print_bt lines exn (Exn. get_backtrace () ) s
176- | false -> output lines facil (s ^ " : exn " ^ Exn. str exn )
213+ | true -> print_bt lines exn (Exn. get_backtrace () ) ts pairs s
214+ | false -> output lines facil ts pairs (s ^ " : exn " ^ Exn. str exn )
177215 with exn ->
178- output_line facil (sprintf " LOG FAILED : %S with message %S" (Exn. str exn ) s)
216+ output_line facil ts pairs (sprintf " LOG FAILED : %S with message %S" (Exn. str exn ) s)
179217in
180- let make output ?exn ?lines ?backtrace ?saved_backtrace fmt =
181- ksprintf (fun s -> output ?exn ?lines ?backtrace ?saved_backtrace s) fmt
218+ let make : _ -> _ pr = fun output ?exn ?lines ?backtrace ?saved_backtrace ? ts ? structured_pairs ? pairs fmt ->
219+ ksprintf (fun s -> output ?exn ?lines ?backtrace ?saved_backtrace ?ts ?structured_pairs ?pairs s) fmt
182220in
183- let debug_s = make_s debug_s in
184- let warn_s = make_s warn_s in
185- let info_s = make_s info_s in
186- let error_s = make_s error_s in
187- let critical_s = make_s critical_s in
188- let put_s level = make_s (put_s level) in
221+ let debug_s = make_s ( State. logger.put `Debug ) in
222+ let warn_s = make_s ( State. logger.put `Warn ) in
223+ let info_s = make_s ( State. logger.put `Info ) in
224+ let error_s = make_s ( State. logger.put `Error ) in
225+ let critical_s = make_s ( State. logger.put `Critical ) in
226+ let put_s level = make_s (State. logger.put level) in
189227object
190228method debug_s = debug_s
191229method warn_s = warn_s
0 commit comments