1use crate::{register_meter_with_group, Meter};
6use parking_lot::{
7 Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
8};
9use std::{
10 ops::{Deref, DerefMut},
11 sync::Arc,
12 time::Instant,
13};
14
15pub struct Lock {
17 acquire_tps: Arc<dyn Meter>, wait_time: Arc<dyn Meter>, hold_time: Arc<dyn Meter>, }
21
22impl Lock {
23 pub fn register(name: &str) -> Self {
24 Lock {
25 acquire_tps: register_meter_with_group(name, "acquires"),
26 wait_time: register_meter_with_group(name, "wait_t"),
27 hold_time: register_meter_with_group(name, "hold_t"),
28 }
29 }
30}
31
32pub trait MutexExtensions<T> {
33 fn lock_with_metric(&self, metric: &Lock) -> MutexGuardWithMetrics<'_, T>;
34}
35
36impl<T> MutexExtensions<T> for Mutex<T> {
37 fn lock_with_metric(&self, metric: &Lock) -> MutexGuardWithMetrics<'_, T> {
38 metric.acquire_tps.mark(1);
39 let start = Instant::now();
40 let guard = self.lock();
41 metric.wait_time.mark(start.elapsed().as_nanos() as usize);
42 MutexGuardWithMetrics::new(guard, metric.hold_time.clone())
43 }
44}
45
46pub trait RwLockExtensions<T> {
47 fn read_with_metric(
48 &self, metric: &Lock,
49 ) -> RwLockReadGuardWithMetrics<'_, T>;
50 fn write_with_metric(
51 &self, metric: &Lock,
52 ) -> RwLockWriteGuardWithMetrics<'_, T>;
53}
54
55impl<T> RwLockExtensions<T> for RwLock<T> {
56 fn read_with_metric(
57 &self, metric: &Lock,
58 ) -> RwLockReadGuardWithMetrics<'_, T> {
59 metric.acquire_tps.mark(1);
60 let start = Instant::now();
61 let guard = self.read();
62 metric.wait_time.mark(start.elapsed().as_nanos() as usize);
63 RwLockReadGuardWithMetrics::new(guard, metric.hold_time.clone())
64 }
65
66 fn write_with_metric(
67 &self, metric: &Lock,
68 ) -> RwLockWriteGuardWithMetrics<'_, T> {
69 metric.acquire_tps.mark(1);
70 let start = Instant::now();
71 let guard = self.write();
72 metric.wait_time.mark(start.elapsed().as_nanos() as usize);
73 RwLockWriteGuardWithMetrics::new(guard, metric.hold_time.clone())
74 }
75}
76
77pub type MutexGuardWithMetrics<'a, T> = LockGuard<MutexGuard<'a, T>>;
78pub type RwLockReadGuardWithMetrics<'a, T> = LockGuard<RwLockReadGuard<'a, T>>;
79pub type RwLockWriteGuardWithMetrics<'a, T> =
80 LockGuard<RwLockWriteGuard<'a, T>>;
81
82pub struct LockGuard<GUARD> {
83 raw: GUARD,
84 start: Instant,
85 lock_hold_time: Arc<dyn Meter>,
86}
87
88impl<GUARD> LockGuard<GUARD> {
89 fn new(raw: GUARD, lock_hold_time: Arc<dyn Meter>) -> Self {
90 LockGuard {
91 raw,
92 start: Instant::now(),
93 lock_hold_time,
94 }
95 }
96}
97
98impl<GUARD> Drop for LockGuard<GUARD> {
99 fn drop(&mut self) {
100 let elapsed_nano = self.start.elapsed().as_nanos() as usize;
101 self.lock_hold_time.mark(elapsed_nano);
102 }
103}
104
105impl<T, GUARD: Deref<Target = T>> Deref for LockGuard<GUARD> {
106 type Target = T;
107
108 fn deref(&self) -> &T { &self.raw }
109}
110
111impl<T, GUARD: DerefMut<Target = T>> DerefMut for LockGuard<GUARD> {
112 fn deref_mut(&mut self) -> &mut T { &mut self.raw }
113}