--- breaks: false tags: public-tech --- # Logs でログをとる この記事は [OCaml Tips Advent Calendar 2022](https://adventar.org/calendars/8396) の13日目です。 OCaml のログライブラリとして [Logs](https://github.com/dbuenzli/logs) があります。`INFO` や `DEBUG` といったレベルごとのロギングが可能です。 使うには、まずインストールして `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 に出力されます。 ```ocaml= (* 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` を 角括弧でくくってプレフィクスとします。 ```ocaml= 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" ``` ## 参考 - https://erratique.ch/software/logs/doc/Logs/index.html