Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add extensions to otel.trace #77

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 77 additions & 12 deletions src/core/opentelemetry.ml
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,12 @@ module Span_link : sig
unit ->
t

val of_span_ctx : ?attrs:key_value list -> Span_ctx.t -> t
val of_span_ctx :
?trace_state:string ->
?attrs:key_value list ->
?dropped_attributes_count:int ->
Span_ctx.t ->
t
end = struct
open Proto.Trace

Expand All @@ -799,9 +804,10 @@ end = struct
~span_id:(Span_id.to_bytes span_id) ?trace_state ~attributes
?dropped_attributes_count ()

let[@inline] of_span_ctx ?attrs (ctx : Span_ctx.t) : t =
let[@inline] of_span_ctx ?trace_state ?attrs ?dropped_attributes_count
(ctx : Span_ctx.t) : t =
make ~trace_id:(Span_ctx.trace_id ctx) ~span_id:(Span_ctx.parent_id ctx)
?attrs ()
?trace_state ?attrs ?dropped_attributes_count ()
end

module Span_status : sig
Expand Down Expand Up @@ -834,6 +840,29 @@ end = struct
let make ~message ~code = { message; code }
end

(** @since NEXT_RELEASE *)
module Span_kind : sig
open Proto.Trace

type t = span_span_kind =
| Span_kind_unspecified
| Span_kind_internal
| Span_kind_server
| Span_kind_client
| Span_kind_producer
| Span_kind_consumer
end = struct
open Proto.Trace

type t = span_span_kind =
| Span_kind_unspecified
| Span_kind_internal
| Span_kind_server
| Span_kind_client
| Span_kind_producer
| Span_kind_consumer
end

(** {2 Scopes} *)

(** Scopes.
Expand All @@ -857,6 +886,8 @@ module Scope : sig

val status : t -> Span_status.t option

val kind : t -> Span_kind.t option

val make :
trace_id:Trace_id.t ->
span_id:Span_id.t ->
Expand All @@ -867,6 +898,14 @@ module Scope : sig
unit ->
t

val to_span_link :
?trace_state:string ->
?attrs:key_value list ->
?dropped_attributes_count:int ->
t ->
Span_link.t
(** Turn the scope into a span link *)
Comment on lines +901 to +907
Copy link
Contributor

@tatchi tatchi Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently doing the following in a codebase to get the span_link

scope |> Scope.to_span_ctx |> Span_link.of_span_ctx

Is the Span_link.of_span_ctx still required now that we can go directly from scope to span_link ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if yes, should we add ?dropped_attributes_count:int to the Span_link.of_span_ctx to be consistent ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can keep both, but yes, adding the optional arguments is good for consistency.


val to_span_ctx : t -> Span_ctx.t
(** Turn the scope into a span context *)

Expand Down Expand Up @@ -896,6 +935,10 @@ module Scope : sig
Note that this function will be
called only if there is an instrumentation backend. *)

val set_kind : t -> Span_kind.t -> unit
(** Set the span's kind.
@since NEXT_RELEASE *)

val ambient_scope_key : t Ambient_context.key
(** The opaque key necessary to access/set the ambient scope with
{!Ambient_context}. *)
Expand All @@ -916,6 +959,7 @@ end = struct
| Attr of key_value * item_list
| Span_link of Span_link.t * item_list
| Span_status of Span_status.t * item_list
| Span_kind of Span_kind.t * item_list

