7 (* See http://docs.python.org/lib/module-logging.html for Level values *)
8 type logging_levels
= Notset
| Debug
| Info
| Warn
| Error
| Critical
| Level
of int;;
10 (* Set default logger *)
11 let default_logger = (fun l m
-> Printf.printf
"ocaml-default log: %d %s%!\n%!" l m
);;
13 let loggers = Hashtbl.create
10;;
14 Hashtbl.add
loggers "default-ocaml" default_logger;;
16 (* Translate level names into numerical values as used by Python
17 See http://docs.python.org/lib/module-logging.html for Level values *)
18 let int_of_level name
=
29 let find_logger name
=
31 Hashtbl.find
loggers name
35 Hashtbl.find
loggers "default-ocaml"
37 | Not_found
-> failwith
"Default logger missing -- internal problem";;
40 (* Provide interface functions as in Python's logging module *)
42 let log = find_logger name
in
43 log (int_of_level Debug
) msg
;;
46 let log = find_logger name
in
47 log (int_of_level Info
) msg
;;
50 let log = find_logger name
in
51 log (int_of_level Warn
) msg
;;
56 let log = find_logger name
in
57 log (int_of_level Error
) msg
;;
59 let critical name msg
=
60 let log = find_logger name
in
61 log (int_of_level Critical
) msg
;;
63 (* Function that takes a name, level integer (this is 'raw') and the message *)
64 let lograw name level msg
=
65 let logf = find_logger name
in
68 (* Function that takes a name, level and the message.
69 Presumably, this is what will be used most often. *)
70 let log name level msg
=
71 let lograw = find_logger name
in
72 lograw (int_of_level level
) msg
;;
75 (* Allowing to register loggers from Python *)
77 let add_logger_if_new name logger
=
80 let _ = Str.search_forward
(Str.regexp
"ocaml") name
0 in
83 | Not_found
-> Printf.sprintf
"%s-ocaml" name
86 let _ = Hashtbl.find
loggers loggername
87 in failwith
(Printf.sprintf
"Trying to register logger '%s' again. Why?" loggername)
89 | Not_found
-> Printf.printf
"Adding logger %s to hashtable\n%!" loggername;
90 Hashtbl.add
loggers loggername logger
;;
92 let _py_register_logger =
93 python_pre_interfaced_function
94 ~doc
:"Register a python-logger. \nArguments: Logger name (str) and callback function cb(). \nThe signature of cb() is cb( level: int, message:str). "
95 [|StringType
;CallableType
|]
97 let name = pystring_asstring py_args
.(0) in
98 let ocamllogger = (fun level msg
->
101 [|pyint_fromint level
;
102 pystring_fromstring msg
|]
104 let _ = pyeval_callobject
(py_args
.(1),callback_args) in ()
106 in let () = add_logger_if_new name ocamllogger
113 (* Debugging tools: *)
115 (* getinfo returns an array of strings that contain the names of registered loggers. *)
116 let getinfo loggers =
117 let loggerarray = Array.make
(Hashtbl.length
loggers) "empty" in
118 let () = Snippets.hashtbl_iteri
(fun i key
value -> (loggerarray.(i
) <- key
)) loggers in
121 let print_loggers loggers =
122 Array.iter
(fun a
-> Printf.printf
"registered loggername=%s\n%!" a
) (getinfo loggers);;
125 python_pre_interfaced_function
126 ~doc
: "Function that calls the ocaml logger from Python (just for debugging useful) "
127 [|StringType
;IntType
;StringType
|] ( fun py_args
->
128 let name = pystring_asstring py_args
.(0) in
129 let level = pyint_asint py_args
.(1) in
130 let msg = pystring_asstring py_args
.(2) in
131 let () = lograw name level msg in
134 (* Register function for Python *)
136 let () = register_pre_functions_for_python
137 [| ("log", _py_ocaml_log);
138 ("register_logger", _py_register_logger) |]
143 (* This needs to go into the documentation *)
145 Printf.printf
"About to start tests (Ocaml)\n";;
147 let () = add_logger_if_new "Ocaml" (fun l m
-> Printf.printf
"Ocamllog, Lev=%d: %s\n" l m
);
149 python_load
"log.py";;
151 log "default" (Level
30) "Purely called from Ocaml";;
153 info "ocaml" "This is information";;
155 print_loggers loggers;;
157 python_eval
"logger.warn('Warning from Python')";;