mirror of
https://github.com/ocaml-tracing/ocaml-trace.git
synced 2026-03-07 18:37:56 -05:00
remove subscriber entirely
This commit is contained in:
parent
4b4569f956
commit
481b5a10b2
4 changed files with 0 additions and 407 deletions
|
|
@ -1,114 +0,0 @@
|
||||||
(** 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 custom callbacks … *)
|
|
||||||
end
|
|
||||||
]}
|
|
||||||
|
|
||||||
{b NOTE}: the [trace_id] passed alongside manual spans is guaranteed to be
|
|
||||||
at least 64 bits. *)
|
|
||||||
|
|
||||||
open Trace_core
|
|
||||||
|
|
||||||
type 'st t = {
|
|
||||||
on_init: 'st -> time_ns:int64 -> unit;
|
|
||||||
(** Called when the subscriber is initialized in a collector *)
|
|
||||||
new_span_id: 'st -> Span_sub.span_id;
|
|
||||||
(** How to generate a new span ID?
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
new_trace_id: 'st -> Span_sub.trace_id;
|
|
||||||
(** How to generate a new trace ID?
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
on_shutdown: 'st -> time_ns:int64 -> unit;
|
|
||||||
(** Called when the collector is shutdown *)
|
|
||||||
on_enter_span: 'st -> Span_sub.t -> unit; (** Enter a span *)
|
|
||||||
on_exit_span: 'st -> time_ns:int64 -> tid:int -> Span_sub.t -> unit;
|
|
||||||
(** Exit a span. This and [on_enter_span] must follow strict stack
|
|
||||||
discipline.
|
|
||||||
@param tid the id of the thread on which the span was exited. *)
|
|
||||||
on_message:
|
|
||||||
'st ->
|
|
||||||
time_ns:int64 ->
|
|
||||||
tid:int ->
|
|
||||||
span:Span_sub.t option ->
|
|
||||||
params:extension_parameter list ->
|
|
||||||
data:(string * Trace_core.user_data) list ->
|
|
||||||
string ->
|
|
||||||
unit;
|
|
||||||
(** Emit a log message *)
|
|
||||||
on_counter:
|
|
||||||
'st ->
|
|
||||||
time_ns:int64 ->
|
|
||||||
tid:int ->
|
|
||||||
params:extension_parameter list ->
|
|
||||||
data:(string * Trace_core.user_data) list ->
|
|
||||||
name:string ->
|
|
||||||
float ->
|
|
||||||
unit;
|
|
||||||
(** Emit the current value of a counter *)
|
|
||||||
on_extension_event: 'st -> time_ns:int64 -> tid:int -> extension_event -> unit;
|
|
||||||
(** Extension event
|
|
||||||
@since 0.8 *)
|
|
||||||
}
|
|
||||||
(** Callbacks for a subscriber. There is one callback per event in {!Trace}. The
|
|
||||||
type ['st] is the state that is passed to every single callback. *)
|
|
||||||
|
|
||||||
(** Dummy callbacks. It can be useful to reuse some of these functions in a real
|
|
||||||
subscriber that doesn't want to handle {b all} events, but only some of
|
|
||||||
them.
|
|
||||||
|
|
||||||
To write a subscriber that only supports some callbacks, this can be handy:
|
|
||||||
{[
|
|
||||||
module My_callbacks = struct
|
|
||||||
type st = my_own_state
|
|
||||||
include Callbacks.Dummy
|
|
||||||
let on_counter (st:st) ~time_ns ~tid ~data ~name v : unit = ...
|
|
||||||
end
|
|
||||||
]} *)
|
|
||||||
module Dummy = struct
|
|
||||||
let on_init _ ~time_ns:_ = ()
|
|
||||||
let new_span_id _ = Int64.min_int
|
|
||||||
let new_trace_id _ = -1L
|
|
||||||
let on_shutdown _ ~time_ns:_ = ()
|
|
||||||
let on_message _ ~time_ns:_ ~tid:_ ~span:_ ~params:_ ~data:_ _msg = ()
|
|
||||||
let on_counter _ ~time_ns:_ ~tid:_ ~params:_ ~data:_ ~name:_ _v = ()
|
|
||||||
let on_enter_span _ _sp = ()
|
|
||||||
let on_exit_span _ ~time_ns:_ ~tid:_ _ = ()
|
|
||||||
let on_extension_event _ ~time_ns:_ ~tid:_ _ = ()
|
|
||||||
end
|
|
||||||
|
|
||||||
(** Build a set of callbacks.
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
let make ~new_span_id ?(new_trace_id = Dummy.new_trace_id)
|
|
||||||
?(on_init = Dummy.on_init) ?(on_enter_span = Dummy.on_enter_span)
|
|
||||||
?(on_exit_span = Dummy.on_exit_span) ?(on_message = Dummy.on_message)
|
|
||||||
?(on_counter = Dummy.on_counter)
|
|
||||||
?(on_extension_event = Dummy.on_extension_event)
|
|
||||||
?(on_shutdown = Dummy.on_shutdown) () : _ t =
|
|
||||||
{
|
|
||||||
on_init;
|
|
||||||
new_span_id;
|
|
||||||
new_trace_id;
|
|
||||||
on_enter_span;
|
|
||||||
on_exit_span;
|
|
||||||
on_message;
|
|
||||||
on_counter;
|
|
||||||
on_extension_event;
|
|
||||||
on_shutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
(** Dummy callbacks, ignores all events. *)
|
|
||||||
let dummy () : _ t = make ~new_span_id:(fun () -> Span_sub.dummy_span_id) ()
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
(** Trace subscribers *)
|
|
||||||
|
|
||||||
(** A trace subscriber. It pairs a set of callbacks with the state they need
|
|
||||||
(which can contain a file handle, a socket to write events to, config,
|
|
||||||
etc.).
|
|
||||||
|
|
||||||
The design goal for this is that it should be possible to avoid allocations
|
|
||||||
whenever the trace collector invokes the callbacks. *)
|
|
||||||
type t =
|
|
||||||
| Sub : {
|
|
||||||
st: 'st;
|
|
||||||
callbacks: 'st Callbacks.t;
|
|
||||||
}
|
|
||||||
-> t
|
|
||||||
|
|
||||||
(** Dummy subscriber that ignores every call. *)
|
|
||||||
let dummy : t = Sub { st = (); callbacks = Callbacks.dummy () }
|
|
||||||
|
|
||||||
open struct
|
|
||||||
type st = t array
|
|
||||||
|
|
||||||
let new_span_id (st : st) =
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st 0 in
|
|
||||||
cb.new_span_id st
|
|
||||||
|
|
||||||
let new_trace_id st =
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st 0 in
|
|
||||||
cb.new_trace_id st
|
|
||||||
|
|
||||||
let on_init st ~time_ns =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_init st ~time_ns
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_shutdown st ~time_ns =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_shutdown st ~time_ns
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_enter_span st span =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_enter_span st span
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_exit_span st ~time_ns ~tid span =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_exit_span st ~time_ns ~tid span
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_message st ~time_ns ~tid ~span ~params ~data msg =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_message st ~time_ns ~tid ~span ~params ~data msg
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_counter st ~time_ns ~tid ~params ~data ~name n =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_counter st ~time_ns ~tid ~params ~data ~name n
|
|
||||||
done
|
|
||||||
|
|
||||||
let on_extension_event st ~time_ns ~tid ev : unit =
|
|
||||||
for i = 0 to Array.length st - 1 do
|
|
||||||
let (Sub { st; callbacks = cb }) = Array.get st i in
|
|
||||||
cb.on_extension_event st ~time_ns ~tid ev
|
|
||||||
done
|
|
||||||
|
|
||||||
let tee_cb : t array Callbacks.t =
|
|
||||||
{
|
|
||||||
Callbacks.on_init;
|
|
||||||
new_span_id;
|
|
||||||
new_trace_id;
|
|
||||||
on_enter_span;
|
|
||||||
on_exit_span;
|
|
||||||
on_message;
|
|
||||||
on_counter;
|
|
||||||
on_extension_event;
|
|
||||||
on_shutdown;
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
(** Tee multiple subscribers, ie return a subscriber that forwards to every
|
|
||||||
subscriber in [subs].
|
|
||||||
|
|
||||||
To generate a new span or trace ID, the first subscriber of the list is
|
|
||||||
used. *)
|
|
||||||
let tee_l (subs : t list) : t =
|
|
||||||
match subs with
|
|
||||||
| [] -> dummy
|
|
||||||
| [ s ] -> s
|
|
||||||
| l -> Sub { st = Array.of_list l; callbacks = tee_cb }
|
|
||||||
|
|
||||||
(** [tee s1 s2] is a subscriber that forwards every call to [s1] and [s2] both.
|
|
||||||
*)
|
|
||||||
let tee (s1 : t) (s2 : t) : t = tee_l [ s1; s2 ]
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
open Trace_core
|
|
||||||
|
|
||||||
type t = Collector.t
|
|
||||||
|
|
||||||
module Private_ = struct
|
|
||||||
let mock = ref false
|
|
||||||
let get_now_ns_ = ref Time_.get_time_ns
|
|
||||||
let get_tid_ = ref Thread_.get_tid
|
|
||||||
|
|
||||||
(** Now, in nanoseconds *)
|
|
||||||
let[@inline] now_ns () : int64 =
|
|
||||||
if !mock then
|
|
||||||
!get_now_ns_ ()
|
|
||||||
else
|
|
||||||
Time_.get_time_ns ()
|
|
||||||
|
|
||||||
let[@inline] tid_ () : int =
|
|
||||||
if !mock then
|
|
||||||
!get_tid_ ()
|
|
||||||
else
|
|
||||||
Thread_.get_tid ()
|
|
||||||
end
|
|
||||||
|
|
||||||
open struct
|
|
||||||
module A = Trace_core.Internal_.Atomic_
|
|
||||||
open Private_
|
|
||||||
|
|
||||||
type Trace_core.span += Span_sub of Span_sub.t
|
|
||||||
|
|
||||||
let enter_span (Subscriber.Sub { st; callbacks = cb }) ~__FUNCTION__ ~__FILE__
|
|
||||||
~__LINE__ ~params ~data ~parent name : span =
|
|
||||||
let id = cb.new_span_id st in
|
|
||||||
let tid = tid_ () in
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
|
|
||||||
let trace_id =
|
|
||||||
match parent with
|
|
||||||
| P_some (Span_sub span) -> span.trace_id
|
|
||||||
| _ -> cb.new_trace_id st
|
|
||||||
in
|
|
||||||
|
|
||||||
let flavor = ref `Sync in
|
|
||||||
List.iter
|
|
||||||
(function
|
|
||||||
| Core_ext.Extension_span_flavor f -> flavor := f
|
|
||||||
| _ -> ())
|
|
||||||
params;
|
|
||||||
|
|
||||||
let span : Span_sub.t =
|
|
||||||
{
|
|
||||||
name;
|
|
||||||
id;
|
|
||||||
tid;
|
|
||||||
__FUNCTION__;
|
|
||||||
__FILE__;
|
|
||||||
__LINE__;
|
|
||||||
data;
|
|
||||||
parent;
|
|
||||||
trace_id;
|
|
||||||
flavor = !flavor;
|
|
||||||
params;
|
|
||||||
time_ns;
|
|
||||||
time_exit_ns = Int64.max_int;
|
|
||||||
}
|
|
||||||
in
|
|
||||||
|
|
||||||
cb.on_enter_span st span;
|
|
||||||
|
|
||||||
Span_sub span
|
|
||||||
|
|
||||||
let exit_span (Subscriber.Sub { st; callbacks = cb }) span : unit =
|
|
||||||
match span with
|
|
||||||
| Span_sub span ->
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
span.time_exit_ns <- time_ns;
|
|
||||||
let tid = tid_ () in
|
|
||||||
cb.on_exit_span st ~time_ns ~tid span
|
|
||||||
| _ -> ()
|
|
||||||
|
|
||||||
let add_data_to_span _sub span data =
|
|
||||||
match span with
|
|
||||||
| Span_sub span -> span.data <- List.rev_append data span.data
|
|
||||||
| _ -> ()
|
|
||||||
|
|
||||||
let message (Subscriber.Sub { st; callbacks = cb }) ~params ~data ~span msg :
|
|
||||||
unit =
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
let tid = tid_ () in
|
|
||||||
let span =
|
|
||||||
match span with
|
|
||||||
| Some (Span_sub s) -> Some s
|
|
||||||
| _ -> None
|
|
||||||
in
|
|
||||||
cb.on_message st ~time_ns ~tid ~span ~params ~data msg
|
|
||||||
|
|
||||||
let counter_float (Subscriber.Sub { st; callbacks = cb }) ~params ~data name f
|
|
||||||
: unit =
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
let tid = tid_ () in
|
|
||||||
cb.on_counter st ~tid ~time_ns ~params ~data ~name f
|
|
||||||
|
|
||||||
let[@inline] counter_int sub ~params ~data name i =
|
|
||||||
counter_float sub ~params ~data name (float_of_int i)
|
|
||||||
|
|
||||||
let init (Subscriber.Sub { st; callbacks = cb }) =
|
|
||||||
(* init code *)
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
cb.on_init st ~time_ns
|
|
||||||
|
|
||||||
let shutdown (Subscriber.Sub { st; callbacks = cb }) =
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
cb.on_shutdown st ~time_ns
|
|
||||||
|
|
||||||
let extension_event (Subscriber.Sub { st; callbacks = cb }) ev =
|
|
||||||
let tid = tid_ () in
|
|
||||||
let time_ns = now_ns () in
|
|
||||||
cb.on_extension_event st ~time_ns ~tid ev
|
|
||||||
|
|
||||||
(* TODO: do we want to track this? *)
|
|
||||||
let current_span _ = None
|
|
||||||
|
|
||||||
let coll_cbs : t Collector.Callbacks.t =
|
|
||||||
Collector.Callbacks.make ~enter_span ~exit_span ~current_span ~message
|
|
||||||
~add_data_to_span ~counter_int ~counter_float ~extension:extension_event
|
|
||||||
~init ~shutdown ()
|
|
||||||
end
|
|
||||||
|
|
||||||
(** A collector that calls the callbacks of subscriber *)
|
|
||||||
let collector (self : Subscriber.t) : collector =
|
|
||||||
Collector.C_some (self, coll_cbs)
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
(** Generic subscribers.
|
|
||||||
|
|
||||||
This defines the notion of a {b subscriber}, a set of callbacks for every
|
|
||||||
trace event. It also defines a collector that needs to be installed for the
|
|
||||||
subscriber(s) to be called.
|
|
||||||
|
|
||||||
Thanks to {!Subscriber.tee_l} it's possible to combine multiple subscribers
|
|
||||||
into a single collector.
|
|
||||||
|
|
||||||
@since 0.8 *)
|
|
||||||
|
|
||||||
module Callbacks = Callbacks
|
|
||||||
module Subscriber = Subscriber
|
|
||||||
module Span_sub = Span_sub
|
|
||||||
|
|
||||||
(** {2 Main API} *)
|
|
||||||
|
|
||||||
type t = Subscriber.t
|
|
||||||
(** A trace subscriber. It pairs a set of callbacks with the state they need
|
|
||||||
(which can contain a file handle, a socket to write events to, config,
|
|
||||||
etc.).
|
|
||||||
|
|
||||||
The design goal for this is that it should be possible to avoid allocations
|
|
||||||
whenever the trace collector invokes the callbacks. *)
|
|
||||||
|
|
||||||
val collector : t -> Trace_core.collector
|
|
||||||
(** A collector that calls the subscriber's callbacks. It uses [mtime] (if
|
|
||||||
available) to obtain timestamps. *)
|
|
||||||
|
|
||||||
(** A counter-based span generator.
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
module Span_id_generator : sig
|
|
||||||
type t
|
|
||||||
|
|
||||||
val create : unit -> t
|
|
||||||
val gen : t -> Span_sub.span_id
|
|
||||||
end
|
|
||||||
|
|
||||||
(** A counter-based generator.
|
|
||||||
@since NEXT_RELEASE *)
|
|
||||||
module Trace_id_generator : sig
|
|
||||||
type t
|
|
||||||
|
|
||||||
val create : unit -> t
|
|
||||||
val gen : t -> Span_sub.trace_id
|
|
||||||
end
|
|
||||||
|
|
||||||
(**/**)
|
|
||||||
|
|
||||||
module Private_ : sig
|
|
||||||
val mock : bool ref
|
|
||||||
(** Global mock flag. If enable, all timestamps, tid, etc should be faked. *)
|
|
||||||
|
|
||||||
val get_now_ns_ : (unit -> int64) ref
|
|
||||||
(** The callback used to get the current timestamp *)
|
|
||||||
|
|
||||||
val get_tid_ : (unit -> int) ref
|
|
||||||
(** The callback used to get the current thread's id *)
|
|
||||||
|
|
||||||
val now_ns : unit -> int64
|
|
||||||
(** Get the current timestamp, or a mock version *)
|
|
||||||
end
|
|
||||||
|
|
||||||
(**/**)
|
|
||||||
Loading…
Add table
Reference in a new issue