From df4d657c1adc34c513ff8c5e02ff011816d41aa2 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 4 Dec 2025 10:56:04 -0500 Subject: [PATCH] emitter: add `enabled()` field, and `tap` --- src/emitter/emitter.ml | 26 ++++++++++++++++++++++---- src/emitter/to_list.ml | 6 +++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/emitter/emitter.ml b/src/emitter/emitter.ml index 02d8822e..d3aa0e5e 100644 --- a/src/emitter/emitter.ml +++ b/src/emitter/emitter.ml @@ -7,7 +7,10 @@ exception Closed -type 'a t = { +type -'a t = { + enabled: unit -> bool; + (** Return [true] if [emit] has a chance of doing something with the + signals it's given. *) emit: 'a list -> unit; (** Emit signals. @raise Closed if the emitter is closed. *) tick: now:Mtime.t -> unit; @@ -20,6 +23,8 @@ type 'a t = { } (** An emitter for values of type ['a]. *) +let[@inline] enabled self : bool = self.enabled () + let[@inline] emit (self : _ t) l : unit = if l <> [] then self.emit l let[@inline] tick (self : _ t) ~now : unit = self.tick ~now @@ -33,7 +38,20 @@ let[@inline] flush_and_close (self : _ t) : unit = self.flush_and_close () let map (f : 'a -> 'b) (self : 'b t) : 'a t = { self with emit = (fun l -> self.emit (List.map f l)) } -(* TODO: batching, either regular or sharded to reduce contention *) -(* TODO: sampling *) +(** [tap f e] is like [e], but every signal is passed to [f] *) +let tap (f : 'a -> unit) (self : 'a t) : 'a t = + let emit l = + List.iter f l; + self.emit l + in + { self with emit } -(* TODO: use in Opentelemetry, and also for Tracer, Logger, etc. *) +let dummy () : _ t = + let closed = Atomic.make false in + { + enabled = (fun () -> false); + emit = ignore; + tick = (fun ~now:_ -> ()); + closed = (fun () -> Atomic.get closed); + flush_and_close = (fun () -> Atomic.set closed true); + } diff --git a/src/emitter/to_list.ml b/src/emitter/to_list.ml index 61a42ab8..04e228ca 100644 --- a/src/emitter/to_list.ml +++ b/src/emitter/to_list.ml @@ -3,7 +3,11 @@ let to_list (l : 'a list ref) : 'a Emitter.t = let closed = Atomic.make false in { - emit = (fun sigs -> l := List.rev_append sigs !l); + enabled = (fun () -> not (Atomic.get closed)); + emit = + (fun sigs -> + if Atomic.get closed then raise Emitter.Closed; + l := List.rev_append sigs !l); tick = (fun ~now:_ -> ()); closed = (fun () -> Atomic.get closed); flush_and_close = (fun () -> Atomic.set closed true);