package trace

  1. Overview
  2. Docs
A stub for tracing/observability, agnostic in how data is collected

Install

Dune Dependency

Authors

Maintainers

Sources

trace-0.4.tbz
sha256=b51ec546ec1c90f6ed60b330ea7c9212d5c9c26e4d93e38e60224d984fab09b1
sha512=dc617857b0f213765b82b45281ebef2fab4b8c213597f19cf4476356e2c7295c3aeb0d71c8d1954617196d7c491336efba1c67f02138d011ac590053c06ed638

Description

README

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

  • [x] spans

  • [x] messages

  • [x] counters

  • [ ] other metrics?

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 result

The 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:

Backends

Concrete tracing or observability formats such as:

  • [ ] Fuchsia (see tracing)

  • Catapult

    • [x] light bindings here with trace-tef

    • [ ] richer bindings with ocaml-catapult, with multi-process backends, etc.

  • [x] Tracy (see ocaml-tracy, more specifically tracy-client.trace)

  • [x] Opentelemetry (see ocaml-opentelemetry, in opentelemetry.trace)

  • [ ] landmarks?

  • [ ] Logs (only for messages, obviously)

Dependencies (2)

  1. dune >= "2.9"
  2. ocaml >= "4.08"

Dev Dependencies (1)

  1. odoc with-doc

Used by (4)

  1. linol >= "0.5"
  2. moonpool >= "0.2"
  3. trace-tef = "0.4"
  4. tracy-client >= "0.3"

Conflicts

None