Skip to content

Commit b0e0bab

Browse files
author
Colin
authored
Merge pull request #5778 from contificate/IH-642
IH-642: Restructure xs-trace to use Cmdliner
2 parents 9f9c338 + 73f5a30 commit b0e0bab

File tree

2 files changed

+98
-41
lines changed

2 files changed

+98
-41
lines changed

ocaml/xs-trace/dune

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,20 @@
44
(public_name xs-trace)
55
(package xapi)
66
(libraries
7+
cmdliner
78
tracing_export
89
xapi-stdext-unix
910
)
1011
)
12+
13+
(rule
14+
(targets xs-trace.1)
15+
(deps (:exe xs_trace.exe))
16+
(action (with-stdout-to %{targets} (run %{exe} --help=groff)))
17+
)
18+
19+
(install
20+
(section man)
21+
(package xapi)
22+
(files (xs-trace.1 as man1/xs-trace.1))
23+
)

ocaml/xs-trace/xs_trace.ml

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,92 @@
1212
* GNU Lesser General Public License for more details.
1313
*)
1414

15-
let _ =
16-
match Sys.argv with
17-
| [|_; action; origin; url_string|] ->
18-
let url = Uri.of_string url_string in
19-
let submit_json json =
20-
if json <> "" then
21-
let result = Tracing_export.Destination.Http.export ~url json in
22-
match result with
23-
| Ok _ ->
24-
()
25-
| Error err ->
26-
Printf.eprintf "Error: %s" (Printexc.to_string err) ;
27-
exit 1
28-
in
29-
let rec export_file orig =
30-
if Sys.is_directory orig then
31-
let files = Sys.readdir orig in
32-
let file_paths = Array.map (Filename.concat orig) files in
33-
Array.iter export_file file_paths
34-
else if Filename.check_suffix orig ".zst" then
35-
Xapi_stdext_unix.Unixext.with_file orig [O_RDONLY] 0o000
36-
@@ fun compressed_file ->
37-
Zstd.Fast.decompress_passive compressed_file @@ fun decompressed ->
38-
if Filename.check_suffix orig ".ndjson.zst" then
15+
module Exporter = struct
16+
module Unixext = Xapi_stdext_unix.Unixext
17+
18+
(* Submit JSON to a specified endpoint. *)
19+
let submit_json url json =
20+
if json <> "" then
21+
match Tracing_export.Destination.Http.export ~url json with
22+
| Error err ->
23+
Printf.eprintf "Error: %s" (Printexc.to_string err) ;
24+
exit 1
25+
| _ ->
26+
()
27+
28+
(** Export traces from file system to a remote endpoint. *)
29+
let export erase src dst =
30+
let dst = Uri.of_string dst in
31+
let submit_json = submit_json dst in
32+
let rec export_file = function
33+
| path when Sys.is_directory path ->
34+
(* Recursively export trace files. *)
35+
Sys.readdir path
36+
|> Array.iter (fun f -> Filename.concat path f |> export_file)
37+
| path when Filename.check_suffix path ".zst" ->
38+
(* Decompress compressed trace file and decide whether to
39+
treat it as line-delimited or not. *)
40+
let ( let@ ) = ( @@ ) in
41+
let@ compressed = Unixext.with_file path [O_RDONLY] 0o000 in
42+
let@ decompressed = Zstd.Fast.decompress_passive compressed in
43+
if Filename.check_suffix path ".ndjson.zst" then
3944
let ic = Unix.in_channel_of_descr decompressed in
40-
Xapi_stdext_unix.Unixext.lines_iter
41-
(fun line -> submit_json line)
42-
ic
45+
Unixext.lines_iter submit_json ic
4346
else
44-
let json = Xapi_stdext_unix.Unixext.string_of_fd decompressed in
47+
let json = Unixext.string_of_fd decompressed in
4548
submit_json json
46-
else if Filename.check_suffix orig ".ndjson" then
47-
Xapi_stdext_unix.Unixext.readfile_line
48-
(fun line -> submit_json line)
49-
orig
50-
else
51-
let json = Xapi_stdext_unix.Unixext.string_of_file orig in
49+
| path when Filename.check_suffix path ".ndjson" ->
50+
(* Submit traces line by line. *)
51+
Unixext.readfile_line submit_json path
52+
| path ->
53+
(* Assume any other extension is a valid JSON file. *)
54+
let json = Unixext.string_of_file path in
5255
submit_json json
53-
in
54-
export_file origin ;
55-
if action = "mv" then
56-
Xapi_stdext_unix.Unixext.rm_rec ~rm_top:true origin
57-
| _ ->
58-
Printf.eprintf "Usage: %s cp/mv <origin> <destination>\n" Sys.argv.(0) ;
59-
exit 1
56+
in
57+
export_file src ;
58+
if erase then
59+
Unixext.rm_rec ~rm_top:true src
60+
end
61+
62+
module Cli = struct
63+
open Cmdliner
64+
65+
let src =
66+
let doc = "The trace file, e.g. /path/to/trace.ndjson" in
67+
Arg.(required & pos 0 (some string) None (info [] ~docv:"SRC" ~doc))
68+
69+
let dst =
70+
let doc =
71+
"The destination endpoint URL, e.g. http://localhost:9411/api/v2/spans"
72+
in
73+
Arg.(required & pos 1 (some string) None (info [] ~docv:"DST" ~doc))
74+
75+
let export_term ~erase = Term.(const Exporter.export $ const erase $ src $ dst)
76+
77+
let cp_cmd =
78+
let term = export_term ~erase:false in
79+
let doc = "copy a trace to an endpoint" in
80+
Cmd.(v (info "cp" ~doc) term)
81+
82+
let mv_cmd =
83+
let term = export_term ~erase:true in
84+
let doc = "copy a trace to an endpoint and erase it afterwards" in
85+
Cmd.(v (info "mv" ~doc) term)
86+
87+
let xs_trace_cmd =
88+
let man =
89+
[
90+
`S "DESCRIPTION"
91+
; `P "$(mname) is a utility for working with local trace files"
92+
]
93+
in
94+
let desc =
95+
let doc = "utility for working with local trace files" in
96+
Cmd.info "xs-trace" ~doc ~version:"0.1" ~man
97+
in
98+
Cmd.group desc [cp_cmd; mv_cmd]
99+
100+
let main () = Cmd.eval xs_trace_cmd
101+
end
102+
103+
let () = exit (Cli.main ())

0 commit comments

Comments
 (0)