type t = {
trace_id: Trace_id.t;
Expand All @@ -927,33 +971,46 @@ end = struct
let rec loop acc = function
| Nil -> acc
| Attr (attr, l) -> loop (attr :: acc) l
| Ev (_, l) | Span_link (_, l) | Span_status (_, l) -> loop acc l
| Ev (_, l) | Span_kind (_, l) | Span_link (_, l) | Span_status (_, l) ->
loop acc l
in
loop [] scope.items

let events scope =
let rec loop acc = function
| Nil -> acc
| Ev (event, l) -> loop (event :: acc) l
| Attr (_, l) | Span_link (_, l) | Span_status (_, l) -> loop acc l
| Attr (_, l) | Span_kind (_, l) | Span_link (_, l) | Span_status (_, l)
->
loop acc l
in
loop [] scope.items

let links scope =
let rec loop acc = function
| Nil -> acc
| Span_link (span_link, l) -> loop (span_link :: acc) l
| Ev (_, l) | Attr (_, l) | Span_status (_, l) -> loop acc l
| Ev (_, l) | Span_kind (_, l) | Attr (_, l) | Span_status (_, l) ->
loop acc l
in
loop [] scope.items

let status scope =
let rec loop acc = function
| Nil -> acc
let rec loop = function
| Nil -> None
| Span_status (status, _) -> Some status
| Ev (_, l) | Attr (_, l) | Span_link (_, l) -> loop acc l
| Ev (_, l) | Attr (_, l) | Span_kind (_, l) | Span_link (_, l) -> loop l
in
loop scope.items

let kind scope =
let rec loop = function
| Nil -> None
| Span_kind (k, _) -> Some k
| Ev (_, l) | Span_status (_, l) | Attr (_, l) | Span_link (_, l) ->
loop l
in
loop None scope.items
loop scope.items

let make ~trace_id ~span_id ?(events = []) ?(attrs = []) ?(links = []) ?status
() : t =
Expand All @@ -971,6 +1028,11 @@ end = struct
in
{ trace_id; span_id; items }

let[@inline] to_span_link ?trace_state ?attrs ?dropped_attributes_count
(self : t) : Span_link.t =
Span_link.make ?trace_state ?attrs ?dropped_attributes_count
~trace_id:self.trace_id ~span_id:self.span_id ()

let[@inline] to_span_ctx (self : t) : Span_ctx.t =
Span_ctx.make ~trace_id:self.trace_id ~parent_id:self.span_id ()

Expand Down Expand Up @@ -1008,6 +1070,9 @@ end = struct
if Collector.has_backend () then
scope.items <- Span_status (status, scope.items)

let set_kind (scope : t) (k : Span_kind.t) : unit =
if Collector.has_backend () then scope.items <- Span_kind (k, scope.items)

let ambient_scope_key : t Ambient_context.key = Ambient_context.create_key ()

let get_ambient_scope ?scope () : t option =
Expand All @@ -1034,7 +1099,7 @@ module Span : sig

type id = Span_id.t

type nonrec kind = span_span_kind =
type kind = Span_kind.t =
| Span_kind_unspecified
| Span_kind_internal
| Span_kind_server
Expand Down Expand Up @@ -1079,7 +1144,7 @@ end = struct

type id = Span_id.t

type nonrec kind = span_span_kind =
type kind = Span_kind.t =
| Span_kind_unspecified
| Span_kind_internal
| Span_kind_server
Expand Down
40 changes: 37 additions & 3 deletions src/trace/opentelemetry_trace.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ 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 Internal = struct
type span_begin = {
start_time: int64;
Expand Down Expand Up @@ -193,6 +198,9 @@ module Internal = struct
Active_span_tbl.remove active_spans.tbl otrace_id;
Some (exit_span_ otel_span_begin)

let[@inline] get_scope (span : Otrace.explicit_span) : Otel.Scope.t option =
Otrace.Meta_map.find k_explicit_scope span.meta

module M = struct
let with_span ~__FUNCTION__ ~__FILE__ ~__LINE__ ~data name cb =
let otrace_id, sb =
Expand Down Expand Up @@ -259,10 +267,10 @@ module Internal = struct
| Some sb -> Otel.Scope.add_attrs sb.scope (fun () -> data)

let add_data_to_manual_span (span : Otrace.explicit_span) data : unit =
match Otrace.Meta_map.find_exn k_explicit_scope span.meta with
| exception _ ->
match get_scope span with
| None ->
!on_internal_error (spf "manual span does not a contain an OTEL scope")
| scope -> Otel.Scope.add_attrs scope (fun () -> data)
| Some scope -> Otel.Scope.add_attrs scope (fun () -> data)

let message ?span ~data:_ msg : unit =
(* gather information from context *)
Expand Down Expand Up @@ -293,9 +301,35 @@ module Internal = struct
let _kind, attrs = otel_attrs_of_otrace_data data in
let m = Otel.Metrics.(gauge ~name [ float ~attrs cur_val ]) in
Otel.Metrics.emit [ m ]

let extension_event = function
| Ev_link_span (sp1, sp2) ->
(match get_scope sp1, get_scope sp2 with
| Some sc1, Some sc2 ->
Otel.Scope.add_links sc1 (fun () -> [ Otel.Scope.to_span_link sc2 ])
| _ -> !on_internal_error "could not find scope for OTEL span")
| Ev_set_span_kind (sp, k) ->
(match get_scope sp with
| None -> !on_internal_error "could not find scope for OTEL span"
| Some sc -> Otel.Scope.set_kind sc k)
| Ev_record_exn (sp, exn, bt) ->
(match get_scope sp with
| None -> !on_internal_error "could not find scope for OTEL span"
| Some sc -> Otel.Scope.record_exception sc exn bt)
| _ -> ()
end
end

let link_spans (sp1 : Otrace.explicit_span) (sp2 : Otrace.explicit_span) : unit
=
if Otrace.enabled () then Otrace.extension_event @@ Ev_link_span (sp1, sp2)

let set_span_kind sp k : unit =
if Otrace.enabled () then Otrace.extension_event @@ Ev_set_span_kind (sp, k)

let record_exception sp exn bt : unit =
if Otrace.enabled () then Otrace.extension_event @@ Ev_record_exn (sp, exn, bt)

let collector () : Otrace.collector = (module Internal.M)

let setup () = Otrace.setup_collector @@ collector ()
Expand Down
14 changes: 14 additions & 0 deletions src/trace/opentelemetry_trace.mli
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ val setup_with_otel_backend : Opentelemetry.Collector.backend -> unit
val collector : unit -> Trace_core.collector
(** Make a Trace collector that uses the OTEL backend to send spans and logs *)

val link_spans : Otrace.explicit_span -> Otrace.explicit_span -> unit
(** [link_spans sp1 sp2] modifies [sp1] by adding a span link to [sp2].
@since NEXT_RELEASE *)

val set_span_kind : Otrace.explicit_span -> Otel.Span.kind -> unit
(** [set_span_kind sp k] sets the span's kind.
@since NEXT_RELEASE *)

val record_exception :
Otrace.explicit_span -> exn -> Printexc.raw_backtrace -> unit
(** Record exception in the current span.
@since NEXT_RELEASE *)

(** Static references for well-known identifiers; see {!label-wellknown}. *)
module Well_known : sig
val spankind_key : string
Expand All @@ -68,6 +81,7 @@ module Well_known : sig
(string * Otrace.user_data) list ->
Otel.Span.kind * Otel.Span.key_value list
end
[@@deprecated "use the regular functions for this"]

(**/**)

Expand Down
Loading