From 9218dce3d3d9c6280218275dbaaf0dbbe6720f65 Mon Sep 17 00:00:00 2001 From: Andrii Sultanov Date: Tue, 11 Mar 2025 08:46:19 +0000 Subject: [PATCH 1/2] prometheus: Add CollectorRegistry.unregister functions Sources of metrics can sometimes disappear at runtime (a VM being destroyed, disk being unplugged), and rather than continuing to present the last value, it is useful to remove them altogether. Other Prometheus client libraries do implement similar functions as well, see https://docs.rs/prometheus/latest/prometheus/struct.Registry.html#method.unregister for example. Signed-off-by: Andrii Sultanov --- src/prometheus.ml | 6 ++++++ src/prometheus.mli | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/prometheus.ml b/src/prometheus.ml index 7077824..0b47116 100644 --- a/src/prometheus.ml +++ b/src/prometheus.ml @@ -121,10 +121,16 @@ module CollectorRegistry = struct ensure_not_registered t info; t.metrics <- MetricFamilyMap.add info collector t.metrics + let unregister t info = + t.metrics <- MetricFamilyMap.remove info t.metrics + let register_lwt t info collector = ensure_not_registered t info; t.metrics_lwt <- MetricFamilyMap.add info collector t.metrics_lwt + let unregister_lwt t info = + t.metrics_lwt <- MetricFamilyMap.remove info t.metrics_lwt + open Lwt.Infix let map_p m = diff --git a/src/prometheus.mli b/src/prometheus.mli index c7c3d66..afed340 100644 --- a/src/prometheus.mli +++ b/src/prometheus.mli @@ -89,10 +89,16 @@ module CollectorRegistry : sig (** [register t metric collector] adds [metric] to the set of metrics being collected. It will call [collector ()] to collect the values each time [collect] is called. *) + val unregister : t -> MetricInfo.t -> unit + (** [unregister t metric] removes [metric] from the set of metrics being collected. *) + val register_lwt : t -> MetricInfo.t -> (unit -> Sample_set.t LabelSetMap.t Lwt.t) -> unit (** [register_lwt t metric collector] is the same as [register t metrics collector] but [collector] returns [Sample_set.t LabelSetMap.t Lwt.t]. *) + val unregister_lwt : t -> MetricInfo.t -> unit + (** [unregister_lwt t metric] removes [metric] from the set of metrics being collected. *) + val register_pre_collect : t -> (unit -> unit) -> unit (** [register_pre_collect t fn] arranges for [fn ()] to be called at the start of each collection. This is useful if one expensive call provides From d31682299e7b5e6d1ff58c5bc7a52fe6114dd67a Mon Sep 17 00:00:00 2001 From: Andrii Sultanov Date: Tue, 11 Mar 2025 13:59:47 +0000 Subject: [PATCH 2/2] prometheus: Add Metric.unregister_labels function to unregister a family's metric Signed-off-by: Andrii Sultanov --- src/prometheus.ml | 5 +++++ src/prometheus.mli | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/prometheus.ml b/src/prometheus.ml index 0b47116..be83f38 100644 --- a/src/prometheus.ml +++ b/src/prometheus.ml @@ -158,6 +158,7 @@ module type METRIC = sig type t val v_labels : label_names:string list -> ?registry:CollectorRegistry.t -> help:string -> ?namespace:string -> ?subsystem:string -> string -> family val labels : family -> string list -> t + val unregister_labels : family -> string list -> unit val v_label : label_name:string -> ?registry:CollectorRegistry.t -> help:string -> ?namespace:string -> ?subsystem:string -> string -> (string -> t) val v : ?registry:CollectorRegistry.t -> help:string -> ?namespace:string -> ?subsystem:string -> string -> t end @@ -203,6 +204,10 @@ end = struct t.children <- LabelSetMap.add label_values child t.children; child + let unregister_labels t label_values = + assert (List.length t.metric.MetricInfo.label_names = List.length label_values); + t.children <- LabelSetMap.remove label_values t.children + let v_label ~label_name ?registry ~help ?namespace ?subsystem name = let family = v_labels ~label_names:[label_name] ?registry ~help ?namespace ?subsystem name in fun x -> labels family [x] diff --git a/src/prometheus.mli b/src/prometheus.mli index afed340..eedae92 100644 --- a/src/prometheus.mli +++ b/src/prometheus.mli @@ -130,6 +130,12 @@ module type METRIC = sig you may wish to write a wrapper function with labelled arguments to avoid mistakes. If this is called multiple times with the same set of values, the existing metric will be returned. *) + val unregister_labels : family -> string list -> unit + (** [unregister_labels family label_values] unregisters the metric in [family] with these values + for the labels. The order of the values must be the same as the order of the [label_names] + passed to [v_labels]; you may wish to write a wrapper function with labelled arguments to + avoid mistakes. *) + val v_label : label_name:string -> ?registry:CollectorRegistry.t -> help:string -> ?namespace:string -> ?subsystem:string -> string -> (string -> t) (** [v_label] is a convenience wrapper around [v_labels] for the case where there is a single label. The result is a function from the single label's value to the metric. *)