docs, readme

This commit is contained in:
Simon Cruanes 2024-09-17 11:08:54 -04:00
parent 11d313df18
commit 27d4f59523
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
7 changed files with 62 additions and 10 deletions

View file

@ -32,6 +32,11 @@ jobs:
dune-cache: true dune-cache: true
allow-prerelease-opam: true allow-prerelease-opam: true
# check that trace compiles with no optional deps
- run: opam install -t trace --deps-only
- run: opam exec -- dune build '@install' -p trace
# install all packages
- run: opam install -t trace trace-tef trace-fuchsia --deps-only - run: opam install -t trace trace-tef trace-fuchsia --deps-only
- run: opam install ppx_trace --deps-only # no tests - run: opam install ppx_trace --deps-only # no tests
if: matrix.ocaml-compiler != '4.08.x' if: matrix.ocaml-compiler != '4.08.x'

View file

@ -150,9 +150,18 @@ Concrete tracing or observability formats such as:
* [x] backend for [tldrs](https://github.com/imandra-ai/tldrs), a * [x] backend for [tldrs](https://github.com/imandra-ai/tldrs), a
small rust daemon that aggregates TEF traces from multiple processes/clients small rust daemon that aggregates TEF traces from multiple processes/clients
into a single `.jsonl` file into a single `.jsonl` file
* [ ] richer bindings with [ocaml-catapult](https://github.com/imandra-ai/catapult), * [x] [tldrs](https://github.com/imandra-ai/tldrs), to collect TEF traces from multiple processes in a clean way.
with multi-process backends, etc. This requires the rust `tldrs` program to be in path.
* ~~[ ] richer bindings with [ocaml-catapult](https://github.com/imandra-ai/catapult),
with multi-process backends, etc.~~ (subsumed by tldrs)
- [x] Tracy (see [ocaml-tracy](https://github.com/imandra-ai/ocaml-tracy), more specifically `tracy-client.trace`) - [x] Tracy (see [ocaml-tracy](https://github.com/imandra-ai/ocaml-tracy), more specifically `tracy-client.trace`)
- [x] Opentelemetry (see [ocaml-opentelemetry](https://github.com/imandra-ai/ocaml-opentelemetry/), in `opentelemetry.trace`) - [x] Opentelemetry (see [ocaml-opentelemetry](https://github.com/imandra-ai/ocaml-opentelemetry/), in `opentelemetry.trace`)
- [ ] landmarks? - [ ] landmarks?
- [ ] Logs (only for messages, obviously) - [ ] Logs (only for messages, obviously)
## Subscribers
The library `trace.subscriber` defines composable _subscribers_, which are sets of callbacks
that consume tracing events.
Multiple subscribers can be aggregated together (with events being dispatched to all of them)
and be installed as a normal _collector_.

View file

@ -1,3 +1,23 @@
(** Callbacks used for subscribers.
Each subscriber defines a set of callbacks, for each possible
tracing event. These callbacks take a custom state that is paired
with the callbacks in {!Subscriber.t}.
To use a default implementation for some callbacks, use:
{[
module My_callbacks = struct
type st =
include Trace_subscriber.Callbacks.Dummy
let on_init (state:st) ~time_ns : unit =
(* other customize callbacks *)
end ]}
*)
open Trace_core open Trace_core
open Types open Types
@ -119,7 +139,7 @@ module Dummy = struct
() ()
end end
(** Dummy callbacks, do nothing. *) (** Dummy callbacks, ignores all events. *)
let dummy (type st) () : st t = let dummy (type st) () : st t =
let module M = struct let module M = struct
type nonrec st = st type nonrec st = st

View file

@ -1,9 +1,11 @@
(** Trace subscribers *)
(** A trace subscriber. It pairs a set of callbacks (** A trace subscriber. It pairs a set of callbacks
with the state they need (which can contain a file handle, with the state they need (which can contain a file handle,
a socket, config, etc.). a socket to write events to, config, etc.).
The design goal for this is that it should be possible to avoid allocations The design goal for this is that it should be possible to avoid allocations
when the trace collector calls the callbacks. *) whenever the trace collector invokes the callbacks. *)
type t = type t =
| Sub : { | Sub : {
st: 'st; st: 'st;
@ -102,3 +104,12 @@ end
let tee (s1 : t) (s2 : t) : t = let tee (s1 : t) (s2 : t) : t =
let st = s1, s2 in let st = s1, s2 in
Sub { st; callbacks = (module Tee_cb) } Sub { st; callbacks = (module Tee_cb) }
(** Tee multiple subscribers, ie return a subscriber that forwards
to all the subscribers in [subs]. *)
let rec tee_l (subs : t list) : t =
match subs with
| [] -> dummy
| [ s ] -> s
| [ s1; s2 ] -> tee s1 s2
| s1 :: s2 :: tl -> tee (tee s1 s2) (tee_l tl)

View file

@ -13,9 +13,7 @@ module Private_ = struct
let[@inline] now_ns () : float = let[@inline] now_ns () : float =
match !get_now_ns_ with match !get_now_ns_ with
| Some f -> f () | Some f -> f ()
| None -> | None -> Time_.get_time_ns ()
let t = Mtime_clock.now () in
Int64.to_float (Mtime.to_uint64_ns t)
let[@inline] tid_ () : int = let[@inline] tid_ () : int =
match !get_tid_ with match !get_tid_ with

View file

@ -15,13 +15,17 @@ include module type of struct
include Types include Types
end end
(** {2 Main API} *)
type t = Subscriber.t type t = Subscriber.t
val collector : t -> Trace_core.collector val collector : t -> Trace_core.collector
(** A collector that calls the subscriber's callbacks.
It uses [mtime] (if available) to obtain timestamps. *)
(**/**) (**/**)
(**/*)
module Private_ : sig module Private_ : sig
val get_now_ns_ : (unit -> float) option ref val get_now_ns_ : (unit -> float) option ref
(** The callback used to get the current timestamp *) (** The callback used to get the current timestamp *)
@ -31,3 +35,5 @@ module Private_ : sig
val now_ns : unit -> float val now_ns : unit -> float
end end
(**/**)

View file

@ -1,10 +1,13 @@
(** Some core types for subscribers. *)
type user_data = type user_data =
| U_bool of bool | U_bool of bool
| U_float of float | U_float of float
| U_int of int | U_int of int
| U_none | U_none
| U_string of string | U_string of string
(** A non polymorphic-variant version of {!Trace_core.user_data} *)
type flavor = type flavor =
| Sync | Sync
| Async | Async (** A non polymorphic-variant version of {!Trace_core.flavor} *)