mirror of
https://github.com/ocaml-tracing/ocaml-opentelemetry.git
synced 2026-03-08 03:47:59 -04:00
otel.trace: have a single collector that always use current *_provider
just use the current Trace_provider.() (resp Log, Metrics) to emit a span (resp log, metric). Simpler, and we rely on a global exporter anyway.
This commit is contained in:
parent
fa14ddf1f8
commit
478fe1da7b
2 changed files with 58 additions and 86 deletions
|
|
@ -21,15 +21,27 @@ end
|
||||||
|
|
||||||
open Extensions
|
open Extensions
|
||||||
|
|
||||||
open struct
|
module Ambient_span_provider_ = struct
|
||||||
type state = {
|
let get_current_span () =
|
||||||
clock: Opentelemetry_core.Clock.t;
|
match OTEL.Ambient_span.get () with
|
||||||
exporter: OTEL.Exporter.t;
|
| None -> None
|
||||||
}
|
| Some sp -> Some (Span_otel sp)
|
||||||
|
|
||||||
let create_state ~(exporter : OTEL.Exporter.t) () : state =
|
let with_current_span_set_to () span f =
|
||||||
let clock = OTEL.Clock.ptime_clock in
|
match span with
|
||||||
{ clock; exporter }
|
| Span_otel sp -> OTEL.Ambient_span.with_ambient sp (fun () -> f span)
|
||||||
|
| _ -> f span
|
||||||
|
|
||||||
|
let callbacks : unit Trace.Ambient_span_provider.Callbacks.t =
|
||||||
|
{ get_current_span; with_current_span_set_to }
|
||||||
|
|
||||||
|
let provider = Trace.Ambient_span_provider.ASP_some ((), callbacks)
|
||||||
|
end
|
||||||
|
|
||||||
|
let ambient_span_provider = Ambient_span_provider_.provider
|
||||||
|
|
||||||
|
open struct
|
||||||
|
type state = unit
|
||||||
|
|
||||||
(* sanity check: otrace meta-map must be the same as hmap *)
|
(* sanity check: otrace meta-map must be the same as hmap *)
|
||||||
let () = ignore (fun (k : _ Hmap.key) : _ Ambient_context.Context.key -> k)
|
let () = ignore (fun (k : _ Hmap.key) : _ Ambient_context.Context.key -> k)
|
||||||
|
|
@ -38,9 +50,9 @@ open struct
|
||||||
let k_span_ctx : OTEL.Span_ctx.t Ambient_context.Context.key =
|
let k_span_ctx : OTEL.Span_ctx.t Ambient_context.Context.key =
|
||||||
OTEL.Span_ctx.k_ambient
|
OTEL.Span_ctx.k_ambient
|
||||||
|
|
||||||
let enter_span (self : state) ~__FUNCTION__ ~__FILE__ ~__LINE__ ~level:_
|
let enter_span () ~__FUNCTION__ ~__FILE__ ~__LINE__ ~level:_ ~params:_
|
||||||
~params:_ ~(data : (_ * Trace.user_data) list) ~parent name : Trace.span =
|
~(data : (_ * Trace.user_data) list) ~parent name : Trace.span =
|
||||||
let start_time = OTEL.Clock.now self.clock in
|
let start_time = OTEL.Clock.now_main () in
|
||||||
let trace_id, parent_id =
|
let trace_id, parent_id =
|
||||||
match parent with
|
match parent with
|
||||||
| Trace.P_some (Span_otel sp) ->
|
| Trace.P_some (Span_otel sp) ->
|
||||||
|
|
@ -93,13 +105,15 @@ open struct
|
||||||
|
|
||||||
Span_otel otel_sp
|
Span_otel otel_sp
|
||||||
|
|
||||||
let exit_span (self : state) sp =
|
let exit_span () sp =
|
||||||
match sp with
|
match sp with
|
||||||
| Span_otel span when OTEL.Span.is_not_dummy span ->
|
| Span_otel span when OTEL.Span.is_not_dummy span ->
|
||||||
(* emit the span after setting the end timestamp *)
|
(* emit the span after setting the end timestamp *)
|
||||||
let end_time = OTEL.Clock.now self.clock in
|
let end_time = OTEL.Clock.now_main () in
|
||||||
OTEL.Proto.Trace.span_set_end_time_unix_nano span end_time;
|
OTEL.Proto.Trace.span_set_end_time_unix_nano span end_time;
|
||||||
self.exporter.OTEL.Exporter.export (OTEL.Any_signal_l.Spans [ span ])
|
|
||||||
|
(* use the current tracer *)
|
||||||
|
OTEL.Trace_provider.emit span
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
|
|
||||||
let add_data_to_span _self span (data : (_ * Trace.user_data) list) =
|
let add_data_to_span _self span (data : (_ * Trace.user_data) list) =
|
||||||
|
|
@ -116,9 +130,9 @@ open struct
|
||||||
| Info -> OTEL.Log_record.Severity_number_info
|
| Info -> OTEL.Log_record.Severity_number_info
|
||||||
| Warning -> OTEL.Log_record.Severity_number_warn
|
| Warning -> OTEL.Log_record.Severity_number_warn
|
||||||
|
|
||||||
let message (self : state) ~(level : Trace_core.Level.t) ~params:_ ~data ~span
|
let message () ~(level : Trace_core.Level.t) ~params:_ ~data ~span msg : unit
|
||||||
msg : unit =
|
=
|
||||||
let observed_time_unix_nano = OTEL.Clock.now self.clock in
|
let observed_time_unix_nano = OTEL.Clock.now_main () in
|
||||||
let trace_id, span_id =
|
let trace_id, span_id =
|
||||||
match span with
|
match span with
|
||||||
| Some (Span_otel sp) ->
|
| Some (Span_otel sp) ->
|
||||||
|
|
@ -135,10 +149,10 @@ open struct
|
||||||
OTEL.Log_record.make ~severity ?trace_id ?span_id ~attrs:data
|
OTEL.Log_record.make ~severity ?trace_id ?span_id ~attrs:data
|
||||||
~observed_time_unix_nano (`String msg)
|
~observed_time_unix_nano (`String msg)
|
||||||
in
|
in
|
||||||
self.exporter.OTEL.Exporter.export (OTEL.Any_signal_l.Logs [ log ])
|
OTEL.Log_provider.emit log
|
||||||
|
|
||||||
let metric (self : state) ~level:_ ~params:_ ~data:attrs name v : unit =
|
let metric () ~level:_ ~params:_ ~data:attrs name v : unit =
|
||||||
let now = OTEL.Clock.now self.clock in
|
let now = OTEL.Clock.now_main () in
|
||||||
let kind =
|
let kind =
|
||||||
let open Trace_core.Core_ext in
|
let open Trace_core.Core_ext in
|
||||||
match v with
|
match v with
|
||||||
|
|
@ -157,8 +171,7 @@ open struct
|
||||||
| `sum v -> [ OTEL.Metrics.sum ~name [ v ] ]
|
| `sum v -> [ OTEL.Metrics.sum ~name [ v ] ]
|
||||||
| `hist h -> [ OTEL.Metrics.histogram ~name [ h ] ]
|
| `hist h -> [ OTEL.Metrics.histogram ~name [ h ] ]
|
||||||
in
|
in
|
||||||
if m <> [] then
|
if m <> [] then OTEL.Emitter.emit (OTEL.Meter_provider.get ()).emit m
|
||||||
self.exporter.OTEL.Exporter.export (OTEL.Any_signal_l.Metrics m)
|
|
||||||
|
|
||||||
let extension (_self : state) ~level:_ ev =
|
let extension (_self : state) ~level:_ ev =
|
||||||
match ev with
|
match ev with
|
||||||
|
|
@ -174,35 +187,17 @@ open struct
|
||||||
| Ev_record_exn _ -> ()
|
| Ev_record_exn _ -> ()
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
|
|
||||||
let shutdown self = OTEL.Exporter.shutdown self.exporter
|
let init () = Trace.set_ambient_context_provider ambient_span_provider
|
||||||
|
|
||||||
|
let shutdown () = ()
|
||||||
|
|
||||||
let callbacks : state Trace.Collector.Callbacks.t =
|
let callbacks : state Trace.Collector.Callbacks.t =
|
||||||
Trace.Collector.Callbacks.make ~enter_span ~exit_span ~add_data_to_span
|
Trace.Collector.Callbacks.make ~enter_span ~exit_span ~add_data_to_span
|
||||||
~message ~metric ~extension ~shutdown ()
|
~message ~metric ~extension ~init ~shutdown ()
|
||||||
end
|
end
|
||||||
|
|
||||||
module Ambient_span_provider_ = struct
|
let collector : Trace_core.collector =
|
||||||
let get_current_span () =
|
Trace_core.Collector.C_some ((), callbacks)
|
||||||
match OTEL.Ambient_span.get () with
|
|
||||||
| None -> None
|
|
||||||
| Some sp -> Some (Span_otel sp)
|
|
||||||
|
|
||||||
let with_current_span_set_to () span f =
|
|
||||||
match span with
|
|
||||||
| Span_otel sp -> OTEL.Ambient_span.with_ambient sp (fun () -> f span)
|
|
||||||
| _ -> f span
|
|
||||||
|
|
||||||
let callbacks : unit Trace.Ambient_span_provider.Callbacks.t =
|
|
||||||
{ get_current_span; with_current_span_set_to }
|
|
||||||
|
|
||||||
let provider = Trace.Ambient_span_provider.ASP_some ((), callbacks)
|
|
||||||
end
|
|
||||||
|
|
||||||
let ambient_span_provider = Ambient_span_provider_.provider
|
|
||||||
|
|
||||||
let collector_of_exporter (exporter : OTEL.Exporter.t) : Trace_core.collector =
|
|
||||||
let st = create_state ~exporter () in
|
|
||||||
Trace_core.Collector.C_some (st, callbacks)
|
|
||||||
|
|
||||||
let with_ambient_span (sp : Trace.span) f =
|
let with_ambient_span (sp : Trace.span) f =
|
||||||
match sp with
|
match sp with
|
||||||
|
|
@ -235,37 +230,11 @@ let record_exception sp exn bt : unit =
|
||||||
if Trace.enabled () then
|
if Trace.enabled () then
|
||||||
Trace.extension_event @@ Ev_record_exn { sp; exn; bt }
|
Trace.extension_event @@ Ev_record_exn { sp; exn; bt }
|
||||||
|
|
||||||
(** Collector that forwards to the {b currently installed} OTEL exporter. *)
|
let setup () = Trace.setup_collector collector
|
||||||
let collector_main_otel_exporter () : Trace.collector =
|
|
||||||
(* Create a dynamic exporter that forwards to the currently installed main
|
|
||||||
exporter at call time. *)
|
|
||||||
let dynamic_exp : OTEL.Exporter.t =
|
|
||||||
{
|
|
||||||
OTEL.Exporter.export =
|
|
||||||
(fun sig_ ->
|
|
||||||
match OTEL.Sdk.get () with
|
|
||||||
| None -> ()
|
|
||||||
| Some exp -> exp.OTEL.Exporter.export sig_);
|
|
||||||
active = (fun () -> Aswitch.dummy);
|
|
||||||
shutdown = ignore;
|
|
||||||
self_metrics = (fun () -> OTEL.Sdk.self_metrics ());
|
|
||||||
}
|
|
||||||
in
|
|
||||||
collector_of_exporter dynamic_exp
|
|
||||||
|
|
||||||
let (collector
|
|
||||||
[@deprecated "use collector_of_exporter or collector_main_otel_exporter"])
|
|
||||||
=
|
|
||||||
collector_main_otel_exporter
|
|
||||||
|
|
||||||
let setup () =
|
|
||||||
Trace.set_ambient_context_provider Ambient_span_provider_.provider;
|
|
||||||
Trace.setup_collector @@ collector_main_otel_exporter ()
|
|
||||||
|
|
||||||
let setup_with_otel_exporter exp : unit =
|
let setup_with_otel_exporter exp : unit =
|
||||||
let coll = collector_of_exporter exp in
|
|
||||||
OTEL.Sdk.set exp;
|
OTEL.Sdk.set exp;
|
||||||
Trace.setup_collector coll
|
Trace.setup_collector collector
|
||||||
|
|
||||||
let setup_with_otel_backend = setup_with_otel_exporter
|
let setup_with_otel_backend = setup_with_otel_exporter
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
that use [ocaml-trace], and they will automatically emit OpenTelemetry spans
|
that use [ocaml-trace], and they will automatically emit OpenTelemetry spans
|
||||||
and logs.
|
and logs.
|
||||||
|
|
||||||
Ambient_context is used to track the current ambient span.
|
[Ambient_context] is used to propagate the current span to child spans.
|
||||||
|
|
||||||
We use [Trace_core.extension_event] to add more features on top of the
|
[Trace_core.extension_event] is used to expose OTEL-specific features on top
|
||||||
common tracing interface. For example to set the "span kind":
|
of the common tracing interface, e.g. to set the span kind:
|
||||||
|
|
||||||
{[
|
{[
|
||||||
let@ span = Trace_core.with_span ~__FILE__ ~__LINE__ "my-span" in
|
let@ span = Trace_core.with_span ~__FILE__ ~__LINE__ "my-span" in
|
||||||
|
|
@ -44,23 +44,26 @@ module Extensions : sig
|
||||||
end
|
end
|
||||||
|
|
||||||
val setup : unit -> unit
|
val setup : unit -> unit
|
||||||
(** Install the OTEL backend as a Trace collector *)
|
(** Install the OTEL backend as a [Trace] collector. The trace collector will
|
||||||
|
use {!Trace_provider.get}, {!Log_provider.get}, and {!Meter_provider.get} to
|
||||||
|
get the current tracer, logger, meter and use that to emit signals.
|
||||||
|
|
||||||
|
This will not do much until a proper {!OTEL.Exporter.t} is installed via
|
||||||
|
{!OTEL.Sdk.set}. *)
|
||||||
|
|
||||||
val setup_with_otel_exporter : OTEL.Exporter.t -> unit
|
val setup_with_otel_exporter : OTEL.Exporter.t -> unit
|
||||||
(** Same as {!setup}, but using the given exporter *)
|
(** Same as {!setup}, but also calls [OTEL.Sdk.set otel_exporter] *)
|
||||||
|
|
||||||
val setup_with_otel_backend : OTEL.Exporter.t -> unit
|
val setup_with_otel_backend : OTEL.Exporter.t -> unit
|
||||||
[@@deprecated "use setup_with_otel_exporter"]
|
[@@deprecated "use setup_with_otel_exporter"]
|
||||||
|
|
||||||
val collector_of_exporter : OTEL.Exporter.t -> Trace_core.collector
|
val collector : Trace_core.collector
|
||||||
|
(** Make a Trace collector that uses the main OTEL providers to emit traces,
|
||||||
val collector : unit -> Trace_core.collector
|
metrics, and logs *)
|
||||||
[@@deprecated "use collector_of_exporter, avoid global state"]
|
|
||||||
(** Make a Trace collector that uses the main OTEL backend to send spans and
|
|
||||||
logs *)
|
|
||||||
|
|
||||||
val ambient_span_provider : Trace_core.Ambient_span_provider.t
|
val ambient_span_provider : Trace_core.Ambient_span_provider.t
|
||||||
(** Uses {!Ambient_context} to provide contextual spans in {!Trace_core}.*)
|
(** Uses {!Ambient_context} to provide contextual spans in {!Trace_core}. It is
|
||||||
|
automatically installed by the {!collector}. *)
|
||||||
|
|
||||||
val link_spans : Otrace.span -> Otrace.span -> unit
|
val link_spans : Otrace.span -> Otrace.span -> unit
|
||||||
(** [link_spans sp1 sp2] modifies [sp1] by adding a span link to [sp2].
|
(** [link_spans sp1 sp2] modifies [sp1] by adding a span link to [sp2].
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue