mirror of
https://github.com/ocaml-tracing/ocaml-opentelemetry.git
synced 2026-03-09 12:23:32 -04:00
commit
0fb530125a
21 changed files with 446 additions and 385 deletions
4
dune
4
dune
|
|
@ -1,3 +1,3 @@
|
||||||
|
|
||||||
(env
|
(env
|
||||||
(_ (flags :standard -warn-error -a+8)))
|
(_
|
||||||
|
(flags :standard -warn-error -a+8)))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
(* *)
|
(* *)
|
||||||
(* OCaml *)
|
(* OCaml *)
|
||||||
|
|
@ -19,34 +18,34 @@
|
||||||
(** Atomic references.
|
(** Atomic references.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** An atomic (mutable) reference to a value of type ['a]. *)
|
|
||||||
type 'a t = 'a Stdlib.Atomic.t
|
type 'a t = 'a Stdlib.Atomic.t
|
||||||
|
(** An atomic (mutable) reference to a value of type ['a]. *)
|
||||||
|
|
||||||
(** Create an atomic reference. *)
|
|
||||||
val make : 'a -> 'a t
|
val make : 'a -> 'a t
|
||||||
|
(** Create an atomic reference. *)
|
||||||
|
|
||||||
(** Get the current value of the atomic reference. *)
|
|
||||||
val get : 'a t -> 'a
|
val get : 'a t -> 'a
|
||||||
|
(** Get the current value of the atomic reference. *)
|
||||||
|
|
||||||
(** Set a new value for the atomic reference. *)
|
|
||||||
val set : 'a t -> 'a -> unit
|
val set : 'a t -> 'a -> unit
|
||||||
|
(** Set a new value for the atomic reference. *)
|
||||||
|
|
||||||
(** Set a new value for the atomic reference, and return the current value. *)
|
|
||||||
val exchange : 'a t -> 'a -> 'a
|
val exchange : 'a t -> 'a -> 'a
|
||||||
|
(** Set a new value for the atomic reference, and return the current value. *)
|
||||||
|
|
||||||
|
val compare_and_set : 'a t -> 'a -> 'a -> bool
|
||||||
(** [compare_and_set r seen v] sets the new value of [r] to [v] only
|
(** [compare_and_set r seen v] sets the new value of [r] to [v] only
|
||||||
if its current value is physically equal to [seen] -- the
|
if its current value is physically equal to [seen] -- the
|
||||||
comparison and the set occur atomically. Returns [true] if the
|
comparison and the set occur atomically. Returns [true] if the
|
||||||
comparison succeeded (so the set happened) and [false]
|
comparison succeeded (so the set happened) and [false]
|
||||||
otherwise. *)
|
otherwise. *)
|
||||||
val compare_and_set : 'a t -> 'a -> 'a -> bool
|
|
||||||
|
|
||||||
|
val fetch_and_add : int t -> int -> int
|
||||||
(** [fetch_and_add r n] atomically increments the value of [r] by [n],
|
(** [fetch_and_add r n] atomically increments the value of [r] by [n],
|
||||||
and returns the current value (before the increment). *)
|
and returns the current value (before the increment). *)
|
||||||
val fetch_and_add : int t -> int -> int
|
|
||||||
|
|
||||||
(** [incr r] atomically increments the value of [r] by [1]. *)
|
|
||||||
val incr : int t -> unit
|
val incr : int t -> unit
|
||||||
|
(** [incr r] atomically increments the value of [r] by [1]. *)
|
||||||
|
|
||||||
(** [decr r] atomically decrements the value of [r] by [1]. *)
|
|
||||||
val decr : int t -> unit
|
val decr : int t -> unit
|
||||||
|
(** [decr r] atomically decrements the value of [r] by [1]. *)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
(* *)
|
(* *)
|
||||||
(* OCaml *)
|
(* OCaml *)
|
||||||
|
|
@ -19,34 +18,34 @@
|
||||||
(** Atomic references.
|
(** Atomic references.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** An atomic (mutable) reference to a value of type ['a]. *)
|
|
||||||
type 'a t
|
type 'a t
|
||||||
|
(** An atomic (mutable) reference to a value of type ['a]. *)
|
||||||
|
|
||||||
(** Create an atomic reference. *)
|
|
||||||
val make : 'a -> 'a t
|
val make : 'a -> 'a t
|
||||||
|
(** Create an atomic reference. *)
|
||||||
|
|
||||||
(** Get the current value of the atomic reference. *)
|
|
||||||
val get : 'a t -> 'a
|
val get : 'a t -> 'a
|
||||||
|
(** Get the current value of the atomic reference. *)
|
||||||
|
|
||||||
(** Set a new value for the atomic reference. *)
|
|
||||||
val set : 'a t -> 'a -> unit
|
val set : 'a t -> 'a -> unit
|
||||||
|
(** Set a new value for the atomic reference. *)
|
||||||
|
|
||||||
(** Set a new value for the atomic reference, and return the current value. *)
|
|
||||||
val exchange : 'a t -> 'a -> 'a
|
val exchange : 'a t -> 'a -> 'a
|
||||||
|
(** Set a new value for the atomic reference, and return the current value. *)
|
||||||
|
|
||||||
|
val compare_and_set : 'a t -> 'a -> 'a -> bool
|
||||||
(** [compare_and_set r seen v] sets the new value of [r] to [v] only
|
(** [compare_and_set r seen v] sets the new value of [r] to [v] only
|
||||||
if its current value is physically equal to [seen] -- the
|
if its current value is physically equal to [seen] -- the
|
||||||
comparison and the set occur atomically. Returns [true] if the
|
comparison and the set occur atomically. Returns [true] if the
|
||||||
comparison succeeded (so the set happened) and [false]
|
comparison succeeded (so the set happened) and [false]
|
||||||
otherwise. *)
|
otherwise. *)
|
||||||
val compare_and_set : 'a t -> 'a -> 'a -> bool
|
|
||||||
|
|
||||||
|
val fetch_and_add : int t -> int -> int
|
||||||
(** [fetch_and_add r n] atomically increments the value of [r] by [n],
|
(** [fetch_and_add r n] atomically increments the value of [r] by [n],
|
||||||
and returns the current value (before the increment). *)
|
and returns the current value (before the increment). *)
|
||||||
val fetch_and_add : int t -> int -> int
|
|
||||||
|
|
||||||
(** [incr r] atomically increments the value of [r] by [1]. *)
|
|
||||||
val incr : int t -> unit
|
val incr : int t -> unit
|
||||||
|
(** [incr r] atomically increments the value of [r] by [1]. *)
|
||||||
|
|
||||||
(** [decr r] atomically decrements the value of [r] by [1]. *)
|
|
||||||
val decr : int t -> unit
|
val decr : int t -> unit
|
||||||
|
(** [decr r] atomically decrements the value of [r] by [1]. *)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name opentelemetry_atomic)
|
(name opentelemetry_atomic)
|
||||||
(synopsis "Compatibility package for the Atomic module for opentelemetry")
|
(synopsis "Compatibility package for the Atomic module for opentelemetry")
|
||||||
(public_name opentelemetry.atomic)
|
(public_name opentelemetry.atomic)
|
||||||
(modules atomic))
|
(modules atomic))
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(modules gen)
|
(modules gen)
|
||||||
(name gen))
|
(name gen))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(targets atomic.ml atomic.mli atomic.ml)
|
(targets atomic.ml atomic.mli atomic.ml)
|
||||||
(deps atomic.pre412.mli atomic.post412.mli)
|
(deps atomic.pre412.mli atomic.post412.mli)
|
||||||
(action (run ./gen.exe)))
|
(action
|
||||||
|
(run ./gen.exe)))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
|
let atomic_before_412 =
|
||||||
|
{|
|
||||||
let atomic_before_412 = {|
|
|
||||||
type 'a t = {mutable x: 'a}
|
type 'a t = {mutable x: 'a}
|
||||||
let[@inline] make x = {x}
|
let[@inline] make x = {x}
|
||||||
let[@inline] get {x} = x
|
let[@inline] get {x} = x
|
||||||
|
|
@ -32,7 +31,9 @@ let atomic_before_412 = {|
|
||||||
let atomic_after_412 = {|include Stdlib.Atomic|}
|
let atomic_after_412 = {|include Stdlib.Atomic|}
|
||||||
|
|
||||||
let write_file file s =
|
let write_file file s =
|
||||||
let oc = open_out file in output_string oc s; close_out oc
|
let oc = open_out file in
|
||||||
|
output_string oc s;
|
||||||
|
close_out oc
|
||||||
|
|
||||||
let copy_file file1 file2 =
|
let copy_file file1 file2 =
|
||||||
let oc = open_out file2 in
|
let oc = open_out file2 in
|
||||||
|
|
@ -41,14 +42,22 @@ let copy_file file1 file2 =
|
||||||
try
|
try
|
||||||
while true do
|
while true do
|
||||||
let n = input ic buf 0 (Bytes.length buf) in
|
let n = input ic buf 0 (Bytes.length buf) in
|
||||||
if n=0 then raise End_of_file;
|
if n = 0 then raise End_of_file;
|
||||||
output oc buf 0 n
|
output oc buf 0 n
|
||||||
done
|
done
|
||||||
with End_of_file -> ()
|
with End_of_file -> ()
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
let version = Scanf.sscanf Sys.ocaml_version "%d.%d.%s" (fun x y _ -> x,y) in
|
let version = Scanf.sscanf Sys.ocaml_version "%d.%d.%s" (fun x y _ -> x, y) in
|
||||||
write_file "atomic.ml" (if version >= (4,12) then atomic_after_412 else atomic_before_412);
|
write_file "atomic.ml"
|
||||||
copy_file (if version >= (4,12) then "atomic.post412.mli" else "atomic.pre412.mli") "atomic.mli" ;
|
(if version >= (4, 12) then
|
||||||
|
atomic_after_412
|
||||||
|
else
|
||||||
|
atomic_before_412);
|
||||||
|
copy_file
|
||||||
|
(if version >= (4, 12) then
|
||||||
|
"atomic.post412.mli"
|
||||||
|
else
|
||||||
|
"atomic.pre412.mli")
|
||||||
|
"atomic.mli";
|
||||||
()
|
()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
module Atomic = Opentelemetry_atomic.Atomic
|
module Atomic = Opentelemetry_atomic.Atomic
|
||||||
|
|
||||||
type 'a t = 'a list Atomic.t
|
type 'a t = 'a list Atomic.t
|
||||||
|
|
||||||
let make () = Atomic.make []
|
let make () = Atomic.make []
|
||||||
|
|
||||||
let add self x =
|
let add self x =
|
||||||
while
|
while
|
||||||
let old = Atomic.get self in
|
let old = Atomic.get self in
|
||||||
let l' = x :: old in
|
let l' = x :: old in
|
||||||
not (Atomic.compare_and_set self old l')
|
not (Atomic.compare_and_set self old l')
|
||||||
do () done
|
do
|
||||||
|
()
|
||||||
|
done
|
||||||
|
|
||||||
let rec pop_all self =
|
let rec pop_all self =
|
||||||
let l = Atomic.get self in
|
let l = Atomic.get self in
|
||||||
if Atomic.compare_and_set self l [] then l else pop_all self
|
if Atomic.compare_and_set self l [] then
|
||||||
|
l
|
||||||
|
else
|
||||||
|
pop_all self
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
(** Atomic list *)
|
(** Atomic list *)
|
||||||
|
|
||||||
type 'a t
|
type 'a t
|
||||||
|
|
||||||
val make : unit -> 'a t
|
val make : unit -> 'a t
|
||||||
|
|
||||||
val add : 'a t -> 'a -> unit
|
val add : 'a t -> 'a -> unit
|
||||||
|
|
||||||
val pop_all : 'a t -> 'a list
|
val pop_all : 'a t -> 'a list
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
type 'a t = {
|
type 'a t = {
|
||||||
arr: 'a array;
|
arr: 'a array;
|
||||||
mutable i: int;
|
mutable i: int;
|
||||||
|
|
@ -7,23 +5,23 @@ type 'a t = {
|
||||||
|
|
||||||
let create ~dummy n : _ t =
|
let create ~dummy n : _ t =
|
||||||
assert (n >= 1);
|
assert (n >= 1);
|
||||||
{ arr=Array.make n dummy;
|
{ arr = Array.make n dummy; i = 0 }
|
||||||
i=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let[@inline] size self = self.i
|
let[@inline] size self = self.i
|
||||||
|
|
||||||
let[@inline] is_full self = self.i = Array.length self.arr
|
let[@inline] is_full self = self.i = Array.length self.arr
|
||||||
|
|
||||||
let push (self:_ t) x : bool =
|
let push (self : _ t) x : bool =
|
||||||
if is_full self then false
|
if is_full self then
|
||||||
|
false
|
||||||
else (
|
else (
|
||||||
self.arr.(self.i) <- x;
|
self.arr.(self.i) <- x;
|
||||||
self.i <- 1 + self.i;
|
self.i <- 1 + self.i;
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
let pop_iter_all (self: _ t) f =
|
let pop_iter_all (self : _ t) f =
|
||||||
for j=0 to self.i-1 do
|
for j = 0 to self.i - 1 do
|
||||||
f self.arr.(j)
|
f self.arr.(j)
|
||||||
done;
|
done;
|
||||||
self.i <- 0
|
self.i <- 0
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
|
||||||
(** queue of fixed size *)
|
(** queue of fixed size *)
|
||||||
|
|
||||||
type 'a t
|
type 'a t
|
||||||
val create : dummy:'a -> int -> 'a t
|
|
||||||
val size : _ t -> int
|
|
||||||
val push : 'a t -> 'a -> bool (* true iff it could write element *)
|
|
||||||
val pop_iter_all : 'a t -> ('a -> unit) -> unit
|
|
||||||
|
|
||||||
|
val create : dummy:'a -> int -> 'a t
|
||||||
|
|
||||||
|
val size : _ t -> int
|
||||||
|
|
||||||
|
val push : 'a t -> 'a -> bool (* true iff it could write element *)
|
||||||
|
|
||||||
|
val pop_iter_all : 'a t -> ('a -> unit) -> unit
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
open Common_
|
open Common_
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
|
|
@ -14,28 +13,36 @@ type t = {
|
||||||
|
|
||||||
let pp out self =
|
let pp out self =
|
||||||
let ppiopt = Format.pp_print_option Format.pp_print_int in
|
let ppiopt = Format.pp_print_option Format.pp_print_int in
|
||||||
let pp_header ppf (a, b) =
|
let pp_header ppf (a, b) = Format.fprintf ppf "@[%s: @,%s@]@." a b in
|
||||||
Format.fprintf ppf "@[%s: @,%s@]@." a b ;
|
|
||||||
in
|
|
||||||
let ppheaders = Format.pp_print_list pp_header in
|
let ppheaders = Format.pp_print_list pp_header in
|
||||||
let {debug; url; headers; batch_traces; batch_metrics;
|
let {
|
||||||
batch_timeout_ms; thread; ticker_thread} = self in
|
debug;
|
||||||
|
url;
|
||||||
|
headers;
|
||||||
|
batch_traces;
|
||||||
|
batch_metrics;
|
||||||
|
batch_timeout_ms;
|
||||||
|
thread;
|
||||||
|
ticker_thread;
|
||||||
|
} =
|
||||||
|
self
|
||||||
|
in
|
||||||
Format.fprintf out
|
Format.fprintf out
|
||||||
"{@[ debug=%B;@ url=%S;@ headers=%a;@ \
|
"{@[ debug=%B;@ url=%S;@ headers=%a;@ batch_traces=%a;@ batch_metrics=%a;@ \
|
||||||
batch_traces=%a;@ batch_metrics=%a;@ \
|
|
||||||
batch_timeout_ms=%d; thread=%B;@ ticker_thread=%B @]}"
|
batch_timeout_ms=%d; thread=%B;@ ticker_thread=%B @]}"
|
||||||
debug url ppheaders headers ppiopt batch_traces ppiopt batch_metrics
|
debug url ppheaders headers ppiopt batch_traces ppiopt batch_metrics
|
||||||
batch_timeout_ms thread ticker_thread
|
batch_timeout_ms thread ticker_thread
|
||||||
|
|
||||||
let make
|
let make ?(debug = !debug_) ?(url = get_url ()) ?(headers = get_headers ())
|
||||||
?(debug= !debug_)
|
?(batch_traces = Some 400) ?(batch_metrics = None) ?(batch_timeout_ms = 500)
|
||||||
?(url= get_url())
|
?(thread = true) ?(ticker_thread = true) () : t =
|
||||||
?(headers= get_headers ())
|
{
|
||||||
?(batch_traces=Some 400)
|
debug;
|
||||||
?(batch_metrics=None)
|
url;
|
||||||
?(batch_timeout_ms=500)
|
headers;
|
||||||
?(thread=true)
|
batch_traces;
|
||||||
?(ticker_thread=true)
|
batch_metrics;
|
||||||
() : t =
|
batch_timeout_ms;
|
||||||
{ debug; url; headers; batch_traces; batch_metrics; batch_timeout_ms;
|
thread;
|
||||||
thread; ticker_thread; }
|
ticker_thread;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,49 @@
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
debug: bool;
|
debug: bool;
|
||||||
|
|
||||||
url: string;
|
url: string;
|
||||||
(** Url of the endpoint. Default is "http://localhost:4318",
|
(** Url of the endpoint. Default is "http://localhost:4318",
|
||||||
or "OTEL_EXPORTER_OTLP_ENDPOINT" if set. *)
|
or "OTEL_EXPORTER_OTLP_ENDPOINT" if set. *)
|
||||||
|
|
||||||
headers: (string * string) list;
|
headers: (string * string) list;
|
||||||
(** API headers sent to the endpoint. Default is none or
|
(** API headers sent to the endpoint. Default is none or
|
||||||
"OTEL_EXPORTER_OTLP_HEADERS" if set. *)
|
"OTEL_EXPORTER_OTLP_HEADERS" if set. *)
|
||||||
|
|
||||||
batch_traces: int option;
|
batch_traces: int option;
|
||||||
(** Batch traces? If [Some i], then this produces batches of (at most)
|
(** Batch traces? If [Some i], then this produces batches of (at most)
|
||||||
[i] items. If [None], there is no batching.
|
[i] items. If [None], there is no batching.
|
||||||
|
|
||||||
Note that traces and metrics are batched separately.
|
Note that traces and metrics are batched separately.
|
||||||
Default [Some 400].
|
Default [Some 400].
|
||||||
*)
|
*)
|
||||||
|
|
||||||
batch_metrics: int option;
|
batch_metrics: int option;
|
||||||
(** Batch metrics? If [Some i], then this produces batches of (at most)
|
(** Batch metrics? If [Some i], then this produces batches of (at most)
|
||||||
[i] items. If [None], there is no batching.
|
[i] items. If [None], there is no batching.
|
||||||
|
|
||||||
Note that traces and metrics are batched separately.
|
Note that traces and metrics are batched separately.
|
||||||
Default [None].
|
Default [None].
|
||||||
*)
|
*)
|
||||||
|
|
||||||
batch_timeout_ms: int;
|
batch_timeout_ms: int;
|
||||||
(** Number of milliseconds after which we will emit a batch, even
|
(** Number of milliseconds after which we will emit a batch, even
|
||||||
incomplete.
|
incomplete.
|
||||||
Note that the batch might take longer than that, because this is
|
Note that the batch might take longer than that, because this is
|
||||||
only checked when a new event occurs. Default 500. *)
|
only checked when a new event occurs. Default 500. *)
|
||||||
|
thread: bool; (** Is there a background thread? Default [true] *)
|
||||||
thread: bool;
|
|
||||||
(** Is there a background thread? Default [true] *)
|
|
||||||
|
|
||||||
ticker_thread: bool;
|
ticker_thread: bool;
|
||||||
(** Is there a ticker thread? Default [true].
|
(** Is there a ticker thread? Default [true].
|
||||||
This thread will regularly call [tick()] on the backend, to make
|
This thread will regularly call [tick()] on the backend, to make
|
||||||
sure it makes progress, and regularly send events to the collector.
|
sure it makes progress, and regularly send events to the collector.
|
||||||
This option is ignored if [thread=false]. *)
|
This option is ignored if [thread=false]. *)
|
||||||
}
|
}
|
||||||
|
|
||||||
val make :
|
val make :
|
||||||
?debug:bool -> ?url:string ->
|
?debug:bool ->
|
||||||
|
?url:string ->
|
||||||
?headers:(string * string) list ->
|
?headers:(string * string) list ->
|
||||||
?batch_traces:int option ->
|
?batch_traces:int option ->
|
||||||
?batch_metrics:int option ->
|
?batch_metrics:int option ->
|
||||||
?batch_timeout_ms:int ->
|
?batch_timeout_ms:int ->
|
||||||
?thread:bool ->
|
?thread:bool ->
|
||||||
?ticker_thread:bool ->
|
?ticker_thread:bool ->
|
||||||
unit -> t
|
unit ->
|
||||||
|
t
|
||||||
(** Make a configuration *)
|
(** Make a configuration *)
|
||||||
|
|
||||||
val pp : Format.formatter -> t -> unit
|
val pp : Format.formatter -> t -> unit
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name opentelemetry_client_ocurl)
|
(name opentelemetry_client_ocurl)
|
||||||
(public_name opentelemetry-client-ocurl)
|
(public_name opentelemetry-client-ocurl)
|
||||||
(libraries opentelemetry opentelemetry.atomic
|
(libraries opentelemetry opentelemetry.atomic curl pbrt threads mtime
|
||||||
curl pbrt threads
|
mtime.clock.os))
|
||||||
mtime mtime.clock.os))
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(*
|
(*
|
||||||
TODO: more options from
|
TODO: more options from
|
||||||
https://opentelemetry.io/docs/reference/specification/protocol/exporter/
|
https://opentelemetry.io/docs/reference/specification/protocol/exporter/
|
||||||
|
|
|
||||||
149
src/dune
149
src/dune
|
|
@ -8,88 +8,91 @@
|
||||||
; ### protobuf rules ###
|
; ### protobuf rules ###
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets status_types.ml status_types.mli
|
(targets status_types.ml status_types.mli status_pb.ml status_pb.mli
|
||||||
status_pb.ml status_pb.mli
|
status_pp.ml status_pp.mli)
|
||||||
status_pp.ml status_pp.mli)
|
(deps
|
||||||
(deps (:file status.proto)
|
(:file status.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file} -ml_out . -pp -binary)))
|
(action
|
||||||
|
(run ocaml-protoc %{file} -ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets common_types.ml common_types.mli
|
(targets common_types.ml common_types.mli common_pb.ml common_pb.mli
|
||||||
common_pb.ml common_pb.mli
|
common_pp.ml common_pp.mli)
|
||||||
common_pp.ml common_pp.mli)
|
(deps
|
||||||
(deps
|
(:file
|
||||||
(:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto)
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file}
|
(action
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
-ml_out . -pp -binary)))
|
-ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets resource_types.ml resource_types.mli
|
(targets resource_types.ml resource_types.mli resource_pb.ml resource_pb.mli
|
||||||
resource_pb.ml resource_pb.mli
|
resource_pp.ml resource_pp.mli)
|
||||||
resource_pp.ml resource_pp.mli)
|
(deps
|
||||||
(deps
|
(:file
|
||||||
(:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto)
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file}
|
(action
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
-ml_out . -pp -binary)))
|
-ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets trace_types.ml trace_types.mli
|
(targets trace_types.ml trace_types.mli trace_pb.ml trace_pb.mli trace_pp.ml
|
||||||
trace_pb.ml trace_pb.mli
|
trace_pp.mli)
|
||||||
trace_pp.ml trace_pp.mli)
|
(deps
|
||||||
(deps
|
(:file
|
||||||
(:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto)
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file}
|
(action
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
-ml_out . -pp -binary)))
|
-ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets metrics_types.ml metrics_types.mli
|
(targets metrics_types.ml metrics_types.mli metrics_pb.ml metrics_pb.mli
|
||||||
metrics_pb.ml metrics_pb.mli
|
metrics_pp.ml metrics_pp.mli)
|
||||||
metrics_pp.ml metrics_pp.mli)
|
(deps
|
||||||
(deps
|
(:file
|
||||||
(:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto)
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file}
|
(action
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
-ml_out . -pp -binary)))
|
-ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets metrics_service_types.ml metrics_service_types.mli
|
(targets metrics_service_types.ml metrics_service_types.mli
|
||||||
metrics_service_pp.ml metrics_service_pp.mli
|
metrics_service_pp.ml metrics_service_pp.mli metrics_service_pb.ml
|
||||||
metrics_service_pb.ml metrics_service_pb.mli)
|
metrics_service_pb.mli)
|
||||||
(deps (:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service.proto)
|
(deps
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(:file
|
||||||
(action (run ocaml-protoc %{file}
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service.proto)
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
-ml_out . -pp -binary)))
|
(action
|
||||||
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
|
-ml_out . -pp -binary)))
|
||||||
|
|
||||||
(rule
|
(rule
|
||||||
(alias lint)
|
(alias lint)
|
||||||
(mode promote)
|
(mode promote)
|
||||||
(targets trace_service_types.ml trace_service_types.mli
|
(targets trace_service_types.ml trace_service_types.mli trace_service_pp.ml
|
||||||
trace_service_pp.ml trace_service_pp.mli
|
trace_service_pp.mli trace_service_pb.ml trace_service_pb.mli)
|
||||||
trace_service_pb.ml trace_service_pb.mli)
|
(deps
|
||||||
(deps
|
(:file
|
||||||
(:file %{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service.proto)
|
%{project_root}/vendor/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service.proto)
|
||||||
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
(source_tree %{project_root}/vendor/opentelemetry-proto/))
|
||||||
(action (run ocaml-protoc %{file}
|
(action
|
||||||
-I %{project_root}/vendor/opentelemetry-proto/
|
(run ocaml-protoc %{file} -I %{project_root}/vendor/opentelemetry-proto/
|
||||||
-ml_out . -pp -binary)))
|
-ml_out . -pp -binary)))
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,14 @@ open Cohttp
|
||||||
open Cohttp_lwt
|
open Cohttp_lwt
|
||||||
|
|
||||||
module Server : sig
|
module Server : sig
|
||||||
|
val trace :
|
||||||
|
?service_name:string ->
|
||||||
|
?attrs:Otel.Span.key_value list ->
|
||||||
|
('conn -> Request.t -> 'body -> (Response.t * 'body) Lwt.t) ->
|
||||||
|
'conn ->
|
||||||
|
Request.t ->
|
||||||
|
'body ->
|
||||||
|
(Response.t * 'body) Lwt.t
|
||||||
(** Trace requests to a Cohttp server.
|
(** Trace requests to a Cohttp server.
|
||||||
|
|
||||||
Use it like this:
|
Use it like this:
|
||||||
|
|
@ -18,19 +26,8 @@ module Server : sig
|
||||||
~mode:(`TCP (`Port 8080))
|
~mode:(`TCP (`Port 8080))
|
||||||
(Server.make () ~callback:callback_traced)
|
(Server.make () ~callback:callback_traced)
|
||||||
*)
|
*)
|
||||||
val trace :
|
|
||||||
?service_name:string ->
|
|
||||||
?attrs:Otel.Span.key_value list ->
|
|
||||||
('conn -> Request.t -> 'body -> (Response.t * 'body) Lwt.t) ->
|
|
||||||
'conn -> Request.t -> 'body -> (Response.t * 'body) Lwt.t
|
|
||||||
|
|
||||||
(** Trace a new internal span.
|
val with_ :
|
||||||
|
|
||||||
Identical to [Opentelemetry_lwt.Trace.with_], but fetches/stores the trace
|
|
||||||
scope in the [x-ocaml-otel-traceparent] header in the request for
|
|
||||||
convenience.
|
|
||||||
*)
|
|
||||||
val with_:
|
|
||||||
?trace_state:string ->
|
?trace_state:string ->
|
||||||
?service_name:string ->
|
?service_name:string ->
|
||||||
?attrs:Otel.Span.key_value list ->
|
?attrs:Otel.Span.key_value list ->
|
||||||
|
|
@ -40,21 +37,28 @@ module Server : sig
|
||||||
Request.t ->
|
Request.t ->
|
||||||
(Request.t -> 'a Lwt.t) ->
|
(Request.t -> 'a Lwt.t) ->
|
||||||
'a Lwt.t
|
'a Lwt.t
|
||||||
|
(** Trace a new internal span.
|
||||||
|
|
||||||
|
Identical to [Opentelemetry_lwt.Trace.with_], but fetches/stores the trace
|
||||||
|
scope in the [x-ocaml-otel-traceparent] header in the request for
|
||||||
|
convenience.
|
||||||
|
*)
|
||||||
|
|
||||||
|
val get_trace_context :
|
||||||
|
?from:[ `Internal | `External ] -> Request.t -> Otel.Trace.scope option
|
||||||
(** Get the tracing scope from the custom [x-ocaml-otel-traceparent] header
|
(** Get the tracing scope from the custom [x-ocaml-otel-traceparent] header
|
||||||
added by [trace] and [with_].
|
added by [trace] and [with_].
|
||||||
*)
|
*)
|
||||||
val get_trace_context : ?from:[`Internal | `External] -> Request.t -> Otel.Trace.scope option
|
|
||||||
|
|
||||||
|
val set_trace_context : Otel.Trace.scope -> Request.t -> Request.t
|
||||||
(** Set the tracing scope in the custom [x-ocaml-otel-traceparent] header used
|
(** Set the tracing scope in the custom [x-ocaml-otel-traceparent] header used
|
||||||
by [trace] and [with_].
|
by [trace] and [with_].
|
||||||
*)
|
*)
|
||||||
val set_trace_context : Otel.Trace.scope -> Request.t -> Request.t
|
|
||||||
|
|
||||||
|
val remove_trace_context : Request.t -> Request.t
|
||||||
(** Strip the custom [x-ocaml-otel-traceparent] header added by [trace] and
|
(** Strip the custom [x-ocaml-otel-traceparent] header added by [trace] and
|
||||||
[with_].
|
[with_].
|
||||||
*)
|
*)
|
||||||
val remove_trace_context : Request.t -> Request.t
|
|
||||||
end = struct
|
end = struct
|
||||||
let attrs_of_request (req : Request.t) =
|
let attrs_of_request (req : Request.t) =
|
||||||
let meth = req |> Request.meth |> Code.string_of_method in
|
let meth = req |> Request.meth |> Code.string_of_method in
|
||||||
|
|
@ -63,25 +67,24 @@ end = struct
|
||||||
let ua = Header.get (Request.headers req) "user-agent" in
|
let ua = Header.get (Request.headers req) "user-agent" in
|
||||||
let uri = Request.uri req in
|
let uri = Request.uri req in
|
||||||
List.concat
|
List.concat
|
||||||
[ [ ("http.method", `String meth) ]
|
[
|
||||||
; (match host with None -> [] | Some h -> [ ("http.host", `String h) ])
|
[ "http.method", `String meth ];
|
||||||
; [ ("http.url", `String (Uri.to_string uri)) ]
|
(match host with
|
||||||
; ( match ua with
|
| None -> []
|
||||||
| None ->
|
| Some h -> [ "http.host", `String h ]);
|
||||||
[]
|
[ "http.url", `String (Uri.to_string uri) ];
|
||||||
| Some ua ->
|
(match ua with
|
||||||
[ ("http.user_agent", `String ua) ] )
|
| None -> []
|
||||||
; ( match referer with
|
| Some ua -> [ "http.user_agent", `String ua ]);
|
||||||
| None ->
|
(match referer with
|
||||||
[]
|
| None -> []
|
||||||
| Some r ->
|
| Some r -> [ "http.request.header.referer", `String r ]);
|
||||||
[ ("http.request.header.referer", `String r) ] )
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let attrs_of_response (res : Response.t) =
|
let attrs_of_response (res : Response.t) =
|
||||||
let code = Response.status res in
|
let code = Response.status res in
|
||||||
let code = Code.code_of_status code in
|
let code = Code.code_of_status code in
|
||||||
[ ("http.status_code", `Int code) ]
|
[ "http.status_code", `Int code ]
|
||||||
|
|
||||||
let header_x_ocaml_otel_traceparent = "x-ocaml-otel-traceparent"
|
let header_x_ocaml_otel_traceparent = "x-ocaml-otel-traceparent"
|
||||||
|
|
||||||
|
|
@ -89,11 +92,12 @@ end = struct
|
||||||
let module Traceparent = Otel.Trace_context.Traceparent in
|
let module Traceparent = Otel.Trace_context.Traceparent in
|
||||||
let headers =
|
let headers =
|
||||||
Header.add (Request.headers req) header_x_ocaml_otel_traceparent
|
Header.add (Request.headers req) header_x_ocaml_otel_traceparent
|
||||||
(Traceparent.to_value ~trace_id:scope.trace_id ~parent_id:scope.span_id ())
|
(Traceparent.to_value ~trace_id:scope.trace_id ~parent_id:scope.span_id
|
||||||
|
())
|
||||||
in
|
in
|
||||||
{ req with headers }
|
{ req with headers }
|
||||||
|
|
||||||
let get_trace_context ?(from=`Internal) req =
|
let get_trace_context ?(from = `Internal) req =
|
||||||
let module Traceparent = Otel.Trace_context.Traceparent in
|
let module Traceparent = Otel.Trace_context.Traceparent in
|
||||||
let name =
|
let name =
|
||||||
match from with
|
match from with
|
||||||
|
|
@ -103,125 +107,125 @@ end = struct
|
||||||
match Header.get (Request.headers req) name with
|
match Header.get (Request.headers req) name with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some v ->
|
| Some v ->
|
||||||
(match Traceparent.of_value v with
|
(match Traceparent.of_value v with
|
||||||
| Ok (trace_id, parent_id) ->
|
| Ok (trace_id, parent_id) ->
|
||||||
(Some Otel.Trace.{ trace_id; span_id = parent_id; events = []; attrs = []})
|
Some
|
||||||
| Error _ -> None)
|
Otel.Trace.{ trace_id; span_id = parent_id; events = []; attrs = [] }
|
||||||
|
| Error _ -> None)
|
||||||
|
|
||||||
let remove_trace_context req =
|
let remove_trace_context req =
|
||||||
let headers = Header.remove (Request.headers req) header_x_ocaml_otel_traceparent in
|
let headers =
|
||||||
|
Header.remove (Request.headers req) header_x_ocaml_otel_traceparent
|
||||||
|
in
|
||||||
{ req with headers }
|
{ req with headers }
|
||||||
|
|
||||||
let trace ?service_name ?(attrs=[]) callback =
|
let trace ?service_name ?(attrs = []) callback conn req body =
|
||||||
fun conn req body ->
|
|
||||||
let scope = get_trace_context ~from:`External req in
|
let scope = get_trace_context ~from:`External req in
|
||||||
Otel_lwt.Trace.with_
|
Otel_lwt.Trace.with_ ?service_name "request" ~kind:Span_kind_server
|
||||||
?service_name
|
|
||||||
"request"
|
|
||||||
~kind:Span_kind_server
|
|
||||||
?trace_id:(Option.map (fun scope -> scope.Otel.Trace.trace_id) scope)
|
?trace_id:(Option.map (fun scope -> scope.Otel.Trace.trace_id) scope)
|
||||||
?parent:(Option.map (fun scope -> scope.Otel.Trace.span_id) scope)
|
?parent:(Option.map (fun scope -> scope.Otel.Trace.span_id) scope)
|
||||||
~attrs:(attrs @ attrs_of_request req)
|
~attrs:(attrs @ attrs_of_request req)
|
||||||
(fun scope ->
|
(fun scope ->
|
||||||
let open Lwt.Syntax in
|
let open Lwt.Syntax in
|
||||||
let req = set_trace_context scope req in
|
let req = set_trace_context scope req in
|
||||||
let* (res, body) = callback conn req body in
|
let* res, body = callback conn req body in
|
||||||
Otel.Trace.add_attrs scope (fun () -> attrs_of_response res) ;
|
Otel.Trace.add_attrs scope (fun () -> attrs_of_response res);
|
||||||
Lwt.return (res, body) )
|
Lwt.return (res, body))
|
||||||
|
|
||||||
let with_ ?trace_state ?service_name ?attrs ?(kind=Otel.Span.Span_kind_internal) ?links name req (f : Request.t -> 'a Lwt.t) =
|
let with_ ?trace_state ?service_name ?attrs
|
||||||
|
?(kind = Otel.Span.Span_kind_internal) ?links name req
|
||||||
|
(f : Request.t -> 'a Lwt.t) =
|
||||||
let scope = get_trace_context ~from:`Internal req in
|
let scope = get_trace_context ~from:`Internal req in
|
||||||
Otel_lwt.Trace.with_
|
Otel_lwt.Trace.with_ ?trace_state ?service_name ?attrs ~kind
|
||||||
?trace_state
|
|
||||||
?service_name
|
|
||||||
?attrs
|
|
||||||
~kind
|
|
||||||
?trace_id:(Option.map (fun scope -> scope.Otel.Trace.trace_id) scope)
|
?trace_id:(Option.map (fun scope -> scope.Otel.Trace.trace_id) scope)
|
||||||
?parent:(Option.map (fun scope -> scope.Otel.Trace.span_id) scope)
|
?parent:(Option.map (fun scope -> scope.Otel.Trace.span_id) scope)
|
||||||
?links
|
?links name
|
||||||
name
|
|
||||||
(fun scope ->
|
(fun scope ->
|
||||||
let open Lwt.Syntax in
|
let open Lwt.Syntax in
|
||||||
let req = set_trace_context scope req in
|
let req = set_trace_context scope req in
|
||||||
f req)
|
f req)
|
||||||
end
|
end
|
||||||
|
|
||||||
let client ?(scope : Otel.Trace.scope option) (module C : Cohttp_lwt.S.Client) =
|
let client ?(scope : Otel.Trace.scope option) (module C : Cohttp_lwt.S.Client) =
|
||||||
let module Traced = struct
|
let module Traced = struct
|
||||||
open Lwt.Syntax
|
open Lwt.Syntax
|
||||||
|
|
||||||
let attrs_for ~uri ~meth () =
|
let attrs_for ~uri ~meth () =
|
||||||
[ ("http.method", `String (Code.string_of_method `GET))
|
[
|
||||||
; ("http.url", `String (Uri.to_string uri))
|
"http.method", `String (Code.string_of_method `GET);
|
||||||
]
|
"http.url", `String (Uri.to_string uri);
|
||||||
|
]
|
||||||
|
|
||||||
let context_for ~uri ~meth =
|
let context_for ~uri ~meth =
|
||||||
let trace_id = match scope with | Some scope -> Some scope.trace_id | None -> None in
|
let trace_id =
|
||||||
let parent = match scope with | Some scope -> Some scope.span_id | None -> None in
|
match scope with
|
||||||
let attrs = attrs_for ~uri ~meth () in
|
| Some scope -> Some scope.trace_id
|
||||||
(trace_id, parent, attrs)
|
| None -> None
|
||||||
|
in
|
||||||
|
let parent =
|
||||||
|
match scope with
|
||||||
|
| Some scope -> Some scope.span_id
|
||||||
|
| None -> None
|
||||||
|
in
|
||||||
|
let attrs = attrs_for ~uri ~meth () in
|
||||||
|
trace_id, parent, attrs
|
||||||
|
|
||||||
let add_traceparent (scope : Otel.Trace.scope) headers =
|
let add_traceparent (scope : Otel.Trace.scope) headers =
|
||||||
let module Traceparent = Otel.Trace_context.Traceparent in
|
let module Traceparent = Otel.Trace_context.Traceparent in
|
||||||
let headers = match headers with | None -> Header.init () | Some headers -> headers in
|
let headers =
|
||||||
Header.add headers Traceparent.name
|
match headers with
|
||||||
(Traceparent.to_value ~trace_id:scope.trace_id ~parent_id:scope.span_id ())
|
| None -> Header.init ()
|
||||||
|
| Some headers -> headers
|
||||||
|
in
|
||||||
|
Header.add headers Traceparent.name
|
||||||
|
(Traceparent.to_value ~trace_id:scope.trace_id ~parent_id:scope.span_id
|
||||||
|
())
|
||||||
|
|
||||||
type ctx = C.ctx
|
type ctx = C.ctx
|
||||||
|
|
||||||
let call ?ctx ?headers ?body ?chunked meth (uri : Uri.t) : (Response.t * Cohttp_lwt.Body.t) Lwt.t =
|
let call ?ctx ?headers ?body ?chunked meth (uri : Uri.t) :
|
||||||
let (trace_id, parent, attrs) = context_for ~uri ~meth in
|
(Response.t * Cohttp_lwt.Body.t) Lwt.t =
|
||||||
Otel_lwt.Trace.with_ "request"
|
let trace_id, parent, attrs = context_for ~uri ~meth in
|
||||||
~kind:Span_kind_client
|
Otel_lwt.Trace.with_ "request" ~kind:Span_kind_client ?trace_id ?parent
|
||||||
?trace_id
|
~attrs (fun scope ->
|
||||||
?parent
|
let headers = add_traceparent scope headers in
|
||||||
~attrs
|
let* res, body = C.call ?ctx ~headers ?body ?chunked meth uri in
|
||||||
(fun scope ->
|
Otel.Trace.add_attrs scope (fun () ->
|
||||||
let headers = add_traceparent scope headers in
|
let code = Response.status res in
|
||||||
let* (res, body) = C.call ?ctx ~headers ?body ?chunked meth uri in
|
let code = Code.code_of_status code in
|
||||||
Otel.Trace.add_attrs scope (fun () ->
|
[ "http.status_code", `Int code ]);
|
||||||
let code = Response.status res in
|
Lwt.return (res, body))
|
||||||
let code = Code.code_of_status code in
|
|
||||||
[ ("http.status_code", `Int code) ]) ;
|
|
||||||
Lwt.return (res, body))
|
|
||||||
|
|
||||||
let head ?ctx ?headers uri =
|
let head ?ctx ?headers uri =
|
||||||
let open Lwt.Infix in
|
let open Lwt.Infix in
|
||||||
call ?ctx ?headers `HEAD uri >|= fst
|
call ?ctx ?headers `HEAD uri >|= fst
|
||||||
|
|
||||||
let get ?ctx ?headers uri = call ?ctx ?headers `GET uri
|
let get ?ctx ?headers uri = call ?ctx ?headers `GET uri
|
||||||
|
|
||||||
let delete ?ctx ?body ?chunked ?headers uri =
|
let delete ?ctx ?body ?chunked ?headers uri =
|
||||||
call ?ctx ?headers ?body ?chunked `DELETE uri
|
call ?ctx ?headers ?body ?chunked `DELETE uri
|
||||||
|
|
||||||
let post ?ctx ?body ?chunked ?headers uri =
|
let post ?ctx ?body ?chunked ?headers uri =
|
||||||
call ?ctx ?headers ?body ?chunked `POST uri
|
call ?ctx ?headers ?body ?chunked `POST uri
|
||||||
|
|
||||||
let put ?ctx ?body ?chunked ?headers uri =
|
let put ?ctx ?body ?chunked ?headers uri =
|
||||||
call ?ctx ?headers ?body ?chunked `PUT uri
|
call ?ctx ?headers ?body ?chunked `PUT uri
|
||||||
|
|
||||||
let patch ?ctx ?body ?chunked ?headers uri =
|
let patch ?ctx ?body ?chunked ?headers uri =
|
||||||
call ?ctx ?headers ?body ?chunked `PATCH uri
|
call ?ctx ?headers ?body ?chunked `PATCH uri
|
||||||
|
|
||||||
let post_form ?ctx ?headers ~params uri =
|
let post_form ?ctx ?headers ~params uri =
|
||||||
let (trace_id, parent, attrs) = context_for ~uri ~meth:`POST in
|
let trace_id, parent, attrs = context_for ~uri ~meth:`POST in
|
||||||
Otel_lwt.Trace.with_ "request"
|
Otel_lwt.Trace.with_ "request" ~kind:Span_kind_client ?trace_id ?parent
|
||||||
~kind:Span_kind_client
|
~attrs (fun scope ->
|
||||||
?trace_id
|
let headers = add_traceparent scope headers in
|
||||||
?parent
|
let* res, body = C.post_form ?ctx ~headers ~params uri in
|
||||||
~attrs
|
Otel.Trace.add_attrs scope (fun () ->
|
||||||
(fun scope ->
|
let code = Response.status res in
|
||||||
let headers = add_traceparent scope headers in
|
let code = Code.code_of_status code in
|
||||||
let* (res, body) =
|
[ "http.status_code", `Int code ]);
|
||||||
C.post_form ?ctx ~headers ~params uri
|
Lwt.return (res, body))
|
||||||
in
|
|
||||||
Otel.Trace.add_attrs scope (fun () ->
|
|
||||||
let code = Response.status res in
|
|
||||||
let code = Code.code_of_status code in
|
|
||||||
[ ("http.status_code", `Int code) ]) ;
|
|
||||||
Lwt.return (res, body))
|
|
||||||
|
|
||||||
let callv = C.callv (* TODO *)
|
let callv = C.callv (* TODO *)
|
||||||
end
|
end in
|
||||||
in
|
|
||||||
(module Traced : Cohttp_lwt.S.Client)
|
(module Traced : Cohttp_lwt.S.Client)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
(library
|
(library
|
||||||
(name opentelemetry_lwt)
|
(name opentelemetry_lwt)
|
||||||
(public_name opentelemetry-lwt)
|
(public_name opentelemetry-lwt)
|
||||||
(synopsis "Lwt frontend for opentelemetry")
|
(synopsis "Lwt frontend for opentelemetry")
|
||||||
(libraries lwt opentelemetry))
|
(libraries lwt opentelemetry))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
open Opentelemetry
|
open Opentelemetry
|
||||||
open Lwt.Syntax
|
open Lwt.Syntax
|
||||||
|
|
||||||
module Span_id = Span_id
|
module Span_id = Span_id
|
||||||
module Trace_id = Trace_id
|
module Trace_id = Trace_id
|
||||||
module Event = Event
|
module Event = Event
|
||||||
|
|
@ -15,10 +14,8 @@ module Trace = struct
|
||||||
include Trace
|
include Trace
|
||||||
|
|
||||||
(** Sync span guard *)
|
(** Sync span guard *)
|
||||||
let with_
|
let with_ ?trace_state ?service_name ?(attrs = []) ?kind ?trace_id ?parent
|
||||||
?trace_state ?service_name ?(attrs=[])
|
?scope ?links name (f : Trace.scope -> 'a Lwt.t) : 'a Lwt.t =
|
||||||
?kind ?trace_id ?parent ?scope ?links
|
|
||||||
name (f:Trace.scope -> 'a Lwt.t) : 'a Lwt.t =
|
|
||||||
let trace_id =
|
let trace_id =
|
||||||
match trace_id, scope with
|
match trace_id, scope with
|
||||||
| Some trace_id, _ -> trace_id
|
| Some trace_id, _ -> trace_id
|
||||||
|
|
@ -31,30 +28,31 @@ module Trace = struct
|
||||||
| None, Some scope -> Some scope.span_id
|
| None, Some scope -> Some scope.span_id
|
||||||
| None, None -> None
|
| None, None -> None
|
||||||
in
|
in
|
||||||
let start_time = Timestamp_ns.now_unix_ns() in
|
let start_time = Timestamp_ns.now_unix_ns () in
|
||||||
let span_id = Span_id.create() in
|
let span_id = Span_id.create () in
|
||||||
let scope = {trace_id;span_id;events=[];attrs} in
|
let scope = { trace_id; span_id; events = []; attrs } in
|
||||||
let finally ok =
|
let finally ok =
|
||||||
let status = match ok with
|
let status =
|
||||||
|
match ok with
|
||||||
| Ok () -> default_status ~code:Status_code_ok ()
|
| Ok () -> default_status ~code:Status_code_ok ()
|
||||||
| Error e -> default_status ~code:Status_code_error ~message:e () in
|
| Error e -> default_status ~code:Status_code_error ~message:e ()
|
||||||
|
in
|
||||||
let span, _ =
|
let span, _ =
|
||||||
Span.create
|
Span.create ?kind ~trace_id ?parent ?links ~id:span_id ?trace_state
|
||||||
?kind ~trace_id ?parent ?links ~id:span_id
|
~attrs:scope.attrs ~events:scope.events ~start_time
|
||||||
?trace_state ~attrs:scope.attrs ~events:scope.events
|
~end_time:(Timestamp_ns.now_unix_ns ())
|
||||||
~start_time ~end_time:(Timestamp_ns.now_unix_ns())
|
~status name
|
||||||
~status
|
in
|
||||||
name in
|
emit ?service_name [ span ]
|
||||||
emit ?service_name [span]
|
|
||||||
in
|
in
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let* x = f scope in
|
let* x = f scope in
|
||||||
let () = finally (Ok ()) in
|
let () = finally (Ok ()) in
|
||||||
Lwt.return x)
|
Lwt.return x)
|
||||||
(fun e ->
|
(fun e ->
|
||||||
let () = finally (Error (Printexc.to_string e)) in
|
let () = finally (Error (Printexc.to_string e)) in
|
||||||
Lwt.fail e)
|
Lwt.fail e)
|
||||||
end
|
end
|
||||||
|
|
||||||
module Metrics = struct
|
module Metrics = struct
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,29 @@
|
||||||
module T = Opentelemetry
|
module T = Opentelemetry
|
||||||
module Otel_lwt = Opentelemetry_lwt
|
module Otel_lwt = Opentelemetry_lwt
|
||||||
|
|
||||||
let spf = Printf.sprintf
|
let spf = Printf.sprintf
|
||||||
let (let@) f x = f x
|
|
||||||
|
let ( let@ ) f x = f x
|
||||||
|
|
||||||
let sleep_inner = ref 0.1
|
let sleep_inner = ref 0.1
|
||||||
|
|
||||||
let sleep_outer = ref 2.0
|
let sleep_outer = ref 2.0
|
||||||
|
|
||||||
let mk_client ~scope = Opentelemetry_cohttp_lwt.client ~scope (module Cohttp_lwt_unix.Client)
|
let mk_client ~scope =
|
||||||
|
Opentelemetry_cohttp_lwt.client ~scope (module Cohttp_lwt_unix.Client)
|
||||||
|
|
||||||
let run () =
|
let run () =
|
||||||
Printf.printf "collector is on %S\n%!" (Opentelemetry_client_ocurl.get_url());
|
Printf.printf "collector is on %S\n%!" (Opentelemetry_client_ocurl.get_url ());
|
||||||
let open Lwt.Syntax in
|
let open Lwt.Syntax in
|
||||||
let rec go () =
|
let rec go () =
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Otel_lwt.Trace.with_
|
Otel_lwt.Trace.with_ ~kind:T.Span.Span_kind_producer "loop.outer"
|
||||||
~kind:T.Span.Span_kind_producer
|
|
||||||
"loop.outer"
|
|
||||||
in
|
in
|
||||||
let* () = Lwt_unix.sleep !sleep_outer in
|
let* () = Lwt_unix.sleep !sleep_outer in
|
||||||
let module C = (val mk_client ~scope) in
|
let module C = (val mk_client ~scope) in
|
||||||
let* (res, body) = C.get (Uri.of_string "https://enec1hql02hz.x.pipedream.net") in
|
let* res, body =
|
||||||
|
C.get (Uri.of_string "https://enec1hql02hz.x.pipedream.net")
|
||||||
|
in
|
||||||
let* () = Cohttp_lwt.Body.drain_body body in
|
let* () = Cohttp_lwt.Body.drain_body body in
|
||||||
go ()
|
go ()
|
||||||
in
|
in
|
||||||
|
|
@ -34,26 +38,40 @@ let () =
|
||||||
let thread = ref true in
|
let thread = ref true in
|
||||||
let batch_traces = ref 400 in
|
let batch_traces = ref 400 in
|
||||||
let batch_metrics = ref 3 in
|
let batch_metrics = ref 3 in
|
||||||
let opts = [
|
let opts =
|
||||||
"--debug", Arg.Bool ((:=) debug), " enable debug output";
|
[
|
||||||
"--thread", Arg.Bool ((:=) thread), " use a background thread";
|
"--debug", Arg.Bool (( := ) debug), " enable debug output";
|
||||||
"--batch-traces", Arg.Int ((:=) batch_traces), " size of traces batch";
|
"--thread", Arg.Bool (( := ) thread), " use a background thread";
|
||||||
"--batch-metrics", Arg.Int ((:=) batch_metrics), " size of metrics batch";
|
"--batch-traces", Arg.Int (( := ) batch_traces), " size of traces batch";
|
||||||
|
( "--batch-metrics",
|
||||||
|
Arg.Int (( := ) batch_metrics),
|
||||||
|
" size of metrics batch" );
|
||||||
"--sleep-inner", Arg.Set_float sleep_inner, " sleep (in s) in inner loop";
|
"--sleep-inner", Arg.Set_float sleep_inner, " sleep (in s) in inner loop";
|
||||||
"--sleep-outer", Arg.Set_float sleep_outer, " sleep (in s) in outer loop";
|
"--sleep-outer", Arg.Set_float sleep_outer, " sleep (in s) in outer loop";
|
||||||
] |> Arg.align in
|
]
|
||||||
|
|> Arg.align
|
||||||
|
in
|
||||||
|
|
||||||
Arg.parse opts (fun _ -> ()) "emit1 [opt]*";
|
Arg.parse opts (fun _ -> ()) "emit1 [opt]*";
|
||||||
|
|
||||||
let some_if_nzero r = if !r > 0 then Some !r else None in
|
let some_if_nzero r =
|
||||||
let config = Opentelemetry_client_ocurl.Config.make
|
if !r > 0 then
|
||||||
~debug:!debug
|
Some !r
|
||||||
~batch_traces:(some_if_nzero batch_traces)
|
else
|
||||||
~batch_metrics:(some_if_nzero batch_metrics)
|
None
|
||||||
~thread:!thread () in
|
in
|
||||||
|
let config =
|
||||||
|
Opentelemetry_client_ocurl.Config.make ~debug:!debug
|
||||||
|
~batch_traces:(some_if_nzero batch_traces)
|
||||||
|
~batch_metrics:(some_if_nzero batch_metrics)
|
||||||
|
~thread:!thread ()
|
||||||
|
in
|
||||||
Format.printf "@[<2>sleep outer: %.3fs,@ sleep inner: %.3fs,@ config: %a@]@."
|
Format.printf "@[<2>sleep outer: %.3fs,@ sleep inner: %.3fs,@ config: %a@]@."
|
||||||
!sleep_outer !sleep_inner Opentelemetry_client_ocurl.Config.pp config;
|
!sleep_outer !sleep_inner Opentelemetry_client_ocurl.Config.pp config;
|
||||||
|
|
||||||
Format.printf "Check HTTP requests at https://requestbin.com/r/enec1hql02hz/26qShWryt5vJc1JfrOwalhr5vQt@.";
|
Format.printf
|
||||||
|
"Check HTTP requests at \
|
||||||
|
https://requestbin.com/r/enec1hql02hz/26qShWryt5vJc1JfrOwalhr5vQt@.";
|
||||||
|
|
||||||
Opentelemetry_client_ocurl.with_setup ~config () (fun () -> Lwt_main.run (run ()))
|
Opentelemetry_client_ocurl.with_setup ~config () (fun () ->
|
||||||
|
Lwt_main.run (run ()))
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@
|
||||||
(executable
|
(executable
|
||||||
(name cohttp_client)
|
(name cohttp_client)
|
||||||
(modules cohttp_client)
|
(modules cohttp_client)
|
||||||
(libraries cohttp-lwt-unix opentelemetry opentelemetry-client-ocurl opentelemetry-cohttp-lwt))
|
(libraries cohttp-lwt-unix opentelemetry opentelemetry-client-ocurl
|
||||||
|
opentelemetry-cohttp-lwt))
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,43 @@
|
||||||
|
|
||||||
module T = Opentelemetry
|
module T = Opentelemetry
|
||||||
|
|
||||||
let spf = Printf.sprintf
|
let spf = Printf.sprintf
|
||||||
let (let@) f x = f x
|
|
||||||
|
let ( let@ ) f x = f x
|
||||||
|
|
||||||
let sleep_inner = ref 0.1
|
let sleep_inner = ref 0.1
|
||||||
|
|
||||||
let sleep_outer = ref 2.0
|
let sleep_outer = ref 2.0
|
||||||
|
|
||||||
let num_sleep = ref 0
|
let num_sleep = ref 0
|
||||||
|
|
||||||
let run () =
|
let run () =
|
||||||
Printf.printf "collector is on %S\n%!" (Opentelemetry_client_ocurl.get_url());
|
Printf.printf "collector is on %S\n%!" (Opentelemetry_client_ocurl.get_url ());
|
||||||
T.GC_metrics.basic_setup();
|
T.GC_metrics.basic_setup ();
|
||||||
|
|
||||||
T.Metrics_callbacks.register (fun () ->
|
T.Metrics_callbacks.register (fun () ->
|
||||||
T.Metrics.[ sum ~name:"num-sleep" ~is_monotonic:true [int !num_sleep] ]);
|
T.Metrics.[ sum ~name:"num-sleep" ~is_monotonic:true [ int !num_sleep ] ]);
|
||||||
|
|
||||||
let i = ref 0 in
|
let i = ref 0 in
|
||||||
while true do
|
while true do
|
||||||
let@ scope =
|
let@ scope =
|
||||||
T.Trace.with_
|
T.Trace.with_ ~kind:T.Span.Span_kind_producer "loop.outer"
|
||||||
~kind:T.Span.Span_kind_producer
|
~attrs:[ "i", `Int !i ]
|
||||||
"loop.outer" ~attrs:["i", `Int !i] in
|
in
|
||||||
|
|
||||||
for j=0 to 4 do
|
for j = 0 to 4 do
|
||||||
|
let@ scope =
|
||||||
let@ scope = T.Trace.with_ ~kind:T.Span.Span_kind_internal ~scope
|
T.Trace.with_ ~kind:T.Span.Span_kind_internal ~scope
|
||||||
~attrs:["j", `Int j]
|
~attrs:[ "j", `Int j ]
|
||||||
"loop.inner" in
|
"loop.inner"
|
||||||
|
in
|
||||||
|
|
||||||
Unix.sleepf !sleep_outer;
|
Unix.sleepf !sleep_outer;
|
||||||
incr num_sleep;
|
incr num_sleep;
|
||||||
|
|
||||||
incr i;
|
incr i;
|
||||||
|
|
||||||
(try
|
try
|
||||||
let@ _ =
|
let@ _ = T.Trace.with_ ~kind:T.Span.Span_kind_internal ~scope "alloc" in
|
||||||
T.Trace.with_ ~kind:T.Span.Span_kind_internal ~scope
|
|
||||||
"alloc" in
|
|
||||||
(* allocate some stuff *)
|
(* allocate some stuff *)
|
||||||
let _arr = Sys.opaque_identity @@ Array.make (25 * 25551) 42.0 in
|
let _arr = Sys.opaque_identity @@ Array.make (25 * 25551) 42.0 in
|
||||||
ignore _arr;
|
ignore _arr;
|
||||||
|
|
@ -43,12 +45,12 @@ let run () =
|
||||||
Unix.sleepf !sleep_inner;
|
Unix.sleepf !sleep_inner;
|
||||||
incr num_sleep;
|
incr num_sleep;
|
||||||
|
|
||||||
if j=4 && !i mod 13 = 0 then failwith "oh no"; (* simulate a failure *)
|
if j = 4 && !i mod 13 = 0 then failwith "oh no";
|
||||||
|
|
||||||
T.Trace.add_event scope (fun()->T.Event.make "done with alloc");
|
(* simulate a failure *)
|
||||||
with Failure _ ->
|
T.Trace.add_event scope (fun () -> T.Event.make "done with alloc")
|
||||||
());
|
with Failure _ -> ()
|
||||||
done;
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
|
|
@ -60,23 +62,34 @@ let () =
|
||||||
let thread = ref true in
|
let thread = ref true in
|
||||||
let batch_traces = ref 400 in
|
let batch_traces = ref 400 in
|
||||||
let batch_metrics = ref 3 in
|
let batch_metrics = ref 3 in
|
||||||
let opts = [
|
let opts =
|
||||||
"--debug", Arg.Bool ((:=) debug), " enable debug output";
|
[
|
||||||
"--thread", Arg.Bool ((:=) thread), " use a background thread";
|
"--debug", Arg.Bool (( := ) debug), " enable debug output";
|
||||||
"--batch-traces", Arg.Int ((:=) batch_traces), " size of traces batch";
|
"--thread", Arg.Bool (( := ) thread), " use a background thread";
|
||||||
"--batch-metrics", Arg.Int ((:=) batch_metrics), " size of metrics batch";
|
"--batch-traces", Arg.Int (( := ) batch_traces), " size of traces batch";
|
||||||
"--sleep-inner", Arg.Set_float sleep_inner, " sleep (in s) in inner loop";
|
( "--batch-metrics",
|
||||||
"--sleep-outer", Arg.Set_float sleep_outer, " sleep (in s) in outer loop";
|
Arg.Int (( := ) batch_metrics),
|
||||||
] |> Arg.align in
|
" size of metrics batch" );
|
||||||
|
"--sleep-inner", Arg.Set_float sleep_inner, " sleep (in s) in inner loop";
|
||||||
|
"--sleep-outer", Arg.Set_float sleep_outer, " sleep (in s) in outer loop";
|
||||||
|
]
|
||||||
|
|> Arg.align
|
||||||
|
in
|
||||||
|
|
||||||
Arg.parse opts (fun _ -> ()) "emit1 [opt]*";
|
Arg.parse opts (fun _ -> ()) "emit1 [opt]*";
|
||||||
|
|
||||||
let some_if_nzero r = if !r > 0 then Some !r else None in
|
let some_if_nzero r =
|
||||||
let config = Opentelemetry_client_ocurl.Config.make
|
if !r > 0 then
|
||||||
~debug:!debug
|
Some !r
|
||||||
|
else
|
||||||
|
None
|
||||||
|
in
|
||||||
|
let config =
|
||||||
|
Opentelemetry_client_ocurl.Config.make ~debug:!debug
|
||||||
~batch_traces:(some_if_nzero batch_traces)
|
~batch_traces:(some_if_nzero batch_traces)
|
||||||
~batch_metrics:(some_if_nzero batch_metrics)
|
~batch_metrics:(some_if_nzero batch_metrics)
|
||||||
~thread:!thread () in
|
~thread:!thread ()
|
||||||
|
in
|
||||||
Format.printf "@[<2>sleep outer: %.3fs,@ sleep inner: %.3fs,@ config: %a@]@."
|
Format.printf "@[<2>sleep outer: %.3fs,@ sleep inner: %.3fs,@ config: %a@]@."
|
||||||
!sleep_outer !sleep_inner Opentelemetry_client_ocurl.Config.pp config;
|
!sleep_outer !sleep_inner Opentelemetry_client_ocurl.Config.pp config;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,49 @@ open Opentelemetry
|
||||||
|
|
||||||
let pp_traceparent fmt (trace_id, parent_id) =
|
let pp_traceparent fmt (trace_id, parent_id) =
|
||||||
let open Format in
|
let open Format in
|
||||||
fprintf fmt "trace_id:%S parent_id:%S"
|
fprintf fmt "trace_id:%S parent_id:%S" (Trace_id.to_hex trace_id)
|
||||||
(Trace_id.to_hex trace_id)
|
|
||||||
(Span_id.to_hex parent_id)
|
(Span_id.to_hex parent_id)
|
||||||
|
|
||||||
|
|
||||||
let test_of_value str =
|
let test_of_value str =
|
||||||
let open Format in
|
let open Format in
|
||||||
printf "@[<v 2>Trace_context.Traceparent.of_value %S:@ %a@]@."
|
printf "@[<v 2>Trace_context.Traceparent.of_value %S:@ %a@]@." str
|
||||||
str
|
(pp_print_result
|
||||||
(pp_print_result ~ok:(fun fmt (trace_id, parent_id) ->
|
~ok:(fun fmt (trace_id, parent_id) ->
|
||||||
fprintf fmt "Ok %a" pp_traceparent (trace_id, parent_id))
|
fprintf fmt "Ok %a" pp_traceparent (trace_id, parent_id))
|
||||||
~error:(fun fmt msg -> fprintf fmt "Error %S" msg))
|
~error:(fun fmt msg -> fprintf fmt "Error %S" msg))
|
||||||
(Trace_context.Traceparent.of_value str)
|
(Trace_context.Traceparent.of_value str)
|
||||||
|
|
||||||
let () = test_of_value "xx"
|
let () = test_of_value "xx"
|
||||||
|
|
||||||
let () = test_of_value "00"
|
let () = test_of_value "00"
|
||||||
|
|
||||||
let () = test_of_value "00-xxxx"
|
let () = test_of_value "00-xxxx"
|
||||||
|
|
||||||
let () = test_of_value "00-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
let () = test_of_value "00-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef-xxxx"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef-xxxx"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef-xxxxxxxxxxxxxxxx"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef-xxxxxxxxxxxxxxxx"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef-"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef-"
|
||||||
|
|
||||||
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef-00"
|
let () = test_of_value "00-0123456789abcdef0123456789abcdef-0123456789abcdef-00"
|
||||||
|
|
||||||
let () = test_of_value "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
let () = test_of_value "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
||||||
|
|
||||||
let () = print_endline ""
|
let () = print_endline ""
|
||||||
|
|
||||||
let test_to_value trace_id parent_id =
|
let test_to_value trace_id parent_id =
|
||||||
let open Format in
|
let open Format in
|
||||||
printf "@[<v 2>Trace_context.Traceparent.to_value %a:@ %S@]@."
|
printf "@[<v 2>Trace_context.Traceparent.to_value %a:@ %S@]@." pp_traceparent
|
||||||
pp_traceparent (trace_id, parent_id)
|
(trace_id, parent_id)
|
||||||
(Trace_context.Traceparent.to_value ~trace_id ~parent_id ())
|
(Trace_context.Traceparent.to_value ~trace_id ~parent_id ())
|
||||||
|
|
||||||
|
let () =
|
||||||
let () = test_to_value (Trace_id.of_hex "4bf92f3577b34da6a3ce929d0e0e4736") (Span_id.of_hex "00f067aa0ba902b7")
|
test_to_value
|
||||||
|
(Trace_id.of_hex "4bf92f3577b34da6a3ce929d0e0e4736")
|
||||||
|
(Span_id.of_hex "00f067aa0ba902b7")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue