Skip to content

Commit f5b6dbf

Browse files
committed
add complete app example of lwt_reporter with library
1 parent c3c043e commit f5b6dbf

File tree

6 files changed

+163
-0
lines changed

6 files changed

+163
-0
lines changed

examples/lwt_reporter/dune-project

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
(lang dune 3.3)
2+
3+
(name lwt_reporter_example)
4+
5+
(generate_opam_files true)
6+
7+
(license ISC)
8+
9+
(package
10+
(name lwt_reporter_example)
11+
(synopsis "example")
12+
(depends
13+
(cmdliner
14+
(= 1.1.1))
15+
(conf-libev
16+
(>= 4-12))
17+
(dune
18+
(>= 3.4.1))
19+
(logs
20+
(= 0.7.0))
21+
(lwt
22+
(>= 5.6.1))
23+
))
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# This file is generated by dune, edit dune-project instead
2+
opam-version: "2.0"
3+
synopsis: "example"
4+
license: "ISC"
5+
depends: [
6+
"cmdliner" {= "1.1.1"}
7+
"conf-libev" {>= "4-12"}
8+
"dune" {>= "3.3" & >= "3.4.1"}
9+
"logs" {= "0.7.0"}
10+
"lwt" {>= "5.6.1"}
11+
"odoc" {with-doc}
12+
]
13+
build: [
14+
["dune" "subst"] {dev}
15+
[
16+
"dune"
17+
"build"
18+
"-p"
19+
name
20+
"-j"
21+
jobs
22+
"@install"
23+
"@runtest" {with-test}
24+
"@doc" {with-doc}
25+
]
26+
]

examples/lwt_reporter/src/bin/dune

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(executables
2+
(package lwt_reporter_example)
3+
(names main)
4+
(public_names main)
5+
(libraries
6+
lwt_reporter_example
7+
cmdliner
8+
fmt
9+
fmt.cli
10+
fmt.tty
11+
logs
12+
logs.cli
13+
logs.fmt
14+
logs.lwt
15+
lwt.unix
16+
lwt))
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
[@@@ocaml.warning "-unused-var-strict"]
2+
[@@@ocaml.warning "-unused-field"]
3+
4+
open Cmdliner
5+
6+
(* https://erratique.ch/software/logs/doc/Logs_lwt/index.html#report_ex *)
7+
let lwt_reporter () =
8+
let buf_fmt ~like =
9+
let b = Buffer.create 512 in
10+
( Fmt.with_buffer ~like b,
11+
fun () ->
12+
let m = Buffer.contents b in
13+
Buffer.reset b;
14+
m )
15+
in
16+
let app, app_flush = buf_fmt ~like:Fmt.stdout in
17+
let dst, dst_flush = buf_fmt ~like:Fmt.stderr in
18+
let report (src : Logs.Src.t) level ~over k msgf =
19+
let k _ =
20+
let write () =
21+
match level with
22+
| Logs.App -> Lwt_io.write Lwt_io.stdout (app_flush ())
23+
| _ -> Lwt_io.write Lwt_io.stderr (dst_flush ())
24+
in
25+
let unblock () =
26+
over ();
27+
Lwt.return_unit
28+
in
29+
Lwt.finalize write unblock |> Lwt.ignore_result;
30+
k () (* this is 'k' from 'report' not 'k ()' *)
31+
in
32+
(* Adapted from https://erratique.ch/software/logs/doc/Logs/index.html#ex1 *)
33+
let with_source h k ppf fmt =
34+
Format.kfprintf k ppf
35+
("%a [%s] @[" ^^ fmt ^^ "@]@.")
36+
Logs_fmt.pp_header (level, h) (Logs.Src.name src)
37+
in
38+
match level with
39+
| Logs.App -> msgf @@ fun ?header ?tags fmt -> with_source header k app fmt
40+
| _ -> msgf @@ fun ?header ?tags fmt -> with_source header k dst fmt
41+
in
42+
{ Logs.report }
43+
44+
(* Inspired by
45+
https://github.com/mjambon/cmdliner-cheatsheet/blob/main/src/Demo_arg_main.ml *)
46+
47+
type conf = {
48+
name : string;
49+
log : unit;
50+
}
51+
52+
let name_term =
53+
let default = "John Doe" in
54+
let info =
55+
Arg.info
56+
[ "N"; "name" ] (* '-N' and '--name' will be synonyms *)
57+
~docv:"NAME" ~doc:"User to use when connecting"
58+
in
59+
Arg.value (Arg.opt Arg.string default info)
60+
61+
let setup_log style_renderer level =
62+
Fmt_tty.setup_std_outputs ?style_renderer ();
63+
Logs.set_level level;
64+
Logs.set_reporter (lwt_reporter ());
65+
()
66+
67+
let setup_log_term =
68+
Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ())
69+
70+
let conf_term run =
71+
let combine name log =
72+
let conf = { name; log } in
73+
run conf
74+
in
75+
Term.(const combine $ name_term $ setup_log_term)
76+
77+
let parse_command_line_and_run run =
78+
let info =
79+
Cmd.info "lwt-reporter-example"
80+
(* program name as it will appear in --help *)
81+
in
82+
Cmd.v info (conf_term run) |> Cmd.eval |> Stdlib.exit
83+
84+
let main conf =
85+
Logs.info (fun m -> m "My name is: %s" conf.name);
86+
Lwt_reporter_example.A_module.log_name conf.name
87+
88+
let () = parse_command_line_and_run main
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
let src = Logs.Src.create "a_module" ~doc:"logs from a_module"
2+
3+
module Log = (val Logs.src_log src : Logs.LOG)
4+
5+
let log_name name = Log.warn (fun m -> m "My name is: %s" name)

examples/lwt_reporter/src/lib/dune

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(library
2+
(name lwt_reporter_example)
3+
(public_name lwt_reporter_example)
4+
(libraries
5+
logs))

0 commit comments

Comments
 (0)