ocaml-opentelemetry/src/trace/opentelemetry_trace.mli

197 lines
6.7 KiB
OCaml

module Otel := Opentelemetry
module Otrace := Trace_core
module TLS := Ambient_context_tls.TLS
(** [opentelemetry.trace] implements a {!Trace_core.Collector} for
{{:https://v3.ocaml.org/p/trace} ocaml-trace}.
After installing this collector with {!setup}, you can consume libraries
that use [ocaml-trace], and they will automatically emit OpenTelemetry spans
and logs.
Both explicit scope (in the [_manual] functions such as [enter_manual_span])
and implicit scope (in {!Internal.M.with_span}, via {!Ambient_context}) are
supported; see the detailed notes on {!Internal.M.enter_manual_span}.
{1:wellknown Well-known identifiers}
Because [ocaml-trace]'s API is a subset of OpenTelemetry functionality, this
interface allows for a few 'well-known' identifiers to be used in
[Trace]-instrumented libraries that wish to further support OpenTelemetry
usage.
(These strings will not change in subsequent versions of this library, so
you do not need to depend on [opentelemetry.trace] to use them.)
- If a key of exactly ["otrace.spankind"] is included in the
{!Trace_core.user_data} passed to [with_span] et al., it will be used as
the {!Opentelemetry.Span.kind} of the emitted span. (See
{!Internal.spankind_of_string} for the list of supported values.)
{[ocaml
let describe () = [ Opentelemetry_trace.(spankind_key, client) ] in
Trace_core.with_span ~__FILE__ ~__LINE__ ~data:describe "my-span"
@@ fun _ ->
(* ... *)
]}
*)
val setup : unit -> unit
(** Install the OTEL backend as a Trace collector *)
val setup_with_otel_backend : Opentelemetry.Collector.backend -> unit
(** Same as {!setup}, but also install the given backend as OTEL backend *)
val collector : unit -> Trace_core.collector
(** Make a Trace collector that uses the OTEL backend to send spans and logs *)
(** Static references for well-known identifiers; see {!label-wellknown}. *)
module Well_known : sig
val spankind_key : string
val internal : Otrace.user_data
val server : Otrace.user_data
val client : Otrace.user_data
val producer : Otrace.user_data
val consumer : Otrace.user_data
val spankind_of_string : string -> Otel.Span.kind
val otel_attrs_of_otrace_data :
(string * Otrace.user_data) list ->
Otel.Span.kind * Otel.Span.key_value list
end
(** Internal implementation details; do not consider these stable. *)
module Internal : sig
module M : sig
val with_span :
__FUNCTION__:string option ->
__FILE__:string ->
__LINE__:int ->
data:(string * Otrace.user_data) list ->
string (* span name *) ->
(Otrace.span -> 'a) ->
'a
(** Implements {!Trace_core.Collector.S.with_span}, with the OpenTelemetry
collector as the backend. Invoked via {!Trace_core.with_span}.
Notably, this has the same implicit-scope semantics as
{!Opentelemetry.Trace.with_}, and requires configuration of
{!Ambient_context}.
@see <https://github.com/ELLIOTTCABLE/ocaml-ambient-context> ambient-context docs *)
val enter_manual_span :
parent:Otrace.explicit_span option ->
flavor:'a ->
__FUNCTION__:string option ->
__FILE__:string ->
__LINE__:int ->
data:(string * Otrace.user_data) list ->
string (* span name *) ->
Otrace.explicit_span
(** Implements {!Trace_core.Collector.S.enter_manual_span}, with the
OpenTelemetry collector as the backend. Invoked at
{!Trace_core.enter_manual_toplevel_span} and
{!Trace_core.enter_manual_sub_span}; requires an eventual call to
{!Trace_core.exit_manual_span}.
These 'manual span' functions {e do not} implement the same implicit-
scope semantics of {!with_span}; and thus don't need to wrap a single
stack-frame / callback; you can freely enter a span at any point, store
the returned {!Trace_core.explicit_span}, and exit it at any later point
with {!Trace_core.exit_manual_span}.
However, for that same reason, they also cannot update the
{!Ambient_context} — that is, when you invoke the various [manual]
functions, if you then invoke other functions that use
{!Trace_core.with_span}, those callees {e will not} see the span you
entered manually as their [parent].
Generally, the best practice is to only use these [manual] functions at
the 'leaves' of your callstack: that is, don't invoke user callbacks
from within them; or if you do, make sure to pass the [explicit_span]
you recieve from this function onwards to the user callback, so they can create further
child-spans. *)
val exit_manual_span : Otrace.explicit_span -> unit
(** Implements {!Trace_core.Collector.S.exit_manual_span}, with the
OpenTelemetry collector as the backend. Invoked at
{!Trace_core.exit_manual_span}. Expects the [explicit_span] returned
from an earlier call to {!Trace_core.enter_manual_toplevel_span} or
{!Trace_core.enter_manual_sub_span}.
(See the notes at {!enter_manual_span} about {!Ambient_context}.) *)
val add_data_to_span :
Otrace.span -> (string * Otrace.user_data) list -> unit
val add_data_to_manual_span :
Otrace.explicit_span -> (string * Otrace.user_data) list -> unit
val message :
?span:Otrace.span ->
data:(string * Otrace.user_data) list ->
string ->
unit
val shutdown : unit -> unit
val name_process : string -> unit
val name_thread : string -> unit
val counter_int :
data:(string * Otrace.user_data) list -> string -> int -> unit
val counter_float :
data:(string * Otrace.user_data) list -> string -> float -> unit
end
type span_begin = {
id: Otel.Span_id.t;
start_time: int64;
name: string;
data: (string * Otrace.user_data) list;
__FILE__: string;
__LINE__: int;
__FUNCTION__: string option;
trace_id: Otel.Trace_id.t;
scope: Otel.Scope.t;
parent_id: Otel.Span_id.t option;
parent_scope: Otel.Scope.t option;
}
module Active_span_tbl : Hashtbl.S with type key = Otrace.span
(** Table indexed by ocaml-trace spans. *)
module Active_spans : sig
type t = private { tbl: span_begin Active_span_tbl.t } [@@unboxed]
val create : unit -> t
val tls : t TLS.t
val get : unit -> t
end
val otrace_of_otel : Otel.Span_id.t -> Otrace.span
val otel_of_otrace : Otrace.span -> Otel.Span_id.t
val enter_span' :
?explicit_parent:Otrace.span ->
__FUNCTION__:string option ->
__FILE__:string ->
__LINE__:int ->
data:(string * Otrace.user_data) list ->
string ->
Otrace.span * span_begin
val exit_span' : Otrace.span -> span_begin -> Otel.Span.t
end