From 1ac44c4dd80f77e16a8f31bd45ea13832c68eda7 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 4 Dec 2025 11:30:49 -0500 Subject: [PATCH] feat client: add exporter_stdout --- src/client/exporter_stdout.ml | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/client/exporter_stdout.ml diff --git a/src/client/exporter_stdout.ml b/src/client/exporter_stdout.ml new file mode 100644 index 00000000..4e8ec5c2 --- /dev/null +++ b/src/client/exporter_stdout.ml @@ -0,0 +1,62 @@ +(** A simple exporter that prints on stdout *) + +open Common_ +open Opentelemetry_util +open Opentelemetry_emitter + +open struct + let pp_span out (sp : OTEL.Span.t) = + let open OTEL in + Format.fprintf out + "@[<2>SPAN@ trace_id: %a@ span_id: %a@ name: %S@ start: %a@ end: %a@]@." + Trace_id.pp + (Trace_id.of_bytes sp.trace_id) + Span_id.pp + (Span_id.of_bytes sp.span_id) + sp.name Timestamp_ns.pp_debug sp.start_time_unix_nano + Timestamp_ns.pp_debug sp.end_time_unix_nano + + let pp_vlist mutex pp out l = + if l != [] then ( + let@ () = Util_mutex.protect mutex in + Format.fprintf out "@["; + List.iteri + (fun i x -> + if i > 0 then Format.fprintf out "@,"; + pp out x) + l; + Format.fprintf out "@]@." + ) +end + +let stdout : OTEL.Exporter.t = + let open Opentelemetry_util in + let out = Format.std_formatter in + let mutex = Mutex.create () in + + let closed = Atomic.make false in + + let mk_emitter pp_signal = + let emit l = + if Atomic.get closed then raise Emitter.Closed; + pp_vlist mutex pp_signal out l + in + let enabled () = not (Atomic.get closed) in + let tick ~now:_ = () in + let flush_and_close () = + if not (Atomic.exchange closed true) then + let@ () = Util_mutex.protect mutex in + Format.pp_print_flush out () + in + let closed () = Atomic.get closed in + + { Emitter.emit; closed; enabled; tick; flush_and_close } + in + + { + emit_spans = mk_emitter pp_span; + emit_logs = mk_emitter Proto.Logs.pp_log_record; + emit_metrics = mk_emitter Proto.Metrics.pp_metric; + on_tick = Cb_set.create (); + cleanup = (fun ~on_done () -> on_done ()); + }