diff --git a/bin/dune b/bin/dune index 51b9821..ce28bd6 100644 --- a/bin/dune +++ b/bin/dune @@ -3,11 +3,16 @@ (public_name olly) (name olly) (modules olly) - (libraries olly_trace olly_gc_stats olly_format_json olly_format_fuchsia)) + (libraries + olly_trace + olly_gc_stats + olly_gen_tables + olly_format_json + olly_format_fuchsia)) (executable (package runtime_events_tools_bare) (public_name olly_bare) (name olly_bare) (modules olly_bare) - (libraries olly_trace olly_format_json)) + (libraries olly_trace olly_gen_tables olly_format_json)) diff --git a/bin/olly.ml b/bin/olly.ml index 3aa0a16..3050af7 100644 --- a/bin/olly.ml +++ b/bin/olly.ml @@ -2,5 +2,6 @@ let () = let trace_cmd = Olly_trace.trace_cmd [ (module Olly_format_fuchsia); (module Olly_format_json) ] - and gc_stats_cmd = Olly_gc_stats.gc_stats_cmd in - Olly_common.Cli.main "olly" [ trace_cmd; gc_stats_cmd ] + and gc_stats_cmd = Olly_gc_stats.gc_stats_cmd + and gen_tables_cmd = Olly_gen_tables.cmd in + Olly_common.Cli.main "olly" [ trace_cmd; gc_stats_cmd; gen_tables_cmd ] diff --git a/bin/olly_bare.ml b/bin/olly_bare.ml index e140c40..03ae4fc 100644 --- a/bin/olly_bare.ml +++ b/bin/olly_bare.ml @@ -1,3 +1,4 @@ let () = - let trace_cmd = Olly_trace.trace_cmd [ (module Olly_format_json) ] in - Olly_common.Cli.main "olly_bare" [ trace_cmd ] + let trace_cmd = Olly_trace.trace_cmd [ (module Olly_format_json) ] + and gen_tables_cmd = Olly_gen_tables.cmd in + Olly_common.Cli.main "olly_bare" [ trace_cmd; gen_tables_cmd ] diff --git a/lib/olly_common/cli.ml b/lib/olly_common/cli.ml index 10e0e64..1270177 100644 --- a/lib/olly_common/cli.ml +++ b/lib/olly_common/cli.ml @@ -42,6 +42,21 @@ let exec_args p = in Arg.(required & pos p (some string) None & info [] ~docv:"EXECUTABLE" ~doc) +let src_table_args = + let doc = + "Load a runtime events name table for event translation, for forwards \ + compatibility with newer OCaml versions.\n\ + See `olly-gen-tables`." + in + Arg.( + value & opt (some non_dir_file) None & info [ "table" ] ~docv:"PATH" ~doc) + +let common_args p = + let combine src_table_path exec_args : Launch.common_args = + { src_table_path; exec_args } + in + Term.(const combine $ src_table_args $ exec_args p) + let main name commands = let help_cmd = let topic = diff --git a/lib/olly_common/dune b/lib/olly_common/dune index 13bd663..8ecae8e 100644 --- a/lib/olly_common/dune +++ b/lib/olly_common/dune @@ -1,3 +1,3 @@ (library (name olly_common) - (libraries runtime_events unix cmdliner)) + (libraries olly_rte_shim unix cmdliner)) diff --git a/lib/olly_common/launch.ml b/lib/olly_common/launch.ml index 242dec0..7529d99 100644 --- a/lib/olly_common/launch.ml +++ b/lib/olly_common/launch.ml @@ -1,3 +1,6 @@ +open Olly_rte_shim +open Event + let lost_events ring_id num = Printf.eprintf "[ring_id=%d] Lost %d events\n%!" ring_id num @@ -53,47 +56,39 @@ let collect_events child callbacks = (* Do one more poll in case there are any remaining events we've missed *) Runtime_events.read_poll child.cursor callbacks None |> ignore -type 'r acceptor_fn = int -> Runtime_events.Timestamp.t -> 'r - type consumer_config = { - runtime_begin : (Runtime_events.runtime_phase -> unit) acceptor_fn; - runtime_end : (Runtime_events.runtime_phase -> unit) acceptor_fn; - runtime_counter : (Runtime_events.runtime_counter -> int -> unit) acceptor_fn; - lifecycle : (Runtime_events.lifecycle -> int option -> unit) acceptor_fn; - extra : Runtime_events.Callbacks.t -> Runtime_events.Callbacks.t; + handler : shim_callback; init : unit -> unit; cleanup : unit -> unit; } let empty_config = - { - runtime_begin = (fun _ _ _ -> ()); - runtime_end = (fun _ _ _ -> ()); - runtime_counter = (fun _ _ _ _ -> ()); - lifecycle = (fun _ _ _ _ -> ()); - extra = Fun.id; - init = (fun () -> ()); - cleanup = (fun () -> ()); - } + { handler = (fun _ -> ()); init = (fun () -> ()); cleanup = (fun () -> ()) } + +type common_args = { exec_args : string; src_table_path : string option } + +let our_handler (k : shim_callback) (evt : event) = + match evt.tag with + | Lost_events -> ( + match evt.kind with Counter num -> lost_events evt.ring_id num | _ -> ()) + | _ -> k evt + +let make_shim_callback src_table_path handler = + let map_names = + match src_table_path with + | None -> Construct.builtin_names + | Some path -> + Tabling.tabled_names_and_tags + ~actual:(Tabling.parse_from_yaml_file path) + ~builtin:Construct.builtin_name_table + in + our_handler (map_names handler) -let olly config exec_args = +let olly config { exec_args; src_table_path } = config.init (); Fun.protect ~finally:config.cleanup (fun () -> let child = exec_process exec_args in Fun.protect ~finally:child.close (fun () -> - let callbacks = - let { - runtime_begin; - runtime_end; - runtime_counter; - lifecycle; - extra; - _; - } = - config - in - Runtime_events.Callbacks.create ~runtime_begin ~runtime_end - ~runtime_counter ~lifecycle ~lost_events () - |> extra - in + let cb = make_shim_callback src_table_path config.handler in + let callbacks = Construct.make_callbacks cb in collect_events child callbacks)) diff --git a/lib/olly_gc_stats/olly_gc_stats.ml b/lib/olly_gc_stats/olly_gc_stats.ml index 4a74cd2..788c37a 100644 --- a/lib/olly_gc_stats/olly_gc_stats.ml +++ b/lib/olly_gc_stats/olly_gc_stats.ml @@ -8,14 +8,47 @@ let wall_time = { start_time = 0.; end_time = 0. } let total_cpu_time = ref 0. let domain_gc_times = Array.make 128 0 -let lifecycle _domain_id _ts lifecycle_event _data = - match lifecycle_event with - | Runtime_events.EV_RING_START -> wall_time.start_time <- Unix.gettimeofday () - | Runtime_events.EV_RING_STOP -> - wall_time.end_time <- Unix.gettimeofday (); - let times = Unix.times () in - total_cpu_time := times.tms_utime +. times.tms_cutime - | _ -> () +let make_callbacks hist = + let open Olly_rte_shim in + let open Event in + let current_event = Hashtbl.create 13 in + let is_gc_phase phase = + match phase with + | Runtime_events.EV_MAJOR | Runtime_events.EV_STW_LEADER + | Runtime_events.EV_INTERRUPT_REMOTE -> + true + | _ -> false + in + let handle evt = + let { ring_id; ts; _ } = evt in + match evt.tag with + | Runtime_phase phase -> ( + if evt.kind = SpanBegin then ( + if is_gc_phase phase then + match Hashtbl.find_opt current_event ring_id with + | None -> Hashtbl.add current_event ring_id (phase, ts) + | _ -> ()) + else + match Hashtbl.find_opt current_event ring_id with + | Some (saved_phase, saved_ts) when saved_phase = phase -> + Hashtbl.remove current_event ring_id; + let latency = Int64.to_int (Int64.sub ts saved_ts) in + assert (H.record_value hist latency); + total_gc_time := !total_gc_time + latency; + domain_gc_times.(ring_id) <- domain_gc_times.(ring_id) + latency + | _ -> ()) + | Lifecycle lifecycle_event -> ( + match lifecycle_event with + | Runtime_events.EV_RING_START -> + wall_time.start_time <- Unix.gettimeofday () + | Runtime_events.EV_RING_STOP -> + wall_time.end_time <- Unix.gettimeofday (); + let times = Unix.times () in + total_cpu_time := times.tms_utime +. times.tms_cutime + | _ -> ()) + | _ -> () + in + handle let print_percentiles json output hist = let ms ns = ns /. 1000000. in @@ -89,40 +122,14 @@ let print_percentiles json output hist = (float_of_int (H.value_at_percentile hist p) |> ms))) let gc_stats json output exec_args = - let current_event = Hashtbl.create 13 in let hist = H.init ~lowest_discernible_value:10 ~highest_trackable_value:10_000_000_000 ~significant_figures:3 in - let is_gc_phase phase = - match phase with - | Runtime_events.EV_MAJOR | Runtime_events.EV_STW_LEADER - | Runtime_events.EV_INTERRUPT_REMOTE -> - true - | _ -> false - in - let runtime_begin ring_id ts phase = - if is_gc_phase phase then - match Hashtbl.find_opt current_event ring_id with - | None -> Hashtbl.add current_event ring_id (phase, Ts.to_int64 ts) - | _ -> () - in - let runtime_end ring_id ts phase = - match Hashtbl.find_opt current_event ring_id with - | Some (saved_phase, saved_ts) when saved_phase = phase -> - Hashtbl.remove current_event ring_id; - let latency = Int64.to_int (Int64.sub (Ts.to_int64 ts) saved_ts) in - assert (H.record_value hist latency); - total_gc_time := !total_gc_time + latency; - domain_gc_times.(ring_id) <- domain_gc_times.(ring_id) + latency - | _ -> () - in - let init = Fun.id in - let cleanup () = print_percentiles json output hist in - let open Olly_common.Launch in - olly - { empty_config with runtime_begin; runtime_end; lifecycle; init; cleanup } - exec_args + let handler = make_callbacks hist + and init () = () + and cleanup () = print_percentiles json output hist in + Olly_common.Launch.olly { handler; init; cleanup } exec_args let gc_stats_cmd = let open Cmdliner in @@ -171,4 +178,4 @@ let gc_stats_cmd = in let doc = "Report the GC latency profile and stats." in let info = Cmd.info "gc-stats" ~doc ~sdocs ~man in - Cmd.v info Term.(const gc_stats $ json_option $ output_option $ exec_args 0) + Cmd.v info Term.(const gc_stats $ json_option $ output_option $ common_args 0) diff --git a/lib/olly_rte_shim/construct.ml b/lib/olly_rte_shim/construct.ml new file mode 100644 index 0000000..6fee2be --- /dev/null +++ b/lib/olly_rte_shim/construct.ml @@ -0,0 +1,75 @@ +open Event +open Runtime_events + +let builtin_names (k : shim_callback) (evt : event) : unit = + k + @@ + match evt.tag with + | Runtime_phase ph -> { evt with name = runtime_phase_name ph } + | Runtime_counter cnt -> { evt with name = runtime_counter_name cnt } + | Lifecycle lc -> { evt with name = lifecycle_name lc } + | _ -> evt + +let builtin_name_table = Builtin_name_table.name_table + +let make_callbacks (sc : shim_callback) : Callbacks.t = + let runtime_begin ring_id ts ph = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = "?"; + tag = Runtime_phase ph; + kind = SpanBegin; + } + and runtime_end ring_id ts ph = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = "?"; + tag = Runtime_phase ph; + kind = SpanEnd; + } + and runtime_counter ring_id ts cntr cnt = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = "?"; + tag = Runtime_counter cntr; + kind = Counter cnt; + } + and alloc ring_id ts allocs = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = "alloc"; + tag = Alloc; + kind = IntArray allocs; + } + and lifecycle ring_id ts lc arg = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = "?"; + tag = Lifecycle lc; + kind = MaybeInt arg; + } + and lost_events ring_id cnt = + sc + { + ring_id; + ts = 0L; + name = "lost_events"; + tag = Lost_events; + kind = Counter cnt; + } + in + let cb = + Callbacks.create ~runtime_begin ~runtime_end ~runtime_counter ~alloc + ~lifecycle ~lost_events () + in + Custom_events.add_to cb sc diff --git a/lib/olly_rte_shim/custom_events.no.ml b/lib/olly_rte_shim/custom_events.no.ml new file mode 100644 index 0000000..0d32a65 --- /dev/null +++ b/lib/olly_rte_shim/custom_events.no.ml @@ -0,0 +1 @@ +let add_to cb _ = cb diff --git a/lib/olly_rte_shim/custom_events.yes.ml b/lib/olly_rte_shim/custom_events.yes.ml new file mode 100644 index 0000000..0fd1f50 --- /dev/null +++ b/lib/olly_rte_shim/custom_events.yes.ml @@ -0,0 +1,33 @@ +open Event +open Runtime_events + +type _ custom_type = .. + +type _ custom_type += + | Span : Type.span custom_type + | Int : int custom_type + | Unit : unit custom_type + +type tag += Custom : 'a User.t * 'a custom_type -> tag + +let from_int x = Counter x +let from_unit () = Instant + +let from_span (s : Type.span) = + match s with Begin -> SpanBegin | End -> SpanEnd + +let add_to cb sc = + let emit cty get_kind ring_id ts evt value = + sc + { + ring_id; + ts = ts_to_int64 ts; + name = User.name evt; + tag = Custom (evt, cty); + kind = get_kind value; + } + in + cb + |> Callbacks.add_user_event Type.span (emit Span from_span) + |> Callbacks.add_user_event Type.int (emit Int from_int) + |> Callbacks.add_user_event Type.unit (emit Unit from_unit) diff --git a/lib/olly_rte_shim/dune b/lib/olly_rte_shim/dune new file mode 100644 index 0000000..f5997f6 --- /dev/null +++ b/lib/olly_rte_shim/dune @@ -0,0 +1,37 @@ +(library + (name olly_rte_shim) + (modules construct custom_events event tabling builtin_name_table) + (libraries runtime_events)) + +(library + (name olly_gen_tables) + (modules olly_gen_tables) + (libraries str cmdliner)) + +(executable + (name gen_tables) + (libraries olly_gen_tables) + (modules gen_tables)) + +(rule + (target custom_events.ml) + (enabled_if + (>= %{ocaml_version} 5.1.0)) + (action + (copy# custom_events.yes.ml %{target}))) + +(rule + (target custom_events.ml) + (enabled_if + (< %{ocaml_version} 5.1.0)) + (action + (copy# custom_events.no.ml %{target}))) + +(rule + (target builtin_name_table.ml) + (action + (run + ./gen_tables.exe + --output=%{target} + --format=ml + %{ocaml_where}/caml/runtime_events.h))) diff --git a/lib/olly_rte_shim/event.ml b/lib/olly_rte_shim/event.ml new file mode 100644 index 0000000..afd6c15 --- /dev/null +++ b/lib/olly_rte_shim/event.ml @@ -0,0 +1,32 @@ +type kind = .. + +type kind += + | SpanBegin + | SpanEnd + | Instant + | Counter of int + | IntArray of int array + | MaybeInt of int option + +type tag = .. + +type tag += + | Unrecognised + | Lifecycle of Runtime_events.lifecycle + | Runtime_phase of Runtime_events.runtime_phase + | Runtime_counter of Runtime_events.runtime_counter + | Alloc + | Lost_events + +type event = { + ring_id : int; + ts : int64; + name : string; + tag : tag; + kind : kind; +} + +type shim_callback = event -> unit +(** A simple, unified event handler callback *) + +let ts_to_int64 = Runtime_events.Timestamp.to_int64 diff --git a/lib/olly_rte_shim/gen_tables.ml b/lib/olly_rte_shim/gen_tables.ml new file mode 100644 index 0000000..461cefb --- /dev/null +++ b/lib/olly_rte_shim/gen_tables.ml @@ -0,0 +1 @@ +let () = exit (Cmdliner.Cmd.eval Olly_gen_tables.cmd) diff --git a/lib/olly_rte_shim/olly_gen_tables.ml b/lib/olly_rte_shim/olly_gen_tables.ml new file mode 100644 index 0000000..201dd9e --- /dev/null +++ b/lib/olly_rte_shim/olly_gen_tables.ml @@ -0,0 +1,112 @@ +let enum_re = Str.regexp {|typedef enum {\([^}]*\)} \([a-z_]+\);|} +let enum_constant_re = Str.regexp {|\(EV_\(C_\)?\)?\([A-Z_]+\)|} + +let enums_of_concern = + [ + ("ev_lifecycle", "lifecycle"); + ("ev_runtime_phase", "phase"); + ("ev_runtime_counter", "counter"); + ] + +let parse_constants constants_str = + let ls = ref [] in + try + let i = ref 0 in + while true do + ignore (Str.search_forward enum_constant_re constants_str !i); + i := Str.match_end (); + let constant_value = Str.matched_group (* name *) 3 constants_str in + let name = String.lowercase_ascii constant_value in + ls := name :: !ls + done; + !ls + with Not_found -> List.rev !ls + +(** parse the enum from runtime_events.h *) +let parse_tables_from_header source_str = + let state = Hashtbl.create 4 in + try + let i = ref 0 in + while true do + ignore (Str.search_forward enum_re source_str !i); + i := Str.match_end (); + let enum_name = Str.matched_group (* name *) 2 source_str + and enum_constants = Str.matched_group (* constant list *) 1 source_str in + try + let name = List.assoc enum_name enums_of_concern in + Hashtbl.add state name (parse_constants enum_constants) + with Not_found -> () + done; + state + with Not_found -> state + +let parse_tables_from_file file_name = + let source_str = In_channel.(with_open_text file_name input_all) in + parse_tables_from_header source_str + +type out_fmt = Ml | Yaml + +let stringify fmt state = + let make_array name = + try + let cnsts = Hashtbl.find state name in + match fmt with + | Ml -> + Printf.sprintf "let %s_names = [|\n%s\n|]\n\n" name + (String.concat ";\n" (List.map (Printf.sprintf " \"%s\"") cnsts)) + | Yaml -> Printf.sprintf "%s: [%s]\n" name (String.concat "," cnsts) + with Not_found -> + Printf.eprintf "Did not find enum: %s\n" name; + exit 1 + in + match fmt with + | Ml -> + Printf.sprintf + "open Tabling\n\n\ + %slet name_table = { lifecycle_names ; phase_names ; counter_names }\n" + (make_array "lifecycle" ^ make_array "phase" ^ make_array "counter") + | Yaml -> make_array "lifecycle" ^ make_array "phase" ^ make_array "counter" + +let output_to maybe_file str = + match maybe_file with + | None -> print_string str + | Some file_name -> + Out_channel.(with_open_text file_name (fun oc -> output_string oc str)) + +let cmd = + let open Cmdliner in + let header_file_arg p = + let doc = + "Path to `caml/runtime_events.h`, e.g. \"\\$(ocamlc \ + -where)/caml/runtime_events.h\"." + in + Arg.(required & pos p (some non_dir_file) None & info [] ~docv:"FILE" ~doc) + in + + let stringify_fmt_arg = + let doc = + "Format to produce output, options: \"ml\" (OCaml .ml source file) \ + \"yaml\" (a subset of YAML)." + in + Arg.( + value + & opt (enum [ ("ml", Ml); ("yaml", Yaml) ]) Yaml + & info [ "f"; "format" ] ~docv:"FORMAT" ~doc) + in + + let output_dst_arg = + let doc = "Redirect output to the specified file." in + Arg.( + value & opt (some string) None & info [ "o"; "output" ] ~docv:"FILE" ~doc) + in + + let cmd = + let doc = "Generate runtime events name tables" in + let info = Cmd.info "gen-tables" ~doc ~sdocs:Manpage.s_common_options in + Cmd.v info + Term.( + const output_to $ output_dst_arg + $ (const stringify $ stringify_fmt_arg + $ (const parse_tables_from_file $ header_file_arg 0))) + in + cmd diff --git a/lib/olly_rte_shim/tabling.ml b/lib/olly_rte_shim/tabling.ml new file mode 100644 index 0000000..52d00ce --- /dev/null +++ b/lib/olly_rte_shim/tabling.ml @@ -0,0 +1,125 @@ +open Event + +type raw_name_table = { + lifecycle_names : string array; + phase_names : string array; + counter_names : string array; +} + +exception Not_an_int + +let enum_to_int (e : 'a) : int = + if not (Obj.is_int (Obj.repr e)) then raise Not_an_int; + let idx : int = Obj.magic e in + idx + +let lookup_name (sa : string array) (e : 'a) : string = sa.(enum_to_int e) + +let parse_from_yaml yaml_lines = + let lc, ph, cnt = (ref None, ref None, ref None) in + let parse_line line = + (* line format: "name: [evt1_name,evt2_name,evt3_name]" *) + let colon_i = String.index line ':' in + let name = String.sub line 0 colon_i in + let constants_start_i = colon_i + 3 in + let constants_length = String.length line - constants_start_i - 1 in + let constants_str = String.sub line constants_start_i constants_length in + let constants = String.split_on_char ',' constants_str in + let rf = + match name with + | "lifecycle" -> lc + | "phase" -> ph + | "counter" -> cnt + | _ -> ref None + in + rf := Some (Array.of_list constants) + in + List.iter parse_line yaml_lines; + { + lifecycle_names = Option.get !lc; + phase_names = Option.get !ph; + counter_names = Option.get !cnt; + } + +let parse_from_yaml_file path = + let lines = In_channel.(with_open_text path input_lines) in + parse_from_yaml lines + +(** Read the names of the [runtime_phase], [runtime_counter] and [lifecycle] + events from a table, which allows translating runtime events from future + OCaml versions. *) +let tabled_names (table : raw_name_table) (k : shim_callback) (evt : event) : + unit = + k + @@ + try + match evt.tag with + | Runtime_phase ph -> { evt with name = lookup_name table.phase_names ph } + | Runtime_counter cnt -> + { evt with name = lookup_name table.counter_names cnt } + | Lifecycle lc -> { evt with name = lookup_name table.lifecycle_names lc } + | _ -> evt + with Invalid_argument _ -> evt + +(** Make an array the same size as `input`, with each entry the index + of the corresponding string in `output` (the "known events"), + unmapped events will map to -1, indicating that the event should + be dropped. *) +let build_int_map (input : string array) (output : string array) : int array = + let idx_map : (string, int) Hashtbl.t = + Hashtbl.create (Array.length output) + in + let insert_out_name idx name = Hashtbl.add idx_map name idx in + Array.iteri insert_out_name output; + let lookup_in_name name = + try Hashtbl.find idx_map name with Not_found -> -1 + in + Array.map lookup_in_name input + +exception Not_mapped + +let translate_table (src_tag : 'a) (mapping : int array) (k : 'a -> 'b) : 'b = + let new_idx = + try mapping.(enum_to_int src_tag) + with Invalid_argument _ -> raise Not_mapped + in + if new_idx = -1 then raise Not_mapped; + (* safety: input was an int (and possibly an invalid value), output is too *) + let new_tag : 'a = Obj.magic new_idx in + k new_tag + +(** Translate the tags of [runtime_phase], [runtime_counter] and [lifecycle] + events by name using two tables, which allows us to [match] on them using + the currently-compiled OCaml version's values, even if those differ + (bit-wise) from those produced by the program we're attached to. + Unrecognised events (i.e. new ones) will have their tag replaced by + [Unrecognised], in the absence of a better alternative. Olly tools + (e.g. trace) can still use the associated name and data. *) +let tabled_tags ~(actual : raw_name_table) ~(builtin : raw_name_table) + (k : shim_callback) : shim_callback = + let lcm, phm, cntm = + ( build_int_map actual.lifecycle_names builtin.lifecycle_names, + build_int_map actual.phase_names builtin.phase_names, + build_int_map actual.counter_names builtin.counter_names ) + in + fun evt -> + k + @@ + try + match evt.tag with + | Lifecycle lc_in -> + translate_table lc_in lcm (fun lc -> { evt with tag = Lifecycle lc }) + | Runtime_phase ph_in -> + translate_table ph_in phm (fun ph -> + { evt with tag = Runtime_phase ph }) + | Runtime_counter cnt_in -> + translate_table cnt_in cntm (fun cnt -> + { evt with tag = Runtime_counter cnt }) + | _ -> evt + with Not_mapped -> { evt with tag = Unrecognised } + +(** Translate both names and tags of runtime-internal events, by [tabled_names] + and [tabled_tags] respectively, for forward-compatibility. *) +let tabled_names_and_tags ~(actual : raw_name_table) ~(builtin : raw_name_table) + (k : shim_callback) : shim_callback = + tabled_names actual (tabled_tags ~actual ~builtin k) diff --git a/lib/olly_trace/dune b/lib/olly_trace/dune index 2a86be3..a83ce90 100644 --- a/lib/olly_trace/dune +++ b/lib/olly_trace/dune @@ -1,17 +1,3 @@ (library (name olly_trace) (libraries olly_common olly_format_backend)) - -(rule - (target olly_custom_events.ml) - (enabled_if - (>= %{ocaml_version} 5.1.0)) - (action - (copy olly_custom_events.yes.ml %{target}))) - -(rule - (target olly_custom_events.ml) - (enabled_if - (< %{ocaml_version} 5.1.0)) - (action - (copy olly_custom_events.no.ml %{target}))) diff --git a/lib/olly_trace/olly_custom_events.no.ml b/lib/olly_trace/olly_custom_events.no.ml deleted file mode 100644 index 63c3dac..0000000 --- a/lib/olly_trace/olly_custom_events.no.ml +++ /dev/null @@ -1 +0,0 @@ -let v _tracer cb = cb diff --git a/lib/olly_trace/olly_custom_events.yes.ml b/lib/olly_trace/olly_custom_events.yes.ml deleted file mode 100644 index 0daf77a..0000000 --- a/lib/olly_trace/olly_custom_events.yes.ml +++ /dev/null @@ -1,25 +0,0 @@ -module Trace = Olly_format_backend -open Trace.Event -open Runtime_events - -let emit tracer get_kind ring_id ts ev value = - Trace.emit tracer - { - name = User.name ev; - ts = Timestamp.to_int64 ts; - ring_id; - kind = get_kind value; - } - -let from_int x = Counter x -let from_unit () = Instant - -let from_span (s : Type.span) = - match s with Begin -> SpanBegin | End -> SpanEnd - -let v tracer cb = - let open Runtime_events in - cb - |> Callbacks.add_user_event Type.span (emit tracer from_span) - |> Callbacks.add_user_event Type.int (emit tracer from_int) - |> Callbacks.add_user_event Type.unit (emit tracer from_unit) diff --git a/lib/olly_trace/olly_format_backend/dune b/lib/olly_trace/olly_format_backend/dune index 8a7bad9..076a378 100644 --- a/lib/olly_trace/olly_format_backend/dune +++ b/lib/olly_trace/olly_format_backend/dune @@ -1,6 +1,7 @@ (library (name olly_format_backend) - (modules olly_format_backend event)) + (modules olly_format_backend) + (libraries olly_rte_shim)) (library (name olly_format_json) diff --git a/lib/olly_trace/olly_format_backend/event.ml b/lib/olly_trace/olly_format_backend/event.ml deleted file mode 100644 index 4552835..0000000 --- a/lib/olly_trace/olly_format_backend/event.ml +++ /dev/null @@ -1,3 +0,0 @@ -type kind = .. -type kind += SpanBegin | SpanEnd | Instant | Counter of int -type t = { ring_id : int; ts : int64; name : string; kind : kind } diff --git a/lib/olly_trace/olly_format_backend/olly_format_backend.ml b/lib/olly_trace/olly_format_backend/olly_format_backend.ml index 9020c10..9fe9b8d 100644 --- a/lib/olly_trace/olly_format_backend/olly_format_backend.ml +++ b/lib/olly_trace/olly_format_backend/olly_format_backend.ml @@ -1,3 +1,7 @@ +module Event = Olly_rte_shim.Event + +type event = Event.event + module type Format = sig type trace @@ -5,11 +9,11 @@ module type Format = sig val description : string (* description for documentation *) val create : filename:string -> trace val close : trace -> unit - val emit : trace -> Event.t -> unit + val emit : trace -> event -> unit end type format = (module Format) -type trace = { close : unit -> unit; emit : Event.t -> unit } +type trace = { close : unit -> unit; emit : event -> unit } let name (module Fmt : Format) = Fmt.name let description (module Fmt : Format) = Fmt.description @@ -20,5 +24,3 @@ let create (module Fmt : Format) ~filename = let close (trace : trace) = trace.close () let emit (trace : trace) event = trace.emit event - -module Event = Event diff --git a/lib/olly_trace/olly_trace.ml b/lib/olly_trace/olly_trace.ml index 5ad851c..77d505d 100644 --- a/lib/olly_trace/olly_trace.ml +++ b/lib/olly_trace/olly_trace.ml @@ -1,35 +1,11 @@ module Format = Olly_format_backend let trace fmt trace_filename exec_args = - let open Format.Event in let tracer = Format.create fmt ~filename:trace_filename in - let runtime_phase kind ring_id ts phase = - Format.emit tracer - { - name = Runtime_events.runtime_phase_name phase; - ts = Runtime_events.Timestamp.to_int64 ts; - ring_id; - kind; - } - in - let runtime_begin = runtime_phase SpanBegin - and runtime_end = runtime_phase SpanEnd + let handler evt = Format.emit tracer evt and init () = () - and cleanup () = Format.close tracer - and extra = Olly_custom_events.v tracer - and lifecycle _ _ _ _ = () in - let open Olly_common.Launch in - olly - { - empty_config with - extra; - runtime_begin; - runtime_end; - lifecycle; - init; - cleanup; - } - exec_args + and cleanup () = Format.close tracer in + Olly_common.Launch.olly { handler; init; cleanup } exec_args let trace_cmd format_list = let open Cmdliner in @@ -65,4 +41,4 @@ let trace_cmd format_list = in let doc = "Save the runtime trace to file." in let info = Cmd.info "trace" ~doc ~sdocs ~man in - Cmd.v info Term.(const trace $ format_option $ trace_filename $ exec_args 1) + Cmd.v info Term.(const trace $ format_option $ trace_filename $ common_args 1)