ocaml-opentelemetry/src/client/sampler.ml
2026-01-20 00:15:13 -05:00

49 lines
1.3 KiB
OCaml

type t = {
proba_accept: float;
n_seen: int Atomic.t;
n_accepted: int Atomic.t;
}
let create ~proba_accept () : t =
(* FIXME: either czzry a random state and protect it, or make sure
we Random.self_init() in the current domain?? *)
if proba_accept < 0. || proba_accept > 1. then
invalid_arg "sampler: proba_accept must be in [0., 1.]";
{ proba_accept; n_seen = Atomic.make 0; n_accepted = Atomic.make 0 }
let[@inline] proba_accept self = self.proba_accept
let actual_rate (self : t) : float =
let accept = Atomic.get self.n_accepted in
let total = Atomic.get self.n_seen in
if total = 0 then
1.
else
float accept /. float total
let accept (self : t) : bool =
Atomic.incr self.n_seen;
let n = Random.float 1. in
let res = n < self.proba_accept in
if res then Atomic.incr self.n_accepted;
res
open Opentelemetry_emitter
let wrap_emitter (self : t) (e : _ Emitter.t) : _ Emitter.t =
let enabled () = e.enabled () in
let closed () = Emitter.closed e in
let flush_and_close () = Emitter.flush_and_close e in
let tick ~now = Emitter.tick e ~now in
let emit l =
if l <> [] && e.enabled () then (
let accepted = List.filter (fun _x -> accept self) l in
if accepted <> [] then Emitter.emit e accepted
)
in
{ Emitter.closed; enabled; flush_and_close; tick; emit }