Try   HackMD

Logs でログをとる

この記事は OCaml Tips Advent Calendar 2022 の13日目です。

OCaml のログライブラリとして Logs があります。INFODEBUG といったレベルごとのロギングが可能です。

使うには、まずインストールして dune ファイルに記述します。

$ opam install logs

$ vim bin/dune
(executable
 (public_name yourfavname)
 (name main)
 (libraries yourfavname logs logs.fmt))

使うには、まず reporter とログレベルをセットしたあとに Logs.debug, Logs.info, Logs.err などを呼び出します。 これらの関数の引数に渡す一引数関数には printf のように振る舞う関数が渡されてくるので、 これをつかってログメッセージを出力します。 デフォルトでは、ログメッセージは stdout に出力されます。

(* repoter をセット *) Logs.set_reporter (Logs_fmt.reporter ()); (* level をセット *) Logs.set_level (Some Logs.Info (* Logs.Debug なども使える *)); (* ログ *) let username = "anqou" in Logs.info (fun m -> m "Hello, %s" username); Logs.debug (fun m -> m "Hello, %s, debugging here" username) (* 出力 $ dune exec bin/main.exe main.exe: [ERROR] Hello, anqou, error main.exe: [INFO] Hello, anqou # ログレベルとして Info を選んだので debug は表示されない *)

カスタムの reporter を定義することで、 ログメッセージのプレフィクスや、ログの出力先を変更できます。 以下のコードは出力先を stderr に変更しつつ、引数で渡された procname 角括弧でくくってプレフィクスとします。

let set_logs_reporter procname = let reporter procname ppf = let report _src level ~over k msgf = let k _ = over (); k () in let f h _tags k ppf fmt = Format.kfprintf k ppf ("%a[%s] @[" ^^ fmt ^^ "@]@.") Logs.pp_header (level, h) procname in msgf @@ fun ?header ?tags fmt -> f header tags k ppf fmt in { Logs.report } in Logs.set_reporter (reporter procname Format.err_formatter) ;; set_logs_reporter "main"

参考