remove trace_id entirely, use meta-maps in more places

The direct use of span_id+trace_id in OTEL is a bad idea, and it makes
little sense in other collectors. In the end, `span` should be thought
of as an opaque key only the collector understands, and a meta-map
should be carried around for the collector to stash additional info such
as a (8B, 16B, ...) trace ID or other information.
This commit is contained in:
Simon Cruanes 2025-12-12 10:10:09 -05:00
parent ef35cc1d79
commit 8b747053d7
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
12 changed files with 118 additions and 121 deletions

View file

@ -7,13 +7,11 @@
open Types open Types
let dummy_span : span = Int64.min_int let dummy_span : span = Int64.min_int
let dummy_trace_id : trace_id = "<dummy>"
let dummy_explicit_span : explicit_span = let dummy_explicit_span : explicit_span =
{ span = dummy_span; trace_id = dummy_trace_id; meta = Meta_map.empty } { span = dummy_span; meta = Meta_map.empty }
let dummy_explicit_span_ctx : explicit_span_ctx = let dummy_explicit_span_ctx : explicit_span_ctx = { meta = Meta_map.empty }
{ span = dummy_span; trace_id = dummy_trace_id }
(** Signature for a collector. (** Signature for a collector.

View file

@ -18,7 +18,7 @@ let current_level_ = A.make Level.Trace
(* ## implementation ## *) (* ## implementation ## *)
let[@inline] ctx_of_span (sp : explicit_span) : explicit_span_ctx = let[@inline] ctx_of_span (sp : explicit_span) : explicit_span_ctx =
{ span = sp.span; trace_id = sp.trace_id } { meta = sp.meta }
let data_empty_build_ () = [] let data_empty_build_ () = []

View file

@ -1,13 +1,13 @@
(** Common types definitions.
The type [trace_id] was added in 0.10 and removed in NEXT_RELEASE, as it's
simply more flexible to use a meta-map ([Hmap.t] in the better case). *)
type span = int64 type span = int64
(** A span identifier. (** A span identifier.
The meaning of the identifier depends on the collector. *) The meaning of the identifier depends on the collector. *)
type trace_id = string
(** A bytestring representing a (possibly distributed) trace made of async
spans. With opentelemetry this is 16 bytes.
@since 0.10 *)
type user_data = type user_data =
[ `Int of int [ `Int of int
| `String of string | `String of string
@ -26,17 +26,24 @@ type span_flavor =
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
type explicit_span_ctx = { type explicit_span_ctx = {
span: span; (** The current span *) meta: Meta_map.t;
trace_id: trace_id; (** The trace this belongs to *) (** Metadata for this span and its context. This can be used to store
trace IDs, attributes, etc. in a collector-specific way. *)
} }
(** A context, passed around for async traces. [@@unboxed]
@since 0.10 *) (** A context, passed around for async traces. It might not correspond to any
span created via [Trace] at all, e.g. it might be built in a HTTP handler
from a {{:https://www.w3.org/TR/trace-context/} W3C trace contxt} header.
@since 0.10
The fields [span] and [trace_id] were removed in NEXT_RELEASE. Please use
the meta map instead. *)
type explicit_span = { type explicit_span = {
span: span; span: span;
(** Identifier for this span. Several explicit spans might share the same (** Identifier for this span. Several explicit spans might share the same
identifier since we can differentiate between them via [meta]. *) identifier since we can differentiate between them via [meta]. *)
trace_id: trace_id; (** The trace this belongs to *)
mutable meta: Meta_map.t; mutable meta: Meta_map.t;
(** Metadata for this span (and its context). This can be used by (** Metadata for this span (and its context). This can be used by
collectors to carry collector-specific information from the beginning collectors to carry collector-specific information from the beginning
@ -44,7 +51,10 @@ type explicit_span = {
} }
(** Explicit span, with collector-specific metadata. This is richer than (** Explicit span, with collector-specific metadata. This is richer than
{!explicit_span_ctx} but not intended to be passed around (or sent across {!explicit_span_ctx} but not intended to be passed around (or sent across
the wire), unlike {!explicit_span_ctx}. *) the wire), unlike {!explicit_span_ctx}.
The field [trace_id] was removed in NEXT_RELEASE, please use the meta map
instead. *)
type extension_event = .. type extension_event = ..
(** An extension event, used to add features that are backend specific or simply (** An extension event, used to add features that are backend specific or simply

View file

@ -37,7 +37,6 @@ type t =
tid: int; tid: int;
name: string; name: string;
time_ns: int64; time_ns: int64;
id: trace_id;
flavor: span_flavor option; flavor: span_flavor option;
fun_name: string option; fun_name: string option;
data: (string * user_data) list; data: (string * user_data) list;
@ -48,7 +47,6 @@ type t =
time_ns: int64; time_ns: int64;
flavor: span_flavor option; flavor: span_flavor option;
data: (string * user_data) list; data: (string * user_data) list;
id: trace_id;
} }
| E_counter of { | E_counter of {
name: string; name: string;

View file

@ -10,14 +10,17 @@ open struct
(* just use the same ones for everyone *) (* just use the same ones for everyone *)
let span_gen = Sub.Span_generator.create () let span_gen = Sub.Span_generator.create ()
let trace_id_gen = Sub.Trace_id_8B_generator.create ()
end end
module Callbacks : Sub.Callbacks.S with type st = event_consumer = struct module Callbacks : Sub.Callbacks.S with type st = event_consumer = struct
type st = event_consumer type st = event_consumer
let new_span (_self : st) = Sub.Span_generator.mk_span span_gen let new_span (_self : st) = Sub.Span_generator.mk_span span_gen
let new_trace_id _self = Sub.Trace_id_8B_generator.mk_trace_id trace_id_gen
let new_explicit_span _self ~parent:_ =
let span = Sub.Span_generator.mk_span span_gen in
{ span; meta = Meta_map.empty }
let on_init (self : st) ~time_ns = self.on_event (E_init { time_ns }) let on_init (self : st) ~time_ns = self.on_event (E_init { time_ns })
let on_shutdown (self : st) ~time_ns = self.on_event (E_shutdown { time_ns }) let on_shutdown (self : st) ~time_ns = self.on_event (E_shutdown { time_ns })
@ -45,16 +48,13 @@ module Callbacks : Sub.Callbacks.S with type st = event_consumer = struct
self.on_event @@ E_counter { name; n = f; time_ns; tid } self.on_event @@ E_counter { name; n = f; time_ns; tid }
let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_ let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_
~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor ~trace_id _span : ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor _span : unit =
unit =
self.on_event self.on_event
@@ E_enter_manual_span @@ E_enter_manual_span { time_ns; tid; data; name; fun_name; flavor }
{ id = trace_id; time_ns; tid; data; name; fun_name; flavor }
let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor
~trace_id (_ : span) : unit = (_ : explicit_span) : unit =
self.on_event self.on_event @@ E_exit_manual_span { tid; name; time_ns; data; flavor }
@@ E_exit_manual_span { tid; id = trace_id; name; time_ns; data; flavor }
let on_extension_event (self : st) ~time_ns ~tid ext : unit = let on_extension_event (self : st) ~time_ns ~tid ext : unit =
self.on_event @@ E_extension_event { tid; time_ns; ext } self.on_event @@ E_extension_event { tid; time_ns; ext }

View file

@ -22,7 +22,8 @@ type t = {
buf_chain: Buf_chain.t; buf_chain: Buf_chain.t;
exporter: Exporter.t; exporter: Exporter.t;
span_gen: Sub.Span_generator.t; span_gen: Sub.Span_generator.t;
trace_id_gen: Sub.Trace_id_8B_generator.t; (* use the span generator, it's also 64 bits *)
trace_id_gen: Sub.Span_generator.t;
} }
(** Subscriber state *) (** Subscriber state *)
@ -49,6 +50,8 @@ open struct
names; names;
flush stderr flush stderr
) )
let k_trace_id : int64 Meta_map.key = Meta_map.Key.create ()
end end
let close (self : t) : unit = let close (self : t) : unit =
@ -76,7 +79,8 @@ let create ?(buf_pool = Buf_pool.create ()) ~pid ~exporter () : t =
pid; pid;
spans = Span_tbl.create (); spans = Span_tbl.create ();
span_gen = Sub.Span_generator.create (); span_gen = Sub.Span_generator.create ();
trace_id_gen = Sub.Trace_id_8B_generator.create (); (* NOTE: we use a span generator because it's also making [int64] values *)
trace_id_gen = Sub.Span_generator.create ();
} }
module Callbacks = struct module Callbacks = struct
@ -84,8 +88,21 @@ module Callbacks = struct
let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen
let new_trace_id self = let get_trace_id_ meta : int64 =
Sub.Trace_id_8B_generator.mk_trace_id self.trace_id_gen try Meta_map.find_exn k_trace_id meta
with _ ->
failwith "fuchsia subscriber: could not find trace_id in meta-map"
let new_explicit_span (self : st) ~(parent : explicit_span_ctx option) :
explicit_span =
let span = Sub.Span_generator.mk_span self.span_gen in
let trace_id =
match parent with
| None -> Sub.Span_generator.mk_span self.trace_id_gen
| Some p -> get_trace_id_ p.meta
in
let meta = Meta_map.(empty |> add k_trace_id trace_id) in
{ span; meta }
let on_init (self : st) ~time_ns:_ = let on_init (self : st) ~time_ns:_ =
Writer.Metadata.Magic_record.encode self.buf_chain; Writer.Metadata.Magic_record.encode self.buf_chain;
@ -164,7 +181,9 @@ module Callbacks = struct
write_ready_ self write_ready_ self
let on_enter_manual_span (self : st) ~__FUNCTION__:_ ~__FILE__:_ ~__LINE__:_ let on_enter_manual_span (self : st) ~__FUNCTION__:_ ~__FILE__:_ ~__LINE__:_
~time_ns ~tid ~parent:_ ~data ~name ~flavor:_ ~trace_id _span : unit = ~time_ns ~tid ~parent:_ ~data ~name ~flavor:_ (span : explicit_span) :
unit =
let trace_id = get_trace_id_ span.meta in
Writer.( Writer.(
Event.Async_begin.encode self.buf_chain ~name Event.Async_begin.encode self.buf_chain ~name
~args:(args_of_user_data data) ~args:(args_of_user_data data)
@ -173,7 +192,8 @@ module Callbacks = struct
write_ready_ self write_ready_ self
let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor:_ let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor:_
~trace_id (_ : span) : unit = (span : explicit_span) : unit =
let trace_id = get_trace_id_ span.meta in
Writer.( Writer.(
Event.Async_end.encode self.buf_chain ~name ~args:(args_of_user_data data) Event.Async_end.encode self.buf_chain ~name ~args:(args_of_user_data data)
~t_ref:(Thread_ref.inline ~pid:self.pid ~tid) ~t_ref:(Thread_ref.inline ~pid:self.pid ~tid)

View file

@ -4,15 +4,6 @@
open Common_ open Common_
module Util = Util module Util = Util
open struct
let[@inline] int64_of_trace_id_ (id : Trace_core.trace_id) : int64 =
if id == Trace_core.Collector.dummy_trace_id then
0L
else
Bytes.get_int64_le (Bytes.unsafe_of_string id) 0
end
open Util open Util
type user_data = Trace_core.user_data type user_data = Trace_core.user_data
@ -491,7 +482,7 @@ module Event = struct
+ Arguments.size_word args + 1 (* async id *) + Arguments.size_word args + 1 (* async id *)
let encode (bufs : Buf_chain.t) ~name ~(t_ref : Thread_ref.t) ~time_ns let encode (bufs : Buf_chain.t) ~name ~(t_ref : Thread_ref.t) ~time_ns
~(async_id : Trace_core.trace_id) ~args () : unit = ~(async_id : int64) ~args () : unit =
let name = truncate_string name in let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let@ buf = Buf_chain.with_buf bufs ~available_word:size in let@ buf = Buf_chain.with_buf bufs ~available_word:size in
@ -516,7 +507,7 @@ module Event = struct
Buf.add_string buf name; Buf.add_string buf name;
Arguments.encode buf args; Arguments.encode buf args;
Buf.add_i64 buf (int64_of_trace_id_ async_id); Buf.add_i64 buf async_id;
() ()
end end
@ -527,7 +518,7 @@ module Event = struct
+ Arguments.size_word args + 1 (* async id *) + Arguments.size_word args + 1 (* async id *)
let encode (bufs : Buf_chain.t) ~name ~(t_ref : Thread_ref.t) ~time_ns let encode (bufs : Buf_chain.t) ~name ~(t_ref : Thread_ref.t) ~time_ns
~(async_id : Trace_core.trace_id) ~args () : unit = ~(async_id : int64) ~args () : unit =
let name = truncate_string name in let name = truncate_string name in
let size = size_word ~name ~t_ref ~args () in let size = size_word ~name ~t_ref ~args () in
let@ buf = Buf_chain.with_buf bufs ~available_word:size in let@ buf = Buf_chain.with_buf bufs ~available_word:size in
@ -552,7 +543,7 @@ module Event = struct
Buf.add_string buf name; Buf.add_string buf name;
Arguments.encode buf args; Arguments.encode buf args;
Buf.add_i64 buf (int64_of_trace_id_ async_id); Buf.add_i64 buf async_id;
() ()
end end
end end

View file

@ -35,8 +35,9 @@ module type S = sig
(** How to generate a new span? (** How to generate a new span?
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
val new_trace_id : st -> trace_id val new_explicit_span : st -> parent:explicit_span_ctx option -> explicit_span
(** How to generate a new trace ID? (** How to generate a new explicit span, with meta-map potentially containing
data such as a trace ID or request ID?
@since NEXT_RELEASE *) @since NEXT_RELEASE *)
val on_shutdown : st -> time_ns:int64 -> unit val on_shutdown : st -> time_ns:int64 -> unit
@ -96,12 +97,11 @@ module type S = sig
__LINE__:int -> __LINE__:int ->
time_ns:int64 -> time_ns:int64 ->
tid:int -> tid:int ->
parent:span option -> parent:explicit_span_ctx option ->
data:(string * Trace_core.user_data) list -> data:(string * Trace_core.user_data) list ->
name:string -> name:string ->
flavor:Trace_core.span_flavor option -> flavor:Trace_core.span_flavor option ->
trace_id:trace_id -> explicit_span ->
span ->
unit unit
(** Enter a manual (possibly async) span *) (** Enter a manual (possibly async) span *)
@ -112,8 +112,7 @@ module type S = sig
name:string -> name:string ->
data:(string * Trace_core.user_data) list -> data:(string * Trace_core.user_data) list ->
flavor:Trace_core.span_flavor option -> flavor:Trace_core.span_flavor option ->
trace_id:trace_id -> explicit_span ->
span ->
unit unit
(** Exit a manual span *) (** Exit a manual span *)
@ -142,7 +141,7 @@ type 'st t = (module S with type st = 'st)
module Dummy = struct module Dummy = struct
let on_init _ ~time_ns:_ = () let on_init _ ~time_ns:_ = ()
let new_span _ = Collector.dummy_span let new_span _ = Collector.dummy_span
let new_trace_id _ = Collector.dummy_trace_id let new_explicit_span _ ~parent:_ = Collector.dummy_explicit_span
let on_shutdown _ ~time_ns:_ = () let on_shutdown _ ~time_ns:_ = ()
let on_name_thread _ ~time_ns:_ ~tid:_ ~name:_ = () let on_name_thread _ ~time_ns:_ ~tid:_ ~name:_ = ()
let on_name_process _ ~time_ns:_ ~tid:_ ~name:_ = () let on_name_process _ ~time_ns:_ ~tid:_ ~name:_ = ()
@ -157,13 +156,10 @@ module Dummy = struct
let on_add_data _ ~data:_ _sp = () let on_add_data _ ~data:_ _sp = ()
let on_enter_manual_span _ ~__FUNCTION__:_ ~__FILE__:_ ~__LINE__:_ ~time_ns:_ let on_enter_manual_span _ ~__FUNCTION__:_ ~__FILE__:_ ~__LINE__:_ ~time_ns:_
~tid:_ ~parent:_ ~data:_ ~name:_ ~flavor:_ ~trace_id:_ _sp = ~tid:_ ~parent:_ ~data:_ ~name:_ ~flavor:_ _sp =
()
let on_exit_manual_span _ ~time_ns:_ ~tid:_ ~name:_ ~data:_ ~flavor:_
~trace_id:_ _ =
() ()
let on_exit_manual_span _ ~time_ns:_ ~tid:_ ~name:_ ~data:_ ~flavor:_ _ = ()
let on_extension_event _ ~time_ns:_ ~tid:_ _ = () let on_extension_event _ ~time_ns:_ ~tid:_ _ = ()
end end

View file

@ -24,9 +24,9 @@ open struct
let (Sub { st = s; callbacks = (module CB) }) = Array.get st 0 in let (Sub { st = s; callbacks = (module CB) }) = Array.get st 0 in
CB.new_span s CB.new_span s
let new_trace_id st = let new_explicit_span st =
let (Sub { st = s; callbacks = (module CB) }) = Array.get st 0 in let (Sub { st = s; callbacks = (module CB) }) = Array.get st 0 in
CB.new_trace_id s CB.new_explicit_span s
let on_init st ~time_ns = let on_init st ~time_ns =
for i = 0 to Array.length st - 1 do for i = 0 to Array.length st - 1 do
@ -85,19 +85,17 @@ open struct
done done
let on_enter_manual_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~time_ns ~tid let on_enter_manual_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~time_ns ~tid
~parent ~data ~name ~flavor ~trace_id span = ~parent ~data ~name ~flavor span =
for i = 0 to Array.length st - 1 do for i = 0 to Array.length st - 1 do
let (Sub { st = s; callbacks = (module CB) }) = Array.get st i in let (Sub { st = s; callbacks = (module CB) }) = Array.get st i in
CB.on_enter_manual_span s ~__FUNCTION__ ~__FILE__ ~__LINE__ ~time_ns CB.on_enter_manual_span s ~__FUNCTION__ ~__FILE__ ~__LINE__ ~time_ns
~tid ~parent ~data ~name ~flavor ~trace_id span ~tid ~parent ~data ~name ~flavor span
done done
let on_exit_manual_span st ~time_ns ~tid ~name ~data ~flavor ~trace_id span let on_exit_manual_span st ~time_ns ~tid ~name ~data ~flavor span =
=
for i = 0 to Array.length st - 1 do for i = 0 to Array.length st - 1 do
let (Sub { st = s; callbacks = (module CB) }) = Array.get st i in let (Sub { st = s; callbacks = (module CB) }) = Array.get st i in
CB.on_exit_manual_span s ~time_ns ~tid ~name ~data ~flavor ~trace_id CB.on_exit_manual_span s ~time_ns ~tid ~name ~data ~flavor span
span
done done
let on_extension_event st ~time_ns ~tid ev : unit = let on_extension_event st ~time_ns ~tid ev : unit =

View file

@ -71,36 +71,27 @@ let collector (Sub { st; callbacks = (module CB) } : Subscriber.t) : collector =
let enter_manual_span ~(parent : explicit_span_ctx option) ~flavor let enter_manual_span ~(parent : explicit_span_ctx option) ~flavor
~__FUNCTION__ ~__FILE__ ~__LINE__ ~data name : explicit_span = ~__FUNCTION__ ~__FILE__ ~__LINE__ ~data name : explicit_span =
let span = CB.new_span st in
let tid = tid_ () in let tid = tid_ () in
let time_ns = now_ns () in let time_ns = now_ns () in
(* get the common trace id, or make a new one *) let espan : explicit_span = CB.new_explicit_span st ~parent in
let trace_id, parent = espan.meta <-
match parent with Meta_map.add key_manual_info { name; flavor; data = [] } espan.meta;
| Some m -> m.trace_id, Some m.span
| None -> CB.new_trace_id st, None
in
CB.on_enter_manual_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~parent ~data CB.on_enter_manual_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~parent ~data
~time_ns ~tid ~name ~flavor ~trace_id span; ~time_ns ~tid ~name ~flavor espan;
let meta = espan
Meta_map.empty
|> Meta_map.add key_manual_info { name; flavor; data = [] }
in
{ span; trace_id; meta }
let exit_manual_span (es : explicit_span) : unit = let exit_manual_span (es : explicit_span) : unit =
let time_ns = now_ns () in let time_ns = now_ns () in
let tid = tid_ () in let tid = tid_ () in
let trace_id = es.trace_id in
let minfo = let minfo =
match Meta_map.find key_manual_info es.meta with match Meta_map.find key_manual_info es.meta with
| None -> assert false | None -> assert false
| Some m -> m | Some m -> m
in in
CB.on_exit_manual_span st ~tid ~time_ns ~data:minfo.data ~name:minfo.name CB.on_exit_manual_span st ~tid ~time_ns ~data:minfo.data ~name:minfo.name
~flavor:minfo.flavor ~trace_id es.span ~flavor:minfo.flavor es
let add_data_to_manual_span (es : explicit_span) data = let add_data_to_manual_span (es : explicit_span) data =
if data <> [] then ( if data <> [] then (
@ -154,15 +145,3 @@ module Span_generator = struct
let create () = A.make 0 let create () = A.make 0
let[@inline] mk_span self = A.fetch_and_add self 1 |> Int64.of_int let[@inline] mk_span self = A.fetch_and_add self 1 |> Int64.of_int
end end
module Trace_id_8B_generator = struct
type t = int A.t
let create () = A.make 0
let[@inline] mk_trace_id (self : t) : trace_id =
let n = A.fetch_and_add self 1 in
let b = Bytes.create 8 in
Bytes.set_int64_le b 0 (Int64.of_int n);
Bytes.unsafe_to_string b
end

View file

@ -37,15 +37,6 @@ module Span_generator : sig
val mk_span : t -> Trace_core.span val mk_span : t -> Trace_core.span
end end
(** A counter-based trace ID generator, producing 8-byte trace IDs.
@since NEXT_RELEASE *)
module Trace_id_8B_generator : sig
type t
val create : unit -> t
val mk_trace_id : t -> Trace_core.trace_id
end
(**/**) (**/**)
module Private_ : sig module Private_ : sig
@ -53,7 +44,7 @@ module Private_ : sig
(** Global mock flag. If enable, all timestamps, tid, etc should be faked. *) (** Global mock flag. If enable, all timestamps, tid, etc should be faked. *)
val get_now_ns_ : (unit -> int64) ref val get_now_ns_ : (unit -> int64) ref
(** The callback used to get the current timestamp *) (** The callback used to get the current timestamp, in nanoseconds *)
val get_tid_ : (unit -> int) ref val get_tid_ : (unit -> int) ref
(** The callback used to get the current thread's id *) (** The callback used to get the current thread's id *)

View file

@ -16,11 +16,11 @@ open struct
let[@inline] time_us_of_time_ns (t : int64) : float = let[@inline] time_us_of_time_ns (t : int64) : float =
Int64.div t 1_000L |> Int64.to_float Int64.div t 1_000L |> Int64.to_float
let[@inline] int64_of_trace_id_ (id : Trace_core.trace_id) : int64 = (** Used to store async spans' trace ID *)
if id == Trace_core.Collector.dummy_trace_id then let k_trace_id : int64 Meta_map.key = Meta_map.Key.create ()
0L
else (* 8B in both cases *)
Bytes.get_int64_le (Bytes.unsafe_of_string id) 0 module Trace_id_8B_generator = Sub.Span_generator
end end
let on_tracing_error = ref (fun s -> Printf.eprintf "%s\n%!" s) let on_tracing_error = ref (fun s -> Printf.eprintf "%s\n%!" s)
@ -43,7 +43,7 @@ type t = {
buf_pool: Buf_pool.t; buf_pool: Buf_pool.t;
exporter: Exporter.t; exporter: Exporter.t;
span_gen: Sub.Span_generator.t; span_gen: Sub.Span_generator.t;
trace_id_gen: Sub.Trace_id_8B_generator.t; trace_id_gen: Trace_id_8B_generator.t;
} }
(** Subscriber state *) (** Subscriber state *)
@ -85,7 +85,7 @@ let create ?(buf_pool = Buf_pool.create ()) ~pid ~exporter () : t =
pid; pid;
spans = Span_tbl.create (); spans = Span_tbl.create ();
span_gen = Sub.Span_generator.create (); span_gen = Sub.Span_generator.create ();
trace_id_gen = Sub.Trace_id_8B_generator.create (); trace_id_gen = Trace_id_8B_generator.create ();
} }
module Callbacks = struct module Callbacks = struct
@ -93,8 +93,19 @@ module Callbacks = struct
let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen
let new_trace_id self = let new_explicit_span self ~(parent : explicit_span_ctx option) :
Sub.Trace_id_8B_generator.mk_trace_id self.trace_id_gen explicit_span =
let trace_id =
match parent with
| None -> Trace_id_8B_generator.mk_span self.trace_id_gen
| Some p ->
(match Meta_map.find k_trace_id p.meta with
| Some t -> t
| None -> Trace_id_8B_generator.mk_span self.trace_id_gen)
in
let span = new_span self in
let meta = Meta_map.(empty |> add k_trace_id trace_id) in
{ span; meta }
let on_init _ ~time_ns:_ = () let on_init _ ~time_ns:_ = ()
let on_shutdown (self : st) ~time_ns:_ = close self let on_shutdown (self : st) ~time_ns:_ = close self
@ -162,25 +173,30 @@ module Callbacks = struct
self.exporter.on_json buf self.exporter.on_json buf
let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_ let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_
~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor ~trace_id _span : ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor
unit = (span : explicit_span) : unit =
let time_us = time_us_of_time_ns @@ time_ns in let time_us = time_us_of_time_ns @@ time_ns in
let trace_id =
try Meta_map.find_exn k_trace_id span.meta with _ -> assert false
in
let data = add_fun_name_ fun_name data in let data = add_fun_name_ fun_name data in
let@ buf = Rpool.with_ self.buf_pool in let@ buf = Rpool.with_ self.buf_pool in
Writer.emit_manual_begin buf ~pid:self.pid ~tid ~name Writer.emit_manual_begin buf ~pid:self.pid ~tid ~name ~id:trace_id
~id:(int64_of_trace_id_ trace_id)
~ts:time_us ~args:data ~flavor; ~ts:time_us ~args:data ~flavor;
self.exporter.on_json buf self.exporter.on_json buf
let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor
~trace_id (_ : span) : unit = (span : explicit_span) : unit =
let time_us = time_us_of_time_ns @@ time_ns in let time_us = time_us_of_time_ns @@ time_ns in
let trace_id =
try Meta_map.find_exn k_trace_id span.meta with _ -> assert false
in
let@ buf = Rpool.with_ self.buf_pool in let@ buf = Rpool.with_ self.buf_pool in
Writer.emit_manual_end buf ~pid:self.pid ~tid ~name Writer.emit_manual_end buf ~pid:self.pid ~tid ~name ~id:trace_id ~ts:time_us
~id:(int64_of_trace_id_ trace_id) ~flavor ~args:data;
~ts:time_us ~flavor ~args:data;
self.exporter.on_json buf self.exporter.on_json buf
let on_extension_event _ ~time_ns:_ ~tid:_ _ev = () let on_extension_event _ ~time_ns:_ ~tid:_ _ev = ()