mirror of
https://github.com/ocaml-tracing/ocaml-opentelemetry.git
synced 2026-03-08 03:47:59 -04:00
tracer/logger/metrics_emitter now pair emitter and clock
- clock is needed because timestamps need to be provided now - explicit types are good anyway - have at least one helper to emit the signal with optional tracer/logger/metrics_emitter - easier logger with `log` and `logf`
This commit is contained in:
parent
ec584b4829
commit
e2c4a4e680
16 changed files with 145 additions and 124 deletions
|
|
@ -2,7 +2,7 @@ open Common_
|
||||||
|
|
||||||
let enabled = Atomic.make false
|
let enabled = Atomic.make false
|
||||||
|
|
||||||
let tracer = Atomic.make OTEL.Tracer.dynamic_forward_to_main_exporter
|
let tracer = Atomic.make OTEL.Tracer.dynamic_main
|
||||||
|
|
||||||
let[@inline] add_event (scope : OTEL.Span.t) ev = OTEL.Span.add_event scope ev
|
let[@inline] add_event (scope : OTEL.Span.t) ev = OTEL.Span.add_event scope ev
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ let dummy_span_id = OTEL.Span_id.dummy
|
||||||
let with_ ?kind ?attrs name f =
|
let with_ ?kind ?attrs name f =
|
||||||
if Atomic.get enabled then (
|
if Atomic.get enabled then (
|
||||||
let tracer = Atomic.get tracer in
|
let tracer = Atomic.get tracer in
|
||||||
OTEL.Tracer.with_ tracer ?kind ?attrs name f
|
OTEL.Tracer.with_ ~tracer ?kind ?attrs name f
|
||||||
) else (
|
) else (
|
||||||
(* A new scope is needed here because it might be modified *)
|
(* A new scope is needed here because it might be modified *)
|
||||||
let span : OTEL.Span.t =
|
let span : OTEL.Span.t =
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,15 @@ type t = Metrics.metric
|
||||||
let pp = Proto.Metrics.pp_metric
|
let pp = Proto.Metrics.pp_metric
|
||||||
|
|
||||||
(** Number data point, as a float *)
|
(** Number data point, as a float *)
|
||||||
let float ?start_time_unix_nano ?(now = Clock.now_main ()) ?(attrs = [])
|
let float ?start_time_unix_nano ?(attrs = []) ~(now : Timestamp_ns.t)
|
||||||
(d : float) : number_data_point =
|
(d : float) : number_data_point =
|
||||||
let attributes = attrs |> List.map Key_value.conv in
|
let attributes = attrs |> List.map Key_value.conv in
|
||||||
make_number_data_point ?start_time_unix_nano ~time_unix_nano:now ~attributes
|
make_number_data_point ?start_time_unix_nano ~time_unix_nano:now ~attributes
|
||||||
~value:(As_double d) ()
|
~value:(As_double d) ()
|
||||||
|
|
||||||
(** Number data point, as an int *)
|
(** Number data point, as an int *)
|
||||||
let int ?start_time_unix_nano ?(now = Clock.now_main ()) ?(attrs = []) (i : int)
|
let int ?start_time_unix_nano ?(attrs = []) ~(now : Timestamp_ns.t) (i : int) :
|
||||||
: number_data_point =
|
number_data_point =
|
||||||
let attributes = attrs |> List.map Key_value.conv in
|
let attributes = attrs |> List.map Key_value.conv in
|
||||||
make_number_data_point ?start_time_unix_nano ~time_unix_nano:now ~attributes
|
make_number_data_point ?start_time_unix_nano ~time_unix_nano:now ~attributes
|
||||||
~value:(As_int (Int64.of_int i))
|
~value:(As_int (Int64.of_int i))
|
||||||
|
|
@ -52,13 +52,14 @@ let sum ~name ?description ?unit_
|
||||||
(** Histogram data
|
(** Histogram data
|
||||||
@param count number of values in population (non negative)
|
@param count number of values in population (non negative)
|
||||||
@param sum sum of values in population (0 if count is 0)
|
@param sum sum of values in population (0 if count is 0)
|
||||||
|
@param now the timestamp for this data point
|
||||||
@param bucket_counts
|
@param bucket_counts
|
||||||
count value of histogram for each bucket. Sum of the counts must be equal
|
count value of histogram for each bucket. Sum of the counts must be equal
|
||||||
to [count]. length must be [1+length explicit_bounds]
|
to [count]. length must be [1+length explicit_bounds]
|
||||||
@param explicit_bounds strictly increasing list of bounds for the buckets *)
|
@param explicit_bounds strictly increasing list of bounds for the buckets *)
|
||||||
let histogram_data_point ?start_time_unix_nano ?(now = Clock.now_main ())
|
let histogram_data_point ?start_time_unix_nano ?(attrs = []) ?(exemplars = [])
|
||||||
?(attrs = []) ?(exemplars = []) ?(explicit_bounds = []) ?sum ~bucket_counts
|
?(explicit_bounds = []) ?sum ~(now : Timestamp_ns.t) ~bucket_counts ~count
|
||||||
~count () : histogram_data_point =
|
() : histogram_data_point =
|
||||||
let attributes = attrs |> List.map Key_value.conv in
|
let attributes = attrs |> List.map Key_value.conv in
|
||||||
make_histogram_data_point ?start_time_unix_nano ~time_unix_nano:now
|
make_histogram_data_point ?start_time_unix_nano ~time_unix_nano:now
|
||||||
~attributes ~exemplars ~bucket_counts ~explicit_bounds ~count ?sum ()
|
~attributes ~exemplars ~bucket_counts ~explicit_bounds ~count ?sum ()
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,10 @@ end = struct
|
||||||
in
|
in
|
||||||
{ req with headers }
|
{ req with headers }
|
||||||
|
|
||||||
let trace ?(tracer = Otel.Tracer.get_main ()) ?(attrs = []) callback conn req
|
let trace ?(tracer = Otel.Tracer.dynamic_main) ?(attrs = []) callback conn req
|
||||||
body =
|
body =
|
||||||
let parent = get_trace_context ~from:`External req in
|
let parent = get_trace_context ~from:`External req in
|
||||||
Otel_lwt.Tracer.with_ tracer "request" ~kind:Span_kind_server
|
Otel_lwt.Tracer.with_ ~tracer "request" ~kind:Span_kind_server
|
||||||
?trace_id:(Option.map Otel.Span.trace_id parent)
|
?trace_id:(Option.map Otel.Span.trace_id parent)
|
||||||
?parent
|
?parent
|
||||||
~attrs:(attrs @ attrs_of_request req)
|
~attrs:(attrs @ attrs_of_request req)
|
||||||
|
|
@ -131,18 +131,18 @@ end = struct
|
||||||
Otel.Span.add_attrs span (attrs_of_response res);
|
Otel.Span.add_attrs span (attrs_of_response res);
|
||||||
Lwt.return (res, body))
|
Lwt.return (res, body))
|
||||||
|
|
||||||
let with_ ?(tracer = Otel.Tracer.get_main ()) ?trace_state ?attrs
|
let with_ ?(tracer = Otel.Tracer.dynamic_main) ?trace_state ?attrs
|
||||||
?(kind = Otel.Span.Span_kind_internal) ?links name req
|
?(kind = Otel.Span.Span_kind_internal) ?links name req
|
||||||
(f : Request.t -> 'a Lwt.t) =
|
(f : Request.t -> 'a Lwt.t) =
|
||||||
let span = get_trace_context ~from:`Internal req in
|
let span = get_trace_context ~from:`Internal req in
|
||||||
Otel_lwt.Tracer.with_ tracer ?trace_state ?attrs ~kind
|
Otel_lwt.Tracer.with_ ~tracer ?trace_state ?attrs ~kind
|
||||||
?trace_id:(Option.map Otel.Span.trace_id span) ?parent:span ?links name
|
?trace_id:(Option.map Otel.Span.trace_id span) ?parent:span ?links name
|
||||||
(fun span ->
|
(fun span ->
|
||||||
let req = set_trace_context span req in
|
let req = set_trace_context span req in
|
||||||
f req)
|
f req)
|
||||||
end
|
end
|
||||||
|
|
||||||
let client ?(tracer = Otel.Tracer.get_main ()) ?(span : Otel.Span.t option)
|
let client ?(tracer = Otel.Tracer.dynamic_main) ?(span : Otel.Span.t option)
|
||||||
(module C : Cohttp_lwt.S.Client) =
|
(module C : Cohttp_lwt.S.Client) =
|
||||||
let module Traced = struct
|
let module Traced = struct
|
||||||
open Lwt.Syntax
|
open Lwt.Syntax
|
||||||
|
|
@ -190,7 +190,7 @@ let client ?(tracer = Otel.Tracer.get_main ()) ?(span : Otel.Span.t option)
|
||||||
let call ?ctx ?headers ?body ?chunked meth (uri : Uri.t) :
|
let call ?ctx ?headers ?body ?chunked meth (uri : Uri.t) :
|
||||||
(Response.t * Cohttp_lwt.Body.t) Lwt.t =
|
(Response.t * Cohttp_lwt.Body.t) Lwt.t =
|
||||||
let trace_id, parent, attrs = context_for ~uri ~meth in
|
let trace_id, parent, attrs = context_for ~uri ~meth in
|
||||||
Otel_lwt.Tracer.with_ tracer "request" ~kind:Span_kind_client ?trace_id
|
Otel_lwt.Tracer.with_ ~tracer "request" ~kind:Span_kind_client ?trace_id
|
||||||
?parent ~attrs (fun span ->
|
?parent ~attrs (fun span ->
|
||||||
let headers = add_traceparent span headers in
|
let headers = add_traceparent span headers in
|
||||||
let* res, body = C.call ?ctx ~headers ?body ?chunked meth uri in
|
let* res, body = C.call ?ctx ~headers ?body ?chunked meth uri in
|
||||||
|
|
@ -217,7 +217,7 @@ let client ?(tracer = Otel.Tracer.get_main ()) ?(span : Otel.Span.t option)
|
||||||
|
|
||||||
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.Tracer.with_ tracer "request" ~kind:Span_kind_client ?trace_id
|
Otel_lwt.Tracer.with_ ~tracer "request" ~kind:Span_kind_client ?trace_id
|
||||||
?parent ~attrs (fun span ->
|
?parent ~attrs (fun span ->
|
||||||
let headers = add_traceparent span headers in
|
let headers = add_traceparent span headers in
|
||||||
let* res, body = C.post_form ?ctx ~headers ~params uri in
|
let* res, body = C.post_form ?ctx ~headers ~params uri in
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
module Otel = Opentelemetry
|
module OTEL = Opentelemetry
|
||||||
|
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
(* Prelude *)
|
(* Prelude *)
|
||||||
|
|
@ -10,8 +10,8 @@ module Otel = Opentelemetry
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
(* Levels *)
|
(* Levels *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
(* Convert log level to Otel severity *)
|
(* Convert log level to OTEL severity *)
|
||||||
let log_level_to_severity (level : Logs.level) : Otel.Log_record.severity =
|
let log_level_to_severity (level : Logs.level) : OTEL.Log_record.severity =
|
||||||
match level with
|
match level with
|
||||||
| Logs.App -> Severity_number_info (* like info, but less severe *)
|
| Logs.App -> Severity_number_info (* like info, but less severe *)
|
||||||
| Logs.Info -> Severity_number_info2
|
| Logs.Info -> Severity_number_info2
|
||||||
|
|
@ -34,18 +34,20 @@ let emit_telemetry do_emit = Logs.Tag.(empty |> add emit_telemetry_tag do_emit)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
(* Log a message to otel with some attrs *)
|
(* Log a message to otel with some attrs *)
|
||||||
let log ?(logger = Otel.Logger.get_main ()) ?attrs
|
let log ?(logger = OTEL.Logger.dynamic_main) ?attrs
|
||||||
?(scope = Otel.Ambient_span.get ()) ~level msg =
|
?(scope = OTEL.Ambient_span.get ()) ~level msg =
|
||||||
let log_level = Logs.level_to_string (Some level) in
|
let log_level = Logs.level_to_string (Some level) in
|
||||||
let span_id = Option.map Otel.Span.id scope in
|
let span_id = Option.map OTEL.Span.id scope in
|
||||||
let trace_id = Option.map Otel.Span.trace_id scope in
|
let trace_id = Option.map OTEL.Span.trace_id scope in
|
||||||
let severity = log_level_to_severity level in
|
let severity = log_level_to_severity level in
|
||||||
let log =
|
let log =
|
||||||
Otel.Log_record.make_str ~severity ~log_level ?attrs ?trace_id ?span_id msg
|
let observed_time_unix_nano = OTEL.Clock.now logger.clock in
|
||||||
|
OTEL.Log_record.make_str ~observed_time_unix_nano ~severity ~log_level
|
||||||
|
?attrs ?trace_id ?span_id msg
|
||||||
in
|
in
|
||||||
|
|
||||||
(* Noop if no backend is set *)
|
(* Noop if no backend is set *)
|
||||||
(* TODO: be more explicit *)
|
OTEL.Logger.emit1 logger log
|
||||||
Otel.Emitter.emit logger [ log ]
|
|
||||||
|
|
||||||
let otel_reporter ?(attributes = []) () : Logs.reporter =
|
let otel_reporter ?(attributes = []) () : Logs.reporter =
|
||||||
let report src level ~over k msgf =
|
let report src level ~over k msgf =
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
(re_export opentelemetry.util)
|
(re_export opentelemetry.util)
|
||||||
(re_export opentelemetry.ambient-context)
|
(re_export opentelemetry.ambient-context)
|
||||||
(re_export opentelemetry.atomic)
|
(re_export opentelemetry.atomic)
|
||||||
|
(re_export hmap)
|
||||||
mtime
|
mtime
|
||||||
mtime.clock.os
|
mtime.clock.os
|
||||||
pbrt
|
pbrt
|
||||||
threads
|
threads))
|
||||||
hmap))
|
|
||||||
|
|
|
||||||
|
|
@ -6,26 +6,55 @@
|
||||||
|
|
||||||
open Opentelemetry_emitter
|
open Opentelemetry_emitter
|
||||||
|
|
||||||
type t = Log_record.t Emitter.t
|
(** {2 Logger object} *)
|
||||||
|
|
||||||
let dummy : t = Emitter.dummy
|
type t = {
|
||||||
|
emit: Log_record.t Emitter.t;
|
||||||
|
clock: Clock.t;
|
||||||
|
}
|
||||||
|
|
||||||
let enabled = Emitter.enabled
|
let dummy : t = { emit = Emitter.dummy; clock = Clock.Main.dynamic_main }
|
||||||
|
|
||||||
let of_exporter (exp : Exporter.t) : t = exp.emit_logs
|
let[@inline] enabled (self : t) : bool = Emitter.enabled self.emit
|
||||||
|
|
||||||
let get_main () : t =
|
let of_exporter (exp : Exporter.t) : t =
|
||||||
match Main_exporter.get () with
|
{ emit = exp.emit_logs; clock = exp.clock }
|
||||||
| None -> dummy
|
|
||||||
| Some e -> e.emit_logs
|
|
||||||
|
|
||||||
let (emit [@deprecated "use an explicit Logger.t"]) =
|
let[@inline] emit1 (self : t) (l : Log_record.t) = Emitter.emit self.emit [ l ]
|
||||||
|
|
||||||
|
let (emit_main [@deprecated "use an explicit Logger.t"]) =
|
||||||
fun (logs : Log_record.t list) : unit ->
|
fun (logs : Log_record.t list) : unit ->
|
||||||
match Main_exporter.get () with
|
match Main_exporter.get () with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some exp -> Exporter.send_logs exp logs
|
| Some exp -> Exporter.send_logs exp logs
|
||||||
|
|
||||||
(** An emitter that uses the current {!Main_exporter} *)
|
(** An emitter that uses the current {!Main_exporter}'s logger *)
|
||||||
let dynamic_forward_to_main_exporter : t =
|
let dynamic_main : t =
|
||||||
Main_exporter.Util.dynamic_forward_to_main_exporter () ~get_emitter:(fun e ->
|
of_exporter Main_exporter.dynamic_forward_to_main_exporter
|
||||||
e.emit_logs)
|
|
||||||
|
(** {2 Logging helpers} *)
|
||||||
|
|
||||||
|
open Log_record
|
||||||
|
|
||||||
|
(** Create log record and emit it on [logger] *)
|
||||||
|
let log ?(logger = dynamic_main) ?attrs ?trace_id ?span_id
|
||||||
|
?(severity : severity option) (msg : string) : unit =
|
||||||
|
if enabled logger then (
|
||||||
|
let now = Clock.now logger.clock in
|
||||||
|
let logrec =
|
||||||
|
Log_record.make_str ?attrs ?trace_id ?span_id ?severity
|
||||||
|
~observed_time_unix_nano:now msg
|
||||||
|
in
|
||||||
|
emit1 logger logrec
|
||||||
|
)
|
||||||
|
|
||||||
|
(** Helper to create a log record, with a suspension, like in [Logs].
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
[logf ~severity:Severity_number_warn (fun k->k"oh no!! %s it's bad: %b"
|
||||||
|
"help" true)] *)
|
||||||
|
let logf ?(logger = dynamic_main) ?attrs ?trace_id ?span_id ?severity msgf :
|
||||||
|
unit =
|
||||||
|
if enabled logger then
|
||||||
|
msgf (fun fmt ->
|
||||||
|
Format.kasprintf (log ~logger ?attrs ?trace_id ?span_id ?severity) fmt)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,19 @@
|
||||||
open Opentelemetry_emitter
|
open Opentelemetry_emitter
|
||||||
|
|
||||||
type t = Metrics.t Emitter.t
|
type t = {
|
||||||
|
emit: Metrics.t Emitter.t;
|
||||||
|
clock: Clock.t;
|
||||||
|
}
|
||||||
|
|
||||||
let dummy : t = Emitter.dummy
|
let dummy : t = { emit = Emitter.dummy; clock = Clock.Main.dynamic_main }
|
||||||
|
|
||||||
let enabled = Emitter.enabled
|
let[@inline] enabled (self : t) = Emitter.enabled self.emit
|
||||||
|
|
||||||
let of_exporter (exp : Exporter.t) : t = exp.emit_metrics
|
let of_exporter (exp : Exporter.t) : t =
|
||||||
|
{ emit = exp.emit_metrics; clock = exp.clock }
|
||||||
|
|
||||||
|
let dynamic_main : t =
|
||||||
|
Main_exporter.dynamic_forward_to_main_exporter |> of_exporter
|
||||||
|
|
||||||
(** Emit some metrics to the collector (sync). This blocks until the backend has
|
(** Emit some metrics to the collector (sync). This blocks until the backend has
|
||||||
pushed the metrics into some internal queue, or discarded them. *)
|
pushed the metrics into some internal queue, or discarded them. *)
|
||||||
|
|
@ -16,12 +23,5 @@ let (emit [@deprecated "use an explicit Metrics_emitter.t"]) =
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some exp -> Exporter.send_metrics exp l
|
| Some exp -> Exporter.send_metrics exp l
|
||||||
|
|
||||||
let get_main () : t =
|
let[@inline] emit1 (self : t) (m : Metrics.t) : unit =
|
||||||
match Main_exporter.get () with
|
Emitter.emit self.emit [ m ]
|
||||||
| None -> dummy
|
|
||||||
| Some e -> e.emit_metrics
|
|
||||||
|
|
||||||
(** An emitter that uses the current {!Main_exporter} *)
|
|
||||||
let dynamic_forward_to_main_exporter : t =
|
|
||||||
Main_exporter.Util.dynamic_forward_to_main_exporter () ~get_emitter:(fun e ->
|
|
||||||
e.emit_metrics)
|
|
||||||
|
|
|
||||||
|
|
@ -10,29 +10,31 @@ open Opentelemetry_emitter
|
||||||
|
|
||||||
type span = Span.t
|
type span = Span.t
|
||||||
|
|
||||||
type t = Span.t Emitter.t
|
type t = {
|
||||||
|
emit: Span.t Emitter.t;
|
||||||
|
clock: Clock.t;
|
||||||
|
}
|
||||||
(** A tracer.
|
(** A tracer.
|
||||||
|
|
||||||
https://opentelemetry.io/docs/specs/otel/trace/api/#tracer *)
|
https://opentelemetry.io/docs/specs/otel/trace/api/#tracer *)
|
||||||
|
|
||||||
(** Dummy tracer, always disabled *)
|
(** Dummy tracer, always disabled *)
|
||||||
let dummy : t = Emitter.dummy
|
let dummy : t = { emit = Emitter.dummy; clock = Clock.Main.dynamic_main }
|
||||||
|
|
||||||
|
let[@inline] enabled (self : t) = Emitter.enabled self.emit
|
||||||
|
|
||||||
|
let of_exporter (exp : Exporter.t) : t =
|
||||||
|
{ emit = exp.emit_spans; clock = exp.clock }
|
||||||
|
|
||||||
(** A tracer that uses the current {!Main_exporter} *)
|
(** A tracer that uses the current {!Main_exporter} *)
|
||||||
let dynamic_forward_to_main_exporter : t =
|
let dynamic_main : t =
|
||||||
Main_exporter.Util.dynamic_forward_to_main_exporter () ~get_emitter:(fun e ->
|
Main_exporter.dynamic_forward_to_main_exporter |> of_exporter
|
||||||
e.emit_spans)
|
|
||||||
|
|
||||||
(** Get tracer using the main exporter in {!Main_exporter} *)
|
let (add_event [@deprecated "use Span.add_event"]) = Span.add_event'
|
||||||
let get_main () : t =
|
|
||||||
match Main_exporter.get () with
|
|
||||||
| None -> dummy
|
|
||||||
| Some e -> e.emit_spans
|
|
||||||
|
|
||||||
let (add_event [@deprecated "use Span.add_event"]) = Span.add_event
|
let (add_attrs [@deprecated "use Span.add_attrs"]) = Span.add_attrs'
|
||||||
|
|
||||||
let (add_attrs [@deprecated "use Span.add_attrs"]) = Span.add_attrs
|
|
||||||
|
|
||||||
|
(** Helper to implement {!with_} and similar functions *)
|
||||||
let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
||||||
?(attrs : (string * [< Value.t ]) list = []) ?kind ?trace_id ?parent ?links
|
?(attrs : (string * [< Value.t ]) list = []) ?kind ?trace_id ?parent ?links
|
||||||
name cb =
|
name cb =
|
||||||
|
|
@ -48,7 +50,8 @@ let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
||||||
| None, Some p -> Span.trace_id p
|
| None, Some p -> Span.trace_id p
|
||||||
| None, None -> Trace_id.create ()
|
| None, None -> Trace_id.create ()
|
||||||
in
|
in
|
||||||
let start_time = Timestamp_ns.now_unix_ns () in
|
(* TODO: pass a clock in emitters *)
|
||||||
|
let start_time = Clock.now_main () in
|
||||||
let span_id = Span_id.create () in
|
let span_id = Span_id.create () in
|
||||||
|
|
||||||
let parent_id = Option.map Span.id parent in
|
let parent_id = Option.map Span.id parent in
|
||||||
|
|
@ -59,7 +62,7 @@ let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
||||||
in
|
in
|
||||||
(* called once we're done, to emit a span *)
|
(* called once we're done, to emit a span *)
|
||||||
let finally res =
|
let finally res =
|
||||||
let end_time = Timestamp_ns.now_unix_ns () in
|
let end_time = Clock.now_main () in
|
||||||
Proto.Trace.span_set_end_time_unix_nano span end_time;
|
Proto.Trace.span_set_end_time_unix_nano span end_time;
|
||||||
|
|
||||||
(match Span.status span with
|
(match Span.status span with
|
||||||
|
|
@ -80,7 +83,7 @@ let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
||||||
in
|
in
|
||||||
Span.set_status span status));
|
Span.set_status span status));
|
||||||
|
|
||||||
Emitter.emit self [ span ]
|
Emitter.emit self.emit [ span ]
|
||||||
in
|
in
|
||||||
let thunk () = Ambient_span.with_ambient span (fun () -> cb span) in
|
let thunk () = Ambient_span.with_ambient span (fun () -> cb span) in
|
||||||
thunk, finally
|
thunk, finally
|
||||||
|
|
@ -97,14 +100,15 @@ let with_thunk_and_finally (self : t) ?(force_new_trace_id = false) ?trace_state
|
||||||
{b NOTE} be careful not to call this inside a Gc alarm, as it can cause
|
{b NOTE} be careful not to call this inside a Gc alarm, as it can cause
|
||||||
deadlocks.
|
deadlocks.
|
||||||
|
|
||||||
|
@param tracer the tracer to use (default [get_main()])
|
||||||
@param force_new_trace_id
|
@param force_new_trace_id
|
||||||
if true (default false), the span will not use a ambient scope, the
|
if true (default false), the span will not use a ambient scope, the
|
||||||
[~scope] argument, nor [~trace_id], but will instead always create fresh
|
[~scope] argument, nor [~trace_id], but will instead always create fresh
|
||||||
identifiers for this span *)
|
identifiers for this span *)
|
||||||
let with_ (self : t) ?force_new_trace_id ?trace_state ?attrs ?kind ?trace_id
|
let with_ ?(tracer = dynamic_main) ?force_new_trace_id ?trace_state ?attrs ?kind
|
||||||
?parent ?links name (cb : Span.t -> 'a) : 'a =
|
?trace_id ?parent ?links name (cb : Span.t -> 'a) : 'a =
|
||||||
let thunk, finally =
|
let thunk, finally =
|
||||||
with_thunk_and_finally self ?force_new_trace_id ?trace_state ?attrs ?kind
|
with_thunk_and_finally tracer ?force_new_trace_id ?trace_state ?attrs ?kind
|
||||||
?trace_id ?parent ?links name cb
|
?trace_id ?parent ?links name cb
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ module Tracer = struct
|
||||||
include Tracer
|
include Tracer
|
||||||
|
|
||||||
(** Sync span guard *)
|
(** Sync span guard *)
|
||||||
let with_ (self : t) ?force_new_trace_id ?trace_state ?attrs ?kind ?trace_id
|
let with_ ?(tracer = dynamic_main) ?force_new_trace_id ?trace_state ?attrs
|
||||||
?parent ?links name (cb : Span.t -> 'a Lwt.t) : 'a Lwt.t =
|
?kind ?trace_id ?parent ?links name (cb : Span.t -> 'a Lwt.t) : 'a Lwt.t =
|
||||||
let thunk, finally =
|
let thunk, finally =
|
||||||
with_thunk_and_finally self ?force_new_trace_id ?trace_state ?attrs ?kind
|
with_thunk_and_finally tracer ?force_new_trace_id ?trace_state ?attrs
|
||||||
?trace_id ?parent ?links name cb
|
?kind ?trace_id ?parent ?links name cb
|
||||||
in
|
in
|
||||||
|
|
||||||
try%lwt
|
try%lwt
|
||||||
|
|
|
||||||
|
|
@ -315,11 +315,13 @@ module Make_collector (A : COLLECTOR_ARG) = struct
|
||||||
let name_thread _name = ()
|
let name_thread _name = ()
|
||||||
|
|
||||||
let counter_int ~data:attrs name cur_val : unit =
|
let counter_int ~data:attrs name cur_val : unit =
|
||||||
let m = OTEL.Metrics.(gauge ~name [ int ~attrs cur_val ]) in
|
let now = OTEL.Clock.now exporter.clock in
|
||||||
|
let m = OTEL.Metrics.(gauge ~name [ int ~attrs ~now cur_val ]) in
|
||||||
OTEL.Exporter.send_metrics exporter [ m ]
|
OTEL.Exporter.send_metrics exporter [ m ]
|
||||||
|
|
||||||
let counter_float ~data:attrs name cur_val : unit =
|
let counter_float ~data:attrs name cur_val : unit =
|
||||||
let m = OTEL.Metrics.(gauge ~name [ float ~attrs cur_val ]) in
|
let now = OTEL.Clock.now exporter.clock in
|
||||||
|
let m = OTEL.Metrics.(gauge ~name [ float ~attrs ~now cur_val ]) in
|
||||||
OTEL.Exporter.send_metrics exporter [ m ]
|
OTEL.Exporter.send_metrics exporter [ m ]
|
||||||
|
|
||||||
let extension_event = function
|
let extension_event = function
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ let run_job () =
|
||||||
while OT.Aswitch.is_on active && !cnt < !n do
|
while OT.Aswitch.is_on active && !cnt < !n do
|
||||||
let@ _scope =
|
let@ _scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
||||||
~attrs:[ "i", `Int !i ]
|
~attrs:[ "i", `Int !i ]
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ let run_job () =
|
||||||
(* parent scope is found via thread local storage *)
|
(* parent scope is found via thread local storage *)
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_internal ~parent:_scope
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_internal ~parent:_scope
|
||||||
~attrs:[ "j", `Int j ]
|
~attrs:[ "j", `Int j ]
|
||||||
"loop.inner"
|
"loop.inner"
|
||||||
in
|
in
|
||||||
|
|
@ -49,13 +49,9 @@ let run_job () =
|
||||||
Atomic.incr num_sleep
|
Atomic.incr num_sleep
|
||||||
);
|
);
|
||||||
|
|
||||||
let logger = OT.Logger.get_main () in
|
OT.Logger.logf ~trace_id:(OT.Span.trace_id scope)
|
||||||
OT.Emitter.emit logger
|
~span_id:(OT.Span.id scope) ~severity:Severity_number_info (fun k ->
|
||||||
[
|
k "inner at %d" j);
|
||||||
OT.Log_record.make_strf ~trace_id:(OT.Span.trace_id scope)
|
|
||||||
~span_id:(OT.Span.id scope) ~severity:Severity_number_info
|
|
||||||
"inner at %d" j;
|
|
||||||
];
|
|
||||||
|
|
||||||
incr i;
|
incr i;
|
||||||
|
|
||||||
|
|
@ -63,7 +59,7 @@ let run_job () =
|
||||||
(* allocate some stuff *)
|
(* allocate some stuff *)
|
||||||
if !stress_alloc_ then (
|
if !stress_alloc_ then (
|
||||||
let@ _ =
|
let@ _ =
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_internal
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_internal
|
||||||
~parent:scope "alloc"
|
~parent:scope "alloc"
|
||||||
in
|
in
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ let run_job job_id : unit Lwt.t =
|
||||||
let tracer = T.Tracer.get_main () in
|
let tracer = T.Tracer.get_main () in
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
T.Tracer.with_ tracer ~kind:T.Span.Span_kind_producer "loop.outer"
|
T.Tracer.with_ ~tracer ~kind:T.Span.Span_kind_producer "loop.outer"
|
||||||
~attrs:[ "i", `Int job_id ]
|
~attrs:[ "i", `Int job_id ]
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ let run_job job_id : unit Lwt.t =
|
||||||
(* parent scope is found via thread local storage *)
|
(* parent scope is found via thread local storage *)
|
||||||
let@ span =
|
let@ span =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
T.Tracer.with_ tracer ~parent:scope ~kind:T.Span.Span_kind_internal
|
T.Tracer.with_ ~tracer ~parent:scope ~kind:T.Span.Span_kind_internal
|
||||||
~attrs:[ "j", `Int j ]
|
~attrs:[ "j", `Int j ]
|
||||||
"loop.inner"
|
"loop.inner"
|
||||||
in
|
in
|
||||||
|
|
@ -49,19 +49,15 @@ let run_job job_id : unit Lwt.t =
|
||||||
let* () = Lwt_unix.sleep !sleep_outer in
|
let* () = Lwt_unix.sleep !sleep_outer in
|
||||||
Atomic.incr num_sleep;
|
Atomic.incr num_sleep;
|
||||||
|
|
||||||
Opentelemetry_emitter.Emitter.emit (T.Logger.get_main ())
|
T.Logger.logf ~trace_id:(T.Span.trace_id span) ~span_id:(T.Span.id span)
|
||||||
[
|
~severity:Severity_number_info (fun k -> k "inner at %d" j);
|
||||||
T.Log_record.make_strf ~trace_id:(T.Span.trace_id span)
|
|
||||||
~span_id:(T.Span.id span) ~severity:Severity_number_info
|
|
||||||
"inner at %d" j;
|
|
||||||
];
|
|
||||||
|
|
||||||
incr i;
|
incr i;
|
||||||
|
|
||||||
try%lwt
|
try%lwt
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
let@ scope =
|
let@ scope =
|
||||||
T.Tracer.with_ tracer ~kind:T.Span.Span_kind_internal ~parent:span
|
T.Tracer.with_ ~tracer ~kind:T.Span.Span_kind_internal ~parent:span
|
||||||
"alloc"
|
"alloc"
|
||||||
in
|
in
|
||||||
(* allocate some stuff *)
|
(* allocate some stuff *)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ let run_job clock _job_id iterations : unit =
|
||||||
let tracer = OT.Tracer.get_main () in
|
let tracer = OT.Tracer.get_main () in
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
||||||
~attrs:[ "i", `Int (Atomic.get i) ]
|
~attrs:[ "i", `Int (Atomic.get i) ]
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@ let run_job clock _job_id iterations : unit =
|
||||||
(* parent scope is found via thread local storage *)
|
(* parent scope is found via thread local storage *)
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~parent:scope ~kind:OT.Span.Span_kind_internal
|
OT.Tracer.with_ ~tracer ~parent:scope ~kind:OT.Span.Span_kind_internal
|
||||||
~attrs:[ "j", `Int j ]
|
~attrs:[ "j", `Int j ]
|
||||||
"loop.inner"
|
"loop.inner"
|
||||||
in
|
in
|
||||||
|
|
@ -46,20 +46,16 @@ let run_job clock _job_id iterations : unit =
|
||||||
let () = Eio.Time.sleep clock !sleep_outer in
|
let () = Eio.Time.sleep clock !sleep_outer in
|
||||||
Atomic.incr num_sleep;
|
Atomic.incr num_sleep;
|
||||||
|
|
||||||
(let logger = OT.Logger.get_main () in
|
OT.Logger.logf ~trace_id:(OT.Span.trace_id scope)
|
||||||
OT.Emitter.emit logger
|
~span_id:(OT.Span.id scope) ~severity:Severity_number_info (fun k ->
|
||||||
[
|
k "inner at %d" j);
|
||||||
OT.Log_record.make_strf ~trace_id:(OT.Span.trace_id scope)
|
|
||||||
~span_id:(OT.Span.id scope) ~severity:Severity_number_info
|
|
||||||
"inner at %d" j;
|
|
||||||
]);
|
|
||||||
|
|
||||||
Atomic.incr i;
|
Atomic.incr i;
|
||||||
|
|
||||||
try
|
try
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
let@ scope =
|
let@ scope =
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_internal ~parent:scope
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_internal ~parent:scope
|
||||||
"alloc"
|
"alloc"
|
||||||
in
|
in
|
||||||
(* allocate some stuff *)
|
(* allocate some stuff *)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ let run_job () =
|
||||||
while OT.Aswitch.is_on active && !cnt < !n do
|
while OT.Aswitch.is_on active && !cnt < !n do
|
||||||
let@ _scope =
|
let@ _scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_producer "loop.outer"
|
||||||
~attrs:[ "i", `Int !i ]
|
~attrs:[ "i", `Int !i ]
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ let run_job () =
|
||||||
(* parent scope is found via thread local storage *)
|
(* parent scope is found via thread local storage *)
|
||||||
let@ scope =
|
let@ scope =
|
||||||
Atomic.incr num_tr;
|
Atomic.incr num_tr;
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_internal ~parent:_scope
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_internal ~parent:_scope
|
||||||
~attrs:[ "j", `Int j ]
|
~attrs:[ "j", `Int j ]
|
||||||
"loop.inner"
|
"loop.inner"
|
||||||
in
|
in
|
||||||
|
|
@ -49,13 +49,9 @@ let run_job () =
|
||||||
Atomic.incr num_sleep
|
Atomic.incr num_sleep
|
||||||
);
|
);
|
||||||
|
|
||||||
let logger = OT.Logger.get_main () in
|
OT.Logger.logf ~trace_id:(OT.Span.trace_id scope)
|
||||||
OT.Emitter.emit logger
|
~span_id:(OT.Span.id scope) ~severity:Severity_number_info (fun k ->
|
||||||
[
|
k "inner at %d" j);
|
||||||
OT.Log_record.make_strf ~trace_id:(OT.Span.trace_id scope)
|
|
||||||
~span_id:(OT.Span.id scope) ~severity:Severity_number_info
|
|
||||||
"inner at %d" j;
|
|
||||||
];
|
|
||||||
|
|
||||||
incr i;
|
incr i;
|
||||||
|
|
||||||
|
|
@ -64,7 +60,7 @@ let run_job () =
|
||||||
(* allocate some stuff *)
|
(* allocate some stuff *)
|
||||||
(if !stress_alloc_ then
|
(if !stress_alloc_ then
|
||||||
let@ _ =
|
let@ _ =
|
||||||
OT.Tracer.with_ tracer ~kind:OT.Span.Span_kind_internal
|
OT.Tracer.with_ ~tracer ~kind:OT.Span.Span_kind_internal
|
||||||
~parent:scope "alloc"
|
~parent:scope "alloc"
|
||||||
in
|
in
|
||||||
let _arr : _ array =
|
let _arr : _ array =
|
||||||
|
|
@ -153,10 +149,10 @@ let () =
|
||||||
!sleep_outer !sleep_inner !queued;
|
!sleep_outer !sleep_inner !queued;
|
||||||
|
|
||||||
let exporter =
|
let exporter =
|
||||||
let exp = OTC.Exporter_stdout.stdout in
|
let exp = OTC.Exporter_stdout.stdout () in
|
||||||
if !queued then (
|
if !queued then (
|
||||||
let q = OTC.Bounded_queue_sync.create ~high_watermark:20_000 () in
|
let q = OTC.Bounded_queue_sync.create ~high_watermark:20_000 () in
|
||||||
OTC.Exporter_queued.create ~q
|
OTC.Exporter_queued.create ~clock:exp.clock ~q
|
||||||
~consumer:(Consumer_exporter.consumer exp)
|
~consumer:(Consumer_exporter.consumer exp)
|
||||||
()
|
()
|
||||||
) else
|
) else
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ let run () =
|
||||||
Logs.app (fun m -> m "emit_logs: app log");
|
Logs.app (fun m -> m "emit_logs: app log");
|
||||||
let%lwt () =
|
let%lwt () =
|
||||||
let tracer = T.Tracer.get_main () in
|
let tracer = T.Tracer.get_main () in
|
||||||
T.Tracer.with_ tracer ~kind:T.Span.Span_kind_producer "my_scope"
|
T.Tracer.with_ ~tracer ~kind:T.Span.Span_kind_producer "my_scope"
|
||||||
(fun _scope ->
|
(fun _scope ->
|
||||||
Logs.info (fun m ->
|
Logs.info (fun m ->
|
||||||
m ~tags:varied_tag_set
|
m ~tags:varied_tag_set
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,11 @@ let bytes_to_hex = Opentelemetry_util.Util_bytes_.bytes_to_hex
|
||||||
|
|
||||||
let test_stack_based_implicit_scope () =
|
let test_stack_based_implicit_scope () =
|
||||||
let run () =
|
let run () =
|
||||||
let tracer = Otel.Tracer.get_main () in
|
Otel.Tracer.with_ "first trace" @@ fun _scope ->
|
||||||
Otel.Tracer.with_ tracer "first trace" @@ fun _scope ->
|
|
||||||
Thread.delay 0.2;
|
Thread.delay 0.2;
|
||||||
Otel.Tracer.with_ tracer "second trace" @@ fun _scope ->
|
Otel.Tracer.with_ "second trace" @@ fun _scope ->
|
||||||
Thread.delay 0.2;
|
Thread.delay 0.2;
|
||||||
Otel.Tracer.with_ tracer "third trace" @@ fun _scope ->
|
Otel.Tracer.with_ "third trace" @@ fun _scope ->
|
||||||
Thread.delay 0.2;
|
Thread.delay 0.2;
|
||||||
()
|
()
|
||||||
in
|
in
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue