mirror of
https://github.com/ocaml-tracing/ocaml-opentelemetry.git
synced 2026-03-08 20:07:55 -04:00
limit scope of locks
This commit is contained in:
parent
6d72a6fac0
commit
053493db8b
1 changed files with 65 additions and 46 deletions
|
|
@ -143,6 +143,9 @@ end
|
||||||
|
|
||||||
module type BATCH = sig end
|
module type BATCH = sig end
|
||||||
|
|
||||||
|
(** Batch of resources to be pushed later.
|
||||||
|
|
||||||
|
This type is thread-safe. *)
|
||||||
module Batch : sig
|
module Batch : sig
|
||||||
type 'a t
|
type 'a t
|
||||||
|
|
||||||
|
|
@ -164,6 +167,7 @@ module Batch : sig
|
||||||
@param now passed to implement timeout *)
|
@param now passed to implement timeout *)
|
||||||
|
|
||||||
val make : ?batch:int -> ?timeout:Mtime.span -> unit -> 'a t
|
val make : ?batch:int -> ?timeout:Mtime.span -> unit -> 'a t
|
||||||
|
(** Create a new batch *)
|
||||||
end = struct
|
end = struct
|
||||||
type 'a t = {
|
type 'a t = {
|
||||||
lock: Mutex.t;
|
lock: Mutex.t;
|
||||||
|
|
@ -266,12 +270,6 @@ let start_bg_thread (f : unit -> unit) : unit =
|
||||||
in
|
in
|
||||||
ignore (Thread.create run () : Thread.t)
|
ignore (Thread.create run () : Thread.t)
|
||||||
|
|
||||||
let l_is_empty = function
|
|
||||||
| [] -> true
|
|
||||||
| _ :: _ -> false
|
|
||||||
|
|
||||||
let batch_is_empty = List.for_all l_is_empty
|
|
||||||
|
|
||||||
(* make an emitter.
|
(* make an emitter.
|
||||||
|
|
||||||
exceptions inside should be caught, see
|
exceptions inside should be caught, see
|
||||||
|
|
@ -295,9 +293,9 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
let batch_logs : Logs.resource_logs list Batch.t =
|
let batch_logs : Logs.resource_logs list Batch.t =
|
||||||
Batch.make ?batch:config.batch_logs ?timeout ()
|
Batch.make ?batch:config.batch_logs ?timeout ()
|
||||||
|
|
||||||
let on_tick_cbs_ = ref (ref [])
|
let on_tick_cbs_ = Atomic.make (ref [])
|
||||||
|
|
||||||
let set_on_tick_callbacks = ( := ) on_tick_cbs_
|
let set_on_tick_callbacks = Atomic.set on_tick_cbs_
|
||||||
|
|
||||||
let send_http_ (httpc : Httpc.t) encoder ~path ~encode x : unit =
|
let send_http_ (httpc : Httpc.t) encoder ~path ~encode x : unit =
|
||||||
Pbrt.Encoder.reset encoder;
|
Pbrt.Encoder.reset encoder;
|
||||||
|
|
@ -373,13 +371,39 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
ignore (emit_traces_maybe ~now ~force:true httpc encoder : bool);
|
ignore (emit_traces_maybe ~now ~force:true httpc encoder : bool);
|
||||||
ignore (emit_logs_maybe ~now ~force:true httpc encoder : bool);
|
ignore (emit_logs_maybe ~now ~force:true httpc encoder : bool);
|
||||||
ignore (emit_metrics_maybe ~now ~force:true httpc encoder : bool)
|
ignore (emit_metrics_maybe ~now ~force:true httpc encoder : bool)
|
||||||
|
|
||||||
|
let tick_common_ () =
|
||||||
|
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
||||||
|
List.iter
|
||||||
|
(fun f ->
|
||||||
|
try f ()
|
||||||
|
with e ->
|
||||||
|
Printf.eprintf "on tick callback raised: %s\n"
|
||||||
|
(Printexc.to_string e))
|
||||||
|
!(Atomic.get on_tick_cbs_);
|
||||||
|
()
|
||||||
|
|
||||||
|
let setup_ticker_thread ~tick ~finally () =
|
||||||
|
(* thread that calls [tick()] regularly, to help enforce timeouts *)
|
||||||
|
let tick_thread () =
|
||||||
|
let@ () =
|
||||||
|
Fun.protect ~finally:(fun () ->
|
||||||
|
Atomic.set stop true;
|
||||||
|
finally ())
|
||||||
|
in
|
||||||
|
while not @@ Atomic.get stop do
|
||||||
|
Thread.delay 0.5;
|
||||||
|
tick ()
|
||||||
|
done
|
||||||
|
in
|
||||||
|
start_bg_thread tick_thread
|
||||||
end in
|
end in
|
||||||
if config.bg_threads > 0 then (
|
|
||||||
(let m = Mutex.create () in
|
(let m = Mutex.create () in
|
||||||
Lock.set_mutex
|
Lock.set_mutex
|
||||||
~lock:(fun () -> Mutex.lock m)
|
~lock:(fun () -> Mutex.lock m)
|
||||||
~unlock:(fun () -> Mutex.unlock m));
|
~unlock:(fun () -> Mutex.unlock m));
|
||||||
|
|
||||||
|
if config.bg_threads > 0 then (
|
||||||
let m = Mutex.create () in
|
let m = Mutex.create () in
|
||||||
let cond = Condition.create () in
|
let cond = Condition.create () in
|
||||||
|
|
||||||
|
|
@ -420,14 +444,7 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
in
|
in
|
||||||
|
|
||||||
let tick () =
|
let tick () =
|
||||||
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
tick_common_ ();
|
||||||
List.iter
|
|
||||||
(fun f ->
|
|
||||||
try f ()
|
|
||||||
with e ->
|
|
||||||
Printf.eprintf "on tick callback raised: %s\n"
|
|
||||||
(Printexc.to_string e))
|
|
||||||
!(!on_tick_cbs_);
|
|
||||||
|
|
||||||
let now = Mtime_clock.now () in
|
let now = Mtime_clock.now () in
|
||||||
if Atomic.get stop then
|
if Atomic.get stop then
|
||||||
|
|
@ -440,18 +457,8 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
wakeup ~all:false ()
|
wakeup ~all:false ()
|
||||||
in
|
in
|
||||||
|
|
||||||
if config.ticker_thread then (
|
if config.ticker_thread then
|
||||||
(* thread that calls [tick()] regularly, to help enforce timeouts *)
|
setup_ticker_thread ~tick ~finally:(fun () -> wakeup ~all:true ()) ();
|
||||||
let tick_thread () =
|
|
||||||
while not @@ Atomic.get stop do
|
|
||||||
Thread.delay 0.5;
|
|
||||||
tick ()
|
|
||||||
done;
|
|
||||||
wakeup ~all:true ()
|
|
||||||
in
|
|
||||||
|
|
||||||
start_bg_thread tick_thread
|
|
||||||
);
|
|
||||||
|
|
||||||
let module M = struct
|
let module M = struct
|
||||||
let push_trace e = if Batch.push batch_traces e then wakeup ~all:false ()
|
let push_trace e = if Batch.push batch_traces e then wakeup ~all:false ()
|
||||||
|
|
@ -468,8 +475,7 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
let cleanup () =
|
let cleanup () =
|
||||||
Atomic.set stop true;
|
Atomic.set stop true;
|
||||||
if !debug_ then Printf.eprintf "opentelemetry: exiting…\n%!";
|
if !debug_ then Printf.eprintf "opentelemetry: exiting…\n%!";
|
||||||
(* wakeup everyone *)
|
wakeup ~all:true ()
|
||||||
with_mutex_ m (fun () -> Condition.broadcast cond)
|
|
||||||
end in
|
end in
|
||||||
(module M)
|
(module M)
|
||||||
) else (
|
) else (
|
||||||
|
|
@ -477,10 +483,16 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
let encoder = Pbrt.Encoder.create () in
|
let encoder = Pbrt.Encoder.create () in
|
||||||
|
|
||||||
let module M = struct
|
let module M = struct
|
||||||
|
(* we make sure that this is thread-safe, even though we don't have a
|
||||||
|
background thread. There can still be a ticker thread, and there
|
||||||
|
can also be several user threads that produce spans and call
|
||||||
|
the emit functions. *)
|
||||||
|
|
||||||
let push_trace e =
|
let push_trace e =
|
||||||
let@ () = guard_exn_ in
|
let@ () = guard_exn_ in
|
||||||
Batch.push' batch_traces e;
|
Batch.push' batch_traces e;
|
||||||
let now = Mtime_clock.now () in
|
let now = Mtime_clock.now () in
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
ignore (emit_traces_maybe ~now httpc encoder : bool)
|
ignore (emit_traces_maybe ~now httpc encoder : bool)
|
||||||
|
|
||||||
let push_metrics e =
|
let push_metrics e =
|
||||||
|
|
@ -488,24 +500,32 @@ let mk_emitter ~stop ~(config : Config.t) () : (module EMITTER) =
|
||||||
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
||||||
Batch.push' batch_metrics e;
|
Batch.push' batch_metrics e;
|
||||||
let now = Mtime_clock.now () in
|
let now = Mtime_clock.now () in
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
ignore (emit_metrics_maybe ~now httpc encoder : bool)
|
ignore (emit_metrics_maybe ~now httpc encoder : bool)
|
||||||
|
|
||||||
let push_logs e =
|
let push_logs e =
|
||||||
let@ () = guard_exn_ in
|
let@ () = guard_exn_ in
|
||||||
Batch.push' batch_logs e;
|
Batch.push' batch_logs e;
|
||||||
let now = Mtime_clock.now () in
|
let now = Mtime_clock.now () in
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
ignore (emit_logs_maybe ~now httpc encoder : bool)
|
ignore (emit_logs_maybe ~now httpc encoder : bool)
|
||||||
|
|
||||||
let set_on_tick_callbacks = set_on_tick_callbacks
|
let set_on_tick_callbacks = set_on_tick_callbacks
|
||||||
|
|
||||||
let tick () =
|
let tick () =
|
||||||
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
if Atomic.get needs_gc_metrics then sample_gc_metrics ();
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
let now = Mtime_clock.now () in
|
let now = Mtime_clock.now () in
|
||||||
ignore (emit_traces_maybe ~now httpc encoder : bool);
|
ignore (emit_traces_maybe ~now httpc encoder : bool);
|
||||||
ignore (emit_metrics_maybe ~now httpc encoder : bool);
|
ignore (emit_metrics_maybe ~now httpc encoder : bool);
|
||||||
ignore (emit_logs_maybe ~now httpc encoder : bool);
|
ignore (emit_logs_maybe ~now httpc encoder : bool);
|
||||||
()
|
()
|
||||||
|
|
||||||
|
(* make sure we have a ticker thread, if required *)
|
||||||
|
let () =
|
||||||
|
if config.ticker_thread then
|
||||||
|
setup_ticker_thread ~tick ~finally:ignore ()
|
||||||
|
|
||||||
let cleanup () =
|
let cleanup () =
|
||||||
if !debug_ then Printf.eprintf "opentelemetry: exiting…\n%!";
|
if !debug_ then Printf.eprintf "opentelemetry: exiting…\n%!";
|
||||||
emit_all_force httpc encoder;
|
emit_all_force httpc encoder;
|
||||||
|
|
@ -529,11 +549,11 @@ end)
|
||||||
{
|
{
|
||||||
send =
|
send =
|
||||||
(fun l ~ret ->
|
(fun l ~ret ->
|
||||||
|
(if !debug_ then
|
||||||
let@ () = Lock.with_lock in
|
let@ () = Lock.with_lock in
|
||||||
if !debug_ then
|
|
||||||
Format.eprintf "send spans %a@."
|
Format.eprintf "send spans %a@."
|
||||||
(Format.pp_print_list Trace.pp_resource_spans)
|
(Format.pp_print_list Trace.pp_resource_spans)
|
||||||
l;
|
l);
|
||||||
push_trace l;
|
push_trace l;
|
||||||
ret ());
|
ret ());
|
||||||
}
|
}
|
||||||
|
|
@ -581,12 +601,11 @@ end)
|
||||||
{
|
{
|
||||||
send =
|
send =
|
||||||
(fun m ~ret ->
|
(fun m ~ret ->
|
||||||
if !debug_ then
|
(if !debug_ then
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
Format.eprintf "send metrics %a@."
|
Format.eprintf "send metrics %a@."
|
||||||
(Format.pp_print_list Metrics.pp_resource_metrics)
|
(Format.pp_print_list Metrics.pp_resource_metrics)
|
||||||
m;
|
m);
|
||||||
|
|
||||||
let@ () = Lock.with_lock in
|
|
||||||
|
|
||||||
let m = List.rev_append (additional_metrics ()) m in
|
let m = List.rev_append (additional_metrics ()) m in
|
||||||
push_metrics m;
|
push_metrics m;
|
||||||
|
|
@ -597,12 +616,12 @@ end)
|
||||||
{
|
{
|
||||||
send =
|
send =
|
||||||
(fun m ~ret ->
|
(fun m ~ret ->
|
||||||
if !debug_ then
|
(if !debug_ then
|
||||||
|
let@ () = Lock.with_lock in
|
||||||
Format.eprintf "send logs %a@."
|
Format.eprintf "send logs %a@."
|
||||||
(Format.pp_print_list Logs.pp_resource_logs)
|
(Format.pp_print_list Logs.pp_resource_logs)
|
||||||
m;
|
m);
|
||||||
|
|
||||||
let@ () = Lock.with_lock in
|
|
||||||
push_logs m;
|
push_logs m;
|
||||||
ret ());
|
ret ());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue