OCaml Logs Patterns
The logs library provides structured logging with per-module sources.
Module Setup
Every module that logs should create its own source:
let log_src = Logs.Src.create "project.module_name"
module Log = (val Logs.src_log log_src : Logs.LOG)
This is the standard idiom. Do NOT attempt to abstract or deduplicate this boilerplate.
Log Levels
| Level | Function | Use Case |
|---|---|---|
| App | Log.app |
Always shown to user (startup, completion) |
| Error | Log.err |
Handled but critical errors |
| Warning | Log.warn |
Potential issues, operation continues |
| Info | Log.info |
State transitions, progress |
| Debug | Log.debug |
Verbose debugging details |
Basic Logging
Log.info (fun m -> m "Processing %d items" count);
Log.err (fun m -> m "Failed to connect: %s" reason);
Log.debug (fun m -> m "Request: %a" Request.pp req)
Structured Tags
Add context with tags for filtering/analysis:
Log.info (fun m ->
m "Event received: %s" event_type
~tags:(Logs.Tag.add "channel_id" channel Logs.Tag.empty))
Reporter Setup (bin/)
In CLI applications, set up the reporter in bin/common.ml:
let setup_log style_renderer level =
Fmt_tty.setup_std_outputs ?style_renderer ();
Logs.set_level level;
Logs.set_reporter (Logs_fmt.reporter ())
open Cmdliner
let setup_log =
Term.(const setup_log
$ Fmt_cli.style_renderer ()
$ Logs_cli.level ())