dbuenzli / logs

Logging infrastructure for OCaml
http://erratique.ch/software/logs
ISC License
87 stars 19 forks source link

Document how to report to multiple outputs #17

Closed bbc2 closed 5 years ago

bbc2 commented 7 years ago

Is reporting to multiple outputs reasonably easy? What about adding outputs at runtime, with a different formatting for each of them? Currently, a reporter is associated to a formatter and Logs.set_reporter replaces the active reporter. I see no easy way of having multiple active reporters or merging reporters together.

dbuenzli commented 7 years ago

Here's an example to combine two reporters. I guess it should be easy for you to adapt this to what you want to do. If not reopen.

let r1 = Logs.format_reporter ()
let r2 = Logs_fmt.reporter ()

let r =
  { Logs.report = fun src level ~over k msgf ->
        let nop () = () in
        let v = r1.Logs.report src level ~over:nop k msgf in
        r2.Logs.report src level ~over (fun () -> v) msgf }

let () =
  Fmt_tty.setup_std_outputs ();
  Logs.set_reporter r;
  Logs.err (fun m -> m "HEY HO!");
  ()
bbc2 commented 7 years ago

Awesome, thank you!

dra27 commented 6 years ago

I've hit this too - in my case, all log messages are going to syslog, but there are certain tagged messages which want to go a totally different logging subsystem as well (in this case a status API for the controlling daemon).

It'd feel neater, as these two systems are totally unrelated, to be able to register multiple reporters, but perhaps if not your example could go in the docs?

dbuenzli commented 6 years ago

It's better for modularity and clearer if there's a single point where reporting gets composed and defined (that doesn't mean reporting/routing functions have to be defined at that point).

If you provide the ability to register multiple reporters, sub-systems start to register their own reporter by side-effect and it becomes an anti-modular mess where client loses control when it tries to compose them.

dra27 commented 6 years ago

Fair point - in which case, the example in the docs of how to do it would be helpful (well, at least potentially for others - I've got the hang of it now!)