Skip to content

Commit 77a3f1d

Browse files
avsmmtelvers
andcommitted
Move the Lwt logic out of the prometheus core
Complete the migration started in mirage#66 so the core no longer depends on Lwt. Libraries that only define and record metrics no longer need to pull in a concurrency library. Review suggestions from @talex5 Co-authored-by: Mark Elvers <mark.elvers@tunbury.org>
1 parent 30da687 commit 77a3f1d

14 files changed

Lines changed: 110 additions & 142 deletions

‎CHANGES.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
## dev
22

3+
- Remove Lwt from the `prometheus` core (@mtelvers @avsm #60 #65)
4+
5+
The deprecated Lwt-typed functions are gone and `CollectorRegistry.collect`
6+
now returns a snapshot directly. The Lwt collectors and timing helpers live
7+
in `prometheus-lwt`, whose interface is unchanged, so code that already
8+
migrated to `Prometheus_lwt` needs no further changes. Applications that
9+
collected via the core in an Lwt context should use
10+
`Prometheus_lwt.CollectorRegistry.collect`.
11+
312
- Add a new `prometheus-lwt` metrics package (@avsm @mtelvers @talex5 #66 #60 #65)
413

514
This release is not a breaking change, but instead prepares for

‎README.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ Unikernels can use `Prometheus_app` instead of `Prometheus_unix` to avoid the `U
7171

7272
The `prometheus-lwt` opam package provides `Prometheus_lwt` with collectors
7373
that may suspend before producing their samples, and also Lwt versions of the
74-
timing helpers.
74+
timing helpers.
75+
76+
The `prometheus` core does not depend on Lwt, so libraries that only define
77+
and record metrics do not pull in a concurrency library. Code that used the
78+
core's Lwt-typed functions should use `Prometheus_lwt`, or the synchronous
79+
variants such as `Gauge.set_time`.
7580

76-
A future release will remove Lwt from the `prometheus` core. Existing code
77-
using the core's Lwt-typed functions should migrate to `Prometheus_lwt`, or to
78-
the synchronous variants such as `Gauge.set_time` now. Code will then keep
79-
working unchanged when the core switch happens.
8081

8182
### API docs
8283

‎app/dune‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(library
22
(name prometheus_app)
33
(public_name prometheus-app)
4-
(libraries prometheus lwt cohttp-lwt fmt re)
4+
(libraries prometheus prometheus-lwt lwt cohttp-lwt fmt re)
55
(modules Prometheus_app)
66
(wrapped false))
77

‎app/prometheus_app.ml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ module Cohttp(Server : Cohttp_lwt.S.Server) = struct
148148
let uri = Request.uri req in
149149
match Request.meth req, Uri.path uri with
150150
| `GET, "/metrics" ->
151-
Prometheus.CollectorRegistry.(collect default) >>= fun data ->
151+
Prometheus_lwt.CollectorRegistry.(collect default) >>= fun data ->
152152
let body = Fmt.to_to_string TextFormat_0_0_4.output data in
153153
let headers = Header.init_with "Content-Type" "text/plain; version=0.0.4" in
154154
Server.respond_string ~status:`OK ~headers ~body ()

‎lwt/prometheus_lwt.ml‎

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,81 @@
1-
[@@@alert "-deprecated"]
1+
(* The Lwt collectors for Prometheus metrics. *)
2+
3+
open Prometheus
24

3-
(* This transition module reexports the core operations under their
4-
new names to allow the core package to drop the Lwt dependency
5-
in a future release. This interface will not change. *)
65
module CollectorRegistry = struct
7-
type t = Prometheus.CollectorRegistry.t
6+
type t = {
7+
core : Prometheus.CollectorRegistry.t;
8+
mutable metrics_lwt : (unit -> Sample_set.t LabelSetMap.t Lwt.t) MetricFamilyMap.t;
9+
mutable pre_collect_lwt : (unit -> unit Lwt.t) list;
10+
}
11+
12+
let of_registry core = {
13+
core;
14+
metrics_lwt = MetricFamilyMap.empty;
15+
pre_collect_lwt = [];
16+
}
17+
18+
let default = of_registry Prometheus.CollectorRegistry.default
819

9-
let of_registry core = core
20+
let core t = t.core
1021

11-
let default = Prometheus.CollectorRegistry.default
22+
let register_pre_collect t f = t.pre_collect_lwt <- f :: t.pre_collect_lwt
1223

13-
let core t = t
24+
let register t info collector =
25+
if MetricFamilyMap.mem info t.metrics_lwt then
26+
failwith (Format.asprintf "%a already registered" MetricName.pp info.MetricInfo.name);
27+
t.metrics_lwt <- MetricFamilyMap.add info collector t.metrics_lwt
1428

15-
let collect = Prometheus.CollectorRegistry.collect
29+
open Lwt.Infix
1630

17-
let register = Prometheus.CollectorRegistry.register_lwt
31+
let map_p m =
32+
MetricFamilyMap.fold (fun k f acc -> (k, f ()) :: acc) m []
33+
|> Lwt_list.fold_left_s
34+
(fun acc (k, v) -> v >|= fun v -> MetricFamilyMap.add k v acc)
35+
MetricFamilyMap.empty
1836

19-
let register_pre_collect = Prometheus.CollectorRegistry.register_pre_collect_lwt
37+
let collect t =
38+
Lwt_list.iter_p (fun f -> f ()) t.pre_collect_lwt >>= fun () ->
39+
let sync = Prometheus.CollectorRegistry.collect t.core in
40+
map_p t.metrics_lwt >|= fun metrics_lwt ->
41+
MetricFamilyMap.merge
42+
(fun _ v1 v2 ->
43+
match v1 with
44+
| Some v1 -> Some v1
45+
| None -> v2)
46+
sync metrics_lwt
2047
end
2148

2249
module Gauge = struct
23-
let track_in_progress = Prometheus.Gauge.track_inprogress
50+
let track_in_progress t fn =
51+
Prometheus.Gauge.inc_one t;
52+
Lwt.finalize fn (fun () -> Prometheus.Gauge.dec_one t; Lwt.return_unit)
2453

25-
let set_time = Prometheus.Gauge.time
54+
let set_time t gettimeofday fn =
55+
let start = gettimeofday () in
56+
Lwt.finalize fn
57+
(fun () ->
58+
let finish = gettimeofday () in
59+
Prometheus.Gauge.set t (finish -. start);
60+
Lwt.return_unit)
2661
end
2762

2863
module Summary = struct
29-
let observe_time = Prometheus.Summary.time
64+
let observe_time t gettimeofday fn =
65+
let start = gettimeofday () in
66+
Lwt.finalize fn
67+
(fun () ->
68+
let finish = gettimeofday () in
69+
Prometheus.Summary.observe t (finish -. start);
70+
Lwt.return_unit)
3071
end
3172

3273
module Histogram (H : Prometheus.HISTOGRAM) = struct
33-
let observe_time = H.time
74+
let observe_time t gettimeofday fn =
75+
let start = gettimeofday () in
76+
Lwt.finalize fn
77+
(fun () ->
78+
let finish = gettimeofday () in
79+
H.observe t (finish -. start);
80+
Lwt.return_unit)
3481
end

‎lwt/test/dune‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
(test
22
(name test_lwt)
3-
(package prometheus-lwt)
3+
(package prometheus-app)
44
(libraries prometheus prometheus-app prometheus-lwt alcotest alcotest-lwt lwt fmt))

‎prometheus-app.opam‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ depends: [
2828
"ocaml" {>= "4.11.0"}
2929
"dune" {>= "2.3"}
3030
"prometheus" {= version}
31+
"prometheus-lwt" {= version}
3132
"fmt" {>= "0.8.7"}
3233
"re"
3334
"cohttp-lwt" {>= "4.0.0"}

‎prometheus-lwt.opam‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ depends: [
1212
"dune" {>= "2.3"}
1313
"prometheus" {= version}
1414
"lwt" {>= "2.5.0"}
15-
"prometheus-app" {= version & with-test}
16-
"fmt" {>= "0.8.7" & with-test}
17-
"alcotest" {with-test}
18-
"alcotest-lwt" {with-test}
1915
]
2016
build: [
2117
["dune" "build" "-p" name "-j" jobs]

‎prometheus.opam‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ depends: [
1010
"ocaml" {>= "4.11.0"}
1111
"dune" {>= "2.3"}
1212
"re"
13-
"lwt" {>= "2.5.0"}
1413
]
1514
build: [
1615
["dune" "build" "-p" name "-j" jobs]

‎src/dune‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
(library
22
(name prometheus)
33
(public_name prometheus)
4-
(libraries lwt re))
4+
(libraries re))

0 commit comments

Comments
 (0)