package trace
- Overview
- No Docs
You can search for identifiers within the package.
in-package search v0.2.0
Install
    
    dune-project
 Dependency
Authors
Maintainers
Sources
sha256=97cc4159b96429adc01a84bff1ed34b8f06746bc56a40a214a6306036be2df38
    
    
  sha512=6a67ea9ddeebb4b93a0b8dba9ed26d95e786722d08fd9ca7d8e2db7651a9b9d6ccc63cc437b4eb71c28b3ec51838716a84707a8d366abb595f32a5e65035e28b
    
    
  doc/README.html
Trace
This small library provides basic types that can be used to instrument a library or application, either by hand or via a ppx.
Features
- spans
- messages
- counters
- other metrics?
- ppx to help instrumentation
Usage
To instrument your code, you can simply add trace to your dune/opam files, and then write code like such:
let f x =
  Trace.with_span ~__FILE__ ~__LINE__ "inside-f" @@ fun _sp ->
  (* … code for f *)
let g x =
  Trace.with_span ~__FILE__ ~__LINE__ "inside-g" @@ fun _sp ->
  let y = f x in
  (* … code for f *)
let () =
  Some_trace_backend.setup () @@ fun () ->
  let result = g 42 in
  print_result resultThe file test/t1.ml follows this pattern, using trace-tef as a simple backend that emits one JSON object per span/message:
let run () =
  Trace.set_process_name "main";
  Trace.set_thread_name "t1";
  let n = ref 0 in
  for _i = 1 to 50 do
    Trace.with_span ~__FILE__ ~__LINE__ "outer.loop" @@ fun _sp ->
    for _j = 2 to 5 do
      incr n;
      Trace.with_span ~__FILE__ ~__LINE__ "inner.loop" @@ fun _sp ->
      Trace.messagef (fun k -> k "hello %d %d" _i _j);
      Trace.message "world";
      Trace.counter_int "n" !n
    done
  done
let () =
  Trace_tef.with_setup ~out:(`File "trace.json") () @@ fun () ->
  run ()After running this, the file "trace.json" will contain something like:
[{"pid":2,"name":"process_name","ph":"M","args": {"name":"main"}},
{"pid":2,"tid": 3,"name":"thread_name","ph":"M","args": {"name":"t1"}},
{"pid":2,"cat":"","tid": 3,"ts": 2.00,"name":"hello 1 2","ph":"I"},
{"pid":2,"cat":"","tid": 3,"ts": 3.00,"name":"world","ph":"I"},
{"pid":2,"tid":3,"ts":4.00,"name":"c","ph":"C","args": {"n":1}},
…Opening it in https://ui.perfetto.dev we get something like this:

ppx_trace
On OCaml >= 4.12, and with ppxlib installed, you can install ppx_trace. This is a preprocessor that will rewrite like so:
let%trace f x y z =
  do_sth x;
  do_sth y;
  begin
    let%trace () = "sub-span" in
    do_sth z
  endThis more or less corresponds to:
let f x y z =
  let _trace_span = Trace_core.enter_span ~__FILE__ ~__LINE__ "Foo.f" in
  match
    do_sth x;
    do_sth y;
    begin
      let _trace_span = Trace_core.enter_span ~__FILE__ ~__LINE__ "sub-span" in
      match do_sth z with
      | res ->
        Trace_core.exit_span _trace_span;
        res
      | exception e ->
        Trace_core.exit_span _trace_span
        raise e
    end;
  with
  | res ->
    Trace_core.exit_span _trace_span
    res
  | exception e ->
    Trace_core.exit_span _trace_span
    raise eAlternatively, a name can be provided for the span, which is useful if you want to access it and use functions like Trace.add_data_to_span:
let%trace f x y z =
  do_sth x;
  do_sth y;
  begin
    let%trace _sp = "sub-span" in
    do_sth z;
    Trace.add_data_to_span _sp ["x", `Int 42]
  endDune configuration
In your library or executable stanza, add: (preprocess (pps ppx_trace)). The dependency on trace.core is automatically added. You still need to configure a backend to actually do collection.
Backends
Concrete tracing or observability formats such as:
- Fuchsia (see the spec and tracing. Can be opened in https://ui.perfetto.dev)
- Catapult - light bindings here with trace-tef. (Can be opened in https://ui.perfetto.dev)
- richer bindings with ocaml-catapult, with multi-process backends, etc.
 
- light bindings here with 
- Tracy (see ocaml-tracy, more specifically tracy-client.trace)
- Opentelemetry (see ocaml-opentelemetry, in opentelemetry.trace)
- landmarks?
- Logs (only for messages, obviously)