diff --git a/src/core/collector.ml b/src/core/collector.ml index 5e3a267..13eea28 100644 --- a/src/core/collector.ml +++ b/src/core/collector.ml @@ -7,13 +7,11 @@ open Types let dummy_span : span = Int64.min_int -let dummy_trace_id : trace_id = "" 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 = - { span = dummy_span; trace_id = dummy_trace_id } +let dummy_explicit_span_ctx : explicit_span_ctx = { meta = Meta_map.empty } (** Signature for a collector. diff --git a/src/core/trace_core.ml b/src/core/trace_core.ml index e43497e..877c4c0 100644 --- a/src/core/trace_core.ml +++ b/src/core/trace_core.ml @@ -18,7 +18,7 @@ let current_level_ = A.make Level.Trace (* ## implementation ## *) 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_ () = [] diff --git a/src/core/types.ml b/src/core/types.ml index 1f76d29..52b458b 100644 --- a/src/core/types.ml +++ b/src/core/types.ml @@ -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 (** A span identifier. 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 = [ `Int of int | `String of string @@ -26,17 +26,24 @@ type span_flavor = @since NEXT_RELEASE *) type explicit_span_ctx = { - span: span; (** The current span *) - trace_id: trace_id; (** The trace this belongs to *) + meta: Meta_map.t; + (** 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. - @since 0.10 *) +[@@unboxed] +(** 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 = { span: span; (** Identifier for this span. Several explicit spans might share the same identifier since we can differentiate between them via [meta]. *) - trace_id: trace_id; (** The trace this belongs to *) mutable meta: Meta_map.t; (** Metadata for this span (and its context). This can be used by 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_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 = .. (** An extension event, used to add features that are backend specific or simply diff --git a/src/event/event.ml b/src/event/event.ml index 456562b..2551d6d 100644 --- a/src/event/event.ml +++ b/src/event/event.ml @@ -37,7 +37,6 @@ type t = tid: int; name: string; time_ns: int64; - id: trace_id; flavor: span_flavor option; fun_name: string option; data: (string * user_data) list; @@ -48,7 +47,6 @@ type t = time_ns: int64; flavor: span_flavor option; data: (string * user_data) list; - id: trace_id; } | E_counter of { name: string; diff --git a/src/event/subscriber.ml b/src/event/subscriber.ml index 52e809f..efce613 100644 --- a/src/event/subscriber.ml +++ b/src/event/subscriber.ml @@ -10,14 +10,17 @@ open struct (* just use the same ones for everyone *) let span_gen = Sub.Span_generator.create () - let trace_id_gen = Sub.Trace_id_8B_generator.create () end module Callbacks : Sub.Callbacks.S with type st = event_consumer = struct type st = event_consumer 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_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 } let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_ - ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor ~trace_id _span : - unit = + ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor _span : unit = self.on_event - @@ E_enter_manual_span - { id = trace_id; time_ns; tid; data; name; fun_name; flavor } + @@ E_enter_manual_span { time_ns; tid; data; name; fun_name; flavor } let on_exit_manual_span (self : st) ~time_ns ~tid ~name ~data ~flavor - ~trace_id (_ : span) : unit = - self.on_event - @@ E_exit_manual_span { tid; id = trace_id; name; time_ns; data; flavor } + (_ : explicit_span) : unit = + self.on_event @@ E_exit_manual_span { tid; name; time_ns; data; flavor } let on_extension_event (self : st) ~time_ns ~tid ext : unit = self.on_event @@ E_extension_event { tid; time_ns; ext } diff --git a/src/fuchsia/subscriber.ml b/src/fuchsia/subscriber.ml index 768ae46..b7b42d6 100644 --- a/src/fuchsia/subscriber.ml +++ b/src/fuchsia/subscriber.ml @@ -22,7 +22,8 @@ type t = { buf_chain: Buf_chain.t; exporter: Exporter.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 *) @@ -49,6 +50,8 @@ open struct names; flush stderr ) + + let k_trace_id : int64 Meta_map.key = Meta_map.Key.create () end let close (self : t) : unit = @@ -76,7 +79,8 @@ let create ?(buf_pool = Buf_pool.create ()) ~pid ~exporter () : t = pid; spans = Span_tbl.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 @@ -84,8 +88,21 @@ module Callbacks = struct let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen - let new_trace_id self = - Sub.Trace_id_8B_generator.mk_trace_id self.trace_id_gen + let get_trace_id_ meta : int64 = + 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:_ = Writer.Metadata.Magic_record.encode self.buf_chain; @@ -164,7 +181,9 @@ module Callbacks = struct write_ready_ self 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.( Event.Async_begin.encode self.buf_chain ~name ~args:(args_of_user_data data) @@ -173,7 +192,8 @@ module Callbacks = struct write_ready_ self 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.( Event.Async_end.encode self.buf_chain ~name ~args:(args_of_user_data data) ~t_ref:(Thread_ref.inline ~pid:self.pid ~tid) diff --git a/src/fuchsia/writer.ml b/src/fuchsia/writer.ml index 972d9eb..ffc363c 100644 --- a/src/fuchsia/writer.ml +++ b/src/fuchsia/writer.ml @@ -4,15 +4,6 @@ open Common_ 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 type user_data = Trace_core.user_data @@ -491,7 +482,7 @@ module Event = struct + Arguments.size_word args + 1 (* async id *) 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 size = size_word ~name ~t_ref ~args () in let@ buf = Buf_chain.with_buf bufs ~available_word:size in @@ -516,7 +507,7 @@ module Event = struct Buf.add_string buf name; Arguments.encode buf args; - Buf.add_i64 buf (int64_of_trace_id_ async_id); + Buf.add_i64 buf async_id; () end @@ -527,7 +518,7 @@ module Event = struct + Arguments.size_word args + 1 (* async id *) 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 size = size_word ~name ~t_ref ~args () in let@ buf = Buf_chain.with_buf bufs ~available_word:size in @@ -552,7 +543,7 @@ module Event = struct Buf.add_string buf name; Arguments.encode buf args; - Buf.add_i64 buf (int64_of_trace_id_ async_id); + Buf.add_i64 buf async_id; () end end diff --git a/src/subscriber/callbacks.ml b/src/subscriber/callbacks.ml index 0792493..40ea74d 100644 --- a/src/subscriber/callbacks.ml +++ b/src/subscriber/callbacks.ml @@ -35,8 +35,9 @@ module type S = sig (** How to generate a new span? @since NEXT_RELEASE *) - val new_trace_id : st -> trace_id - (** How to generate a new trace ID? + val new_explicit_span : st -> parent:explicit_span_ctx option -> explicit_span + (** How to generate a new explicit span, with meta-map potentially containing + data such as a trace ID or request ID? @since NEXT_RELEASE *) val on_shutdown : st -> time_ns:int64 -> unit @@ -96,12 +97,11 @@ module type S = sig __LINE__:int -> time_ns:int64 -> tid:int -> - parent:span option -> + parent:explicit_span_ctx option -> data:(string * Trace_core.user_data) list -> name:string -> flavor:Trace_core.span_flavor option -> - trace_id:trace_id -> - span -> + explicit_span -> unit (** Enter a manual (possibly async) span *) @@ -112,8 +112,7 @@ module type S = sig name:string -> data:(string * Trace_core.user_data) list -> flavor:Trace_core.span_flavor option -> - trace_id:trace_id -> - span -> + explicit_span -> unit (** Exit a manual span *) @@ -142,7 +141,7 @@ type 'st t = (module S with type st = 'st) module Dummy = struct let on_init _ ~time_ns:_ = () 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_name_thread _ ~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_enter_manual_span _ ~__FUNCTION__:_ ~__FILE__:_ ~__LINE__:_ ~time_ns:_ - ~tid:_ ~parent:_ ~data:_ ~name:_ ~flavor:_ ~trace_id:_ _sp = - () - - let on_exit_manual_span _ ~time_ns:_ ~tid:_ ~name:_ ~data:_ ~flavor:_ - ~trace_id:_ _ = + ~tid:_ ~parent:_ ~data:_ ~name:_ ~flavor:_ _sp = () + let on_exit_manual_span _ ~time_ns:_ ~tid:_ ~name:_ ~data:_ ~flavor:_ _ = () let on_extension_event _ ~time_ns:_ ~tid:_ _ = () end diff --git a/src/subscriber/subscriber.ml b/src/subscriber/subscriber.ml index 80ddc02..865acf0 100644 --- a/src/subscriber/subscriber.ml +++ b/src/subscriber/subscriber.ml @@ -24,9 +24,9 @@ open struct let (Sub { st = s; callbacks = (module CB) }) = Array.get st 0 in 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 - CB.new_trace_id s + CB.new_explicit_span s let on_init st ~time_ns = for i = 0 to Array.length st - 1 do @@ -85,19 +85,17 @@ open struct done 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 let (Sub { st = s; callbacks = (module CB) }) = Array.get st i in 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 - 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 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 - span + CB.on_exit_manual_span s ~time_ns ~tid ~name ~data ~flavor span done let on_extension_event st ~time_ns ~tid ev : unit = diff --git a/src/subscriber/trace_subscriber.ml b/src/subscriber/trace_subscriber.ml index e103916..4b72ca5 100644 --- a/src/subscriber/trace_subscriber.ml +++ b/src/subscriber/trace_subscriber.ml @@ -71,36 +71,27 @@ let collector (Sub { st; callbacks = (module CB) } : Subscriber.t) : collector = let enter_manual_span ~(parent : explicit_span_ctx option) ~flavor ~__FUNCTION__ ~__FILE__ ~__LINE__ ~data name : explicit_span = - let span = CB.new_span st in let tid = tid_ () in let time_ns = now_ns () in - (* get the common trace id, or make a new one *) - let trace_id, parent = - match parent with - | Some m -> m.trace_id, Some m.span - | None -> CB.new_trace_id st, None - in + let espan : explicit_span = CB.new_explicit_span st ~parent in + espan.meta <- + Meta_map.add key_manual_info { name; flavor; data = [] } espan.meta; CB.on_enter_manual_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~parent ~data - ~time_ns ~tid ~name ~flavor ~trace_id span; - let meta = - Meta_map.empty - |> Meta_map.add key_manual_info { name; flavor; data = [] } - in - { span; trace_id; meta } + ~time_ns ~tid ~name ~flavor espan; + espan let exit_manual_span (es : explicit_span) : unit = let time_ns = now_ns () in let tid = tid_ () in - let trace_id = es.trace_id in let minfo = match Meta_map.find key_manual_info es.meta with | None -> assert false | Some m -> m in 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 = if data <> [] then ( @@ -154,15 +145,3 @@ module Span_generator = struct let create () = A.make 0 let[@inline] mk_span self = A.fetch_and_add self 1 |> Int64.of_int 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 diff --git a/src/subscriber/trace_subscriber.mli b/src/subscriber/trace_subscriber.mli index d84d744..70880a5 100644 --- a/src/subscriber/trace_subscriber.mli +++ b/src/subscriber/trace_subscriber.mli @@ -37,15 +37,6 @@ module Span_generator : sig val mk_span : t -> Trace_core.span 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 @@ -53,7 +44,7 @@ module Private_ : sig (** 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 *) + (** The callback used to get the current timestamp, in nanoseconds *) val get_tid_ : (unit -> int) ref (** The callback used to get the current thread's id *) diff --git a/src/tef/subscriber.ml b/src/tef/subscriber.ml index b90a6a3..6313c8e 100644 --- a/src/tef/subscriber.ml +++ b/src/tef/subscriber.ml @@ -16,11 +16,11 @@ open struct let[@inline] time_us_of_time_ns (t : int64) : float = Int64.div t 1_000L |> Int64.to_float - 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 + (** Used to store async spans' trace ID *) + let k_trace_id : int64 Meta_map.key = Meta_map.Key.create () + + (* 8B in both cases *) + module Trace_id_8B_generator = Sub.Span_generator end let on_tracing_error = ref (fun s -> Printf.eprintf "%s\n%!" s) @@ -43,7 +43,7 @@ type t = { buf_pool: Buf_pool.t; exporter: Exporter.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 *) @@ -85,7 +85,7 @@ let create ?(buf_pool = Buf_pool.create ()) ~pid ~exporter () : t = pid; spans = Span_tbl.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 @@ -93,8 +93,19 @@ module Callbacks = struct let new_span (self : st) = Sub.Span_generator.mk_span self.span_gen - let new_trace_id self = - Sub.Trace_id_8B_generator.mk_trace_id self.trace_id_gen + let new_explicit_span self ~(parent : explicit_span_ctx option) : + 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_shutdown (self : st) ~time_ns:_ = close self @@ -162,25 +173,30 @@ module Callbacks = struct self.exporter.on_json buf let on_enter_manual_span (self : st) ~__FUNCTION__:fun_name ~__FILE__:_ - ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor ~trace_id _span : - unit = + ~__LINE__:_ ~time_ns ~tid ~parent:_ ~data ~name ~flavor + (span : explicit_span) : unit = 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@ buf = Rpool.with_ self.buf_pool in - Writer.emit_manual_begin buf ~pid:self.pid ~tid ~name - ~id:(int64_of_trace_id_ trace_id) + Writer.emit_manual_begin buf ~pid:self.pid ~tid ~name ~id:trace_id ~ts:time_us ~args:data ~flavor; self.exporter.on_json buf 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 trace_id = + try Meta_map.find_exn k_trace_id span.meta with _ -> assert false + in let@ buf = Rpool.with_ self.buf_pool in - Writer.emit_manual_end buf ~pid:self.pid ~tid ~name - ~id:(int64_of_trace_id_ trace_id) - ~ts:time_us ~flavor ~args:data; + Writer.emit_manual_end buf ~pid:self.pid ~tid ~name ~id:trace_id ~ts:time_us + ~flavor ~args:data; self.exporter.on_json buf let on_extension_event _ ~time_ns:_ ~tid:_ _ev = () diff --git a/src/tef/writer.ml b/src/tef/writer.ml index 26286c3..43c920e 100644 --- a/src/tef/writer.ml +++ b/src/tef/writer.ml @@ -1,5 +1,3 @@ -open Common_ - let char = Buffer.add_char let raw_string = Buffer.add_string diff --git a/src/tef/writer.mli b/src/tef/writer.mli index 536b602..619fa41 100644 --- a/src/tef/writer.mli +++ b/src/tef/writer.mli @@ -3,7 +3,6 @@ This is the part of the code that knows how to emit TEF-compliant JSON from raw event data. *) -open Common_ open Trace_core val emit_duration_event :