diff --git a/src/trace/opentelemetry_trace.ml b/src/trace/opentelemetry_trace.ml index 1d2f7f34..ba3c8462 100644 --- a/src/trace/opentelemetry_trace.ml +++ b/src/trace/opentelemetry_trace.ml @@ -50,57 +50,30 @@ end open Conv -module Well_known = struct - let spankind_key = "otrace.spankind" - - let internal = `String "INTERNAL" - - let server = `String "SERVER" - - let client = `String "CLIENT" - - let producer = `String "PRODUCER" - - let consumer = `String "CONSUMER" - - let spankind_of_string = - let open Otel.Span in - function - | "INTERNAL" -> Span_kind_internal - | "SERVER" -> Span_kind_server - | "CLIENT" -> Span_kind_client - | "PRODUCER" -> Span_kind_producer - | "CONSUMER" -> Span_kind_consumer - | _ -> Span_kind_unspecified - - let otel_attrs_of_otrace_data data = - let kind : Otel.Span.kind ref = ref Otel.Span.Span_kind_unspecified in - let data = - List.filter_map - (function - | name, `String v when name = "otrace.spankind" -> - kind := spankind_of_string v; - None - | x -> Some x) - data - in - !kind, data - - (** Key to store an error [Otel.Span.status] with the message. Set - ["otrace.error" = "mymsg"] in a span data to set the span's status to - [{message="mymsg"; code=Error}]. *) - let status_error_key = "otrace.error" -end - -open Well_known - let on_internal_error = ref (fun msg -> Printf.eprintf "error in Opentelemetry_trace: %s\n%!" msg) -type Otrace.extension_event += - | Ev_link_span of Otrace.explicit_span * Otrace.explicit_span - | Ev_set_span_kind of Otrace.explicit_span * Otel.Span_kind.t - | Ev_record_exn of Otrace.explicit_span * exn * Printexc.raw_backtrace +module Extensions = struct + type Otrace.extension_event += + | Ev_link_span of Otrace.explicit_span * Otrace.explicit_span + | Ev_record_exn of Otrace.explicit_span * exn * Printexc.raw_backtrace + | Ev_set_span_kind of Otrace.explicit_span * Otel.Span_kind.t +end + +open Extensions +module Span_tbl = Trace_subscriber.Span_tbl + +(* TODO: subscriber +type state = { + foo: unit (* TODO: *) +} + +module Callbacks +*) + +let subscriber_of_exporter _ = assert false + +let collector_of_exporter _ = assert false module Internal = struct type span_begin = { @@ -190,7 +163,8 @@ module Internal = struct { start_time; name; __FILE__; __LINE__; __FUNCTION__; scope; parent } = let open Otel in let end_time = Timestamp_ns.now_unix_ns () in - let kind, attrs = otel_attrs_of_otrace_data (Scope.attrs scope) in + let kind = Scope.kind scope in + let attrs = Scope.attrs scope in let status : Span_status.t = match List.assoc_opt Well_known.status_error_key attrs with diff --git a/src/trace/opentelemetry_trace.mli b/src/trace/opentelemetry_trace.mli index eb5591fa..a8d511f6 100644 --- a/src/trace/opentelemetry_trace.mli +++ b/src/trace/opentelemetry_trace.mli @@ -9,26 +9,13 @@ 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.) + We use [Trace_core.extension_event] to add more features on top of the + common tracing interface. For example to set the "span kind": {[ - let describe () = [ Opentelemetry_trace.(spankind_key, client) ] in - Trace_core.with_span ~__FILE__ ~__LINE__ ~data:describe "my-span" - @@ fun _ -> - (* ... *) + let@ span = Trace_core.with_span ~__FILE__ ~__LINE__ "my-span" in + Opentelemetry_trace.set_span_kind span Span_kind_client + (* ... *) ]} *) module Otel := Opentelemetry @@ -78,7 +65,12 @@ val setup_with_otel_exporter : #Opentelemetry.Exporter.t -> unit val setup_with_otel_backend : #Opentelemetry.Exporter.t -> unit [@@deprecated "use setup_with_otel_exporter"] +val subscriber_of_exporter : #Otel.Exporter.t -> Trace_subscriber.t + +val collector_of_exporter : #Otel.Exporter.t -> Trace_core.collector + val collector : unit -> Trace_core.collector +[@@deprecated "use collector_of_exporter, avoid global state"] (** Make a Trace collector that uses the OTEL backend to send spans and logs *) val link_spans : Otrace.explicit_span -> Otrace.explicit_span -> unit @@ -115,132 +107,3 @@ module Well_known : sig Otel.Span.kind * Otel.Span.key_value list end [@@deprecated "use the regular functions for this"] - -(**/**) - -(** 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 - ambient-context docs *) - - val enter_manual_span : - parent:Otrace.explicit_span_ctx 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 = { - start_time: int64; - name: string; - __FILE__: string; - __LINE__: int; - __FUNCTION__: string option; - scope: Otel.Scope.t; - parent: Otel.Span_ctx.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 k_tls : t TLS.t - - val get : unit -> t - end - - val otrace_of_otel : Otel.Span_id.t -> Otrace.span - - val enter_span' : - ?explicit_parent:Otrace.explicit_span_ctx -> - __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 - -(**/**)