metriki_r2d2/
lib.rs

1//! # Metriki Instrumentation for r2d2
2//!
3//! This library provides extensions for r2d2, which is generic
4//! database connection pool library, to measure performance for
5//! database applications.
6//!
7//! It provides following metriki metrics:
8//!
9//! * `r2d2.checkout`: A meter records the rate of your application
10//! borrowing connection from the pool
11//! * `r2d2.wait`: A histogram summarizes the distribution of time
12//! spent on borrowing connection from the pool
13//! * `r2d2.timeout`: A meter records the error rate of timeout
14//! borrowing connection
15//! * `r2d2.usage`: A histogram summarizes the distribution of time
16//! for using the connection. Typically this is the time spent to
17//! query your database.
18//!
19//! ## Usage
20//!
21//! Add MetrikiHandler as `r2d2::Builder`
22//!
23//! ```rust,ignore
24//! // Create metriki event handler from metriki global registry
25//! let metriki_handler = MetrikiHandlerBuilder::default()
26//!     .registry(global_registry())
27//!     .build()
28//!     .unwrap();
29//!
30//! let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
31//! let pool = r2d2::Pool::builder()
32//!     .max_size(15)
33//!     // set event handler to the builder
34//!     .event_handler(Box::new(metriki_handler))
35//!     .build(manager)
36//!     .unwrap();
37//! ```
38//!
39//! ## diesel Support
40//!
41//! The Rust ORM library diesel has an re-exported version of r2d2. By
42//! enabling `diesel` feature of `metriki-r2d2`, it will work with the
43//! diesel variant.
44//!
45//! ## Customization
46//!
47//! The metric name prefix `r2d2` can be customized with
48//! `MetrikiHandlerBuilder` by setting `name`. This is required when
49//! you have multiple r2d2 pools in your application.
50//!
51use std::sync::Arc;
52
53use derive_builder::Builder;
54#[cfg(not(feature = "diesel"))]
55use r2d2::{
56    event::{CheckinEvent, CheckoutEvent, TimeoutEvent},
57    HandleEvent,
58};
59
60#[cfg(feature = "diesel")]
61use diesel::r2d2::{
62    event::{CheckinEvent, CheckoutEvent, TimeoutEvent},
63    HandleEvent,
64};
65
66use metriki_core::MetricsRegistry;
67
68// The r2d2 EventHandler that tracks usage of the database connection
69// and its connection pool.
70#[derive(Debug, Builder)]
71pub struct MetrikiHandler {
72    registry: Arc<MetricsRegistry>,
73    #[builder(setter(into), default = "\"r2d2\".to_owned()")]
74    name: String,
75}
76
77impl HandleEvent for MetrikiHandler {
78    fn handle_checkout(&self, event: CheckoutEvent) {
79        self.registry
80            .meter(&format!("{}.checkout", self.name))
81            .mark();
82        self.registry
83            .histogram(&format!("{}.wait", self.name))
84            .update(event.duration().as_millis() as u64);
85    }
86
87    fn handle_timeout(&self, _event: TimeoutEvent) {
88        self.registry
89            .meter(&format!("{}.timeout", self.name))
90            .mark();
91    }
92
93    fn handle_checkin(&self, event: CheckinEvent) {
94        self.registry
95            .histogram(&format!("{}.usage", self.name))
96            .update(event.duration().as_millis() as u64);
97    }
98}