Matter smart home protocol implementation for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

vlog: Add structured JSON logging with base fields

- json-logs: Add ~app, ~auto, ~base parameters for base fields
- json-logs: Auto-include hostname and pid in JSON output
- vlog: Add --log-tag KEY=VALUE flag for custom base tags
- vlog: Use json-logs by default, allow disabling with ~json_reporter:None
- Update meross, matter, mdns, claude-skills, precommit to use vlog

JSON output now includes automatic fields (hostname, pid, app) plus
any custom tags from --log-tag flags, useful for log aggregation.

+25 -22
+1 -1
bin/dune
··· 2 2 (name matter_cli) 3 3 (public_name matter) 4 4 (package matter) 5 - (libraries matter eio_main fmt cmdliner)) 5 + (libraries matter eio_main fmt cmdliner vlog))
+24 -21
bin/matter_cli.ml
··· 55 55 let doc = "Timeout in seconds for network operations." in 56 56 Arg.(value & opt float 3.0 & info [ "t"; "timeout" ] ~docv:"SECONDS" ~doc) 57 57 58 - let quiet_arg = 59 - let doc = "Suppress informational messages." in 60 - Arg.(value & flag & info [ "q"; "quiet" ] ~doc) 58 + (* Log configuration via vlog (provides -q, -v, --log, --json, --trace) *) 61 59 62 60 (* Discover command *) 63 61 let discover_cmd = ··· 90 88 & opt device_filter_conv Operational 91 89 & info [ "f"; "filter" ] ~docv:"FILTER" ~doc) 92 90 in 93 - let run timeout quiet filter = 91 + let run () timeout filter = 94 92 Eio_main.run @@ fun env -> 95 93 Eio.Switch.run @@ fun sw -> 96 94 let net = Eio.Stdenv.net env in ··· 104 102 | All -> Matter.Discovery.discover_all ~sw ~net ~clock ~timeout () 105 103 in 106 104 if devices = [] then begin 107 - if not quiet then Fmt.pr "No devices found.@."; 105 + Logs.info (fun m -> m "No devices found."); 108 106 exit exit_error 109 107 end 110 108 else Fmt.pr "%a@." Matter.Discovery.pp devices 111 109 in 112 - Cmd.v info Term.(const run $ timeout_arg $ quiet_arg $ filter_arg) 110 + Cmd.v info Term.(const run $ Vlog.setup "matter" $ timeout_arg $ filter_arg) 113 111 114 112 (* Commission command *) 115 113 let commission_cmd = ··· 144 142 let doc = "Device passcode (8-digit number)." in 145 143 Arg.(required & opt (some int) None & info [ "passcode" ] ~docv:"CODE" ~doc) 146 144 in 147 - let run quiet ip port passcode = 145 + let run () ip port passcode = 148 146 Eio_main.run @@ fun env -> 149 147 Eio.Switch.run @@ fun sw -> 150 148 let net = Eio.Stdenv.net env in 151 149 let clock = Eio.Stdenv.clock env in 152 - if not quiet then Fmt.pr "Commissioning %s:%d...@." ip port; 150 + Logs.info (fun m -> m "Commissioning %s:%d..." ip port); 153 151 match Matter.Session.establish_pase ~net ~sw ~clock ~ip ~port ~passcode with 154 152 | Ok conn -> 155 - if not quiet then begin 156 - Fmt.pr "PASE successful.@."; 157 - Fmt.pr "Session: %a@." Matter.Session.pp_session conn.session 158 - end 153 + Logs.info (fun m -> m "PASE successful."); 154 + Logs.info (fun m -> 155 + m "Session: %a" Matter.Session.pp_session conn.session) 159 156 | Error (`Msg e) -> 160 - Fmt.epr "Error: %s@." e; 157 + Logs.err (fun m -> m "Error: %s" e); 161 158 exit exit_error 162 159 in 163 - Cmd.v info Term.(const run $ quiet_arg $ ip_arg $ port_arg $ passcode_arg) 160 + Cmd.v info 161 + Term.(const run $ Vlog.setup "matter" $ ip_arg $ port_arg $ passcode_arg) 164 162 165 163 (* Control command - unified on/off/toggle *) 166 164 let control_cmd = ··· 204 202 let doc = "Endpoint ID for the on/off cluster." in 205 203 Arg.(value & opt int 1 & info [ "e"; "endpoint" ] ~docv:"ID" ~doc) 206 204 in 207 - let run quiet action ip port passcode endpoint = 205 + let run () action ip port passcode endpoint = 208 206 Eio_main.run @@ fun env -> 209 207 Eio.Switch.run @@ fun sw -> 210 208 let net = Eio.Stdenv.net env in 211 209 let clock = Eio.Stdenv.clock env in 212 210 match Matter.Session.establish_pase ~net ~sw ~clock ~ip ~port ~passcode with 213 211 | Error (`Msg e) -> 214 - Fmt.epr "PASE error: %s@." e; 212 + Logs.err (fun m -> m "PASE error: %s" e); 215 213 exit exit_error 216 214 | Ok conn -> ( 217 215 let cmd_fn = ··· 224 222 match action with On -> "on" | Off -> "off" | Toggle -> "toggled" 225 223 in 226 224 match cmd_fn ~clock conn ~endpoint_id:endpoint with 227 - | Ok _ -> if not quiet then Fmt.pr "Device turned %s.@." action_str 225 + | Ok _ -> Logs.info (fun m -> m "Device turned %s." action_str) 228 226 | Error `Timeout -> 229 - Fmt.epr "Error: timeout waiting for response.@."; 227 + Logs.err (fun m -> m "Error: timeout waiting for response."); 230 228 exit exit_error) 231 229 in 232 230 Cmd.v info 233 231 Term.( 234 - const run $ quiet_arg $ action_arg $ ip_arg $ port_arg $ passcode_arg 235 - $ endpoint_arg) 232 + const run $ Vlog.setup "matter" $ action_arg $ ip_arg $ port_arg 233 + $ passcode_arg $ endpoint_arg) 236 234 237 235 (* Main command group *) 238 236 let cmd = ··· 247 245 `P "$(b,discover) - Find Matter devices using mDNS"; 248 246 `P "$(b,commission) - Establish PASE session with a device"; 249 247 `P "$(b,control) - Send on/off/toggle commands"; 248 + `S "ENVIRONMENT"; 249 + `P 250 + "$(b,MATTER_LOG) can be set to configure logging levels (e.g., \ 251 + $(b,debug) or $(b,info,matter.crypto:debug))."; 250 252 `S Manpage.s_bugs; 251 253 `P "Report issues at https://github.com/samoht/ocaml-matter/issues"; 252 254 ] 253 255 in 254 256 let info = Cmd.info "matter" ~version:"%%VERSION%%" ~doc ~man in 255 - Cmd.group info [ discover_cmd; commission_cmd; control_cmd ] 257 + let default = Vlog.setup "matter" in 258 + Cmd.group info ~default [ discover_cmd; commission_cmd; control_cmd ] 256 259 257 260 let () = exit (Cmd.eval cmd)