Skip to content

Commit b5e3185

Browse files
authored
feat: add metrics (#17)
Signed-off-by: MrCroxx <[email protected]>
1 parent 80c40de commit b5e3185

File tree

4 files changed

+133
-26
lines changed

4 files changed

+133
-26
lines changed

foyer/src/container.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::collections::BTreeMap;
1616
use std::hash::Hasher;
1717

1818
use std::ptr::NonNull;
19+
use std::sync::Arc;
1920

2021
use futures::future::try_join_all;
2122
use itertools::Itertools;
@@ -24,7 +25,7 @@ use twox_hash::XxHash64;
2425

2526
use crate::policies::{Handle, Policy};
2627
use crate::store::Store;
27-
use crate::{Data, Index, WrappedNonNull};
28+
use crate::{Data, Index, Metrics, WrappedNonNull};
2829

2930
// TODO(MrCroxx): wrap own result type
3031
use crate::store::error::Result;
@@ -73,6 +74,8 @@ where
7374
{
7475
pool_count_bits: usize,
7576
pools: Vec<Mutex<Pool<I, P, H, D, S>>>,
77+
78+
metrics: Arc<Metrics>,
7679
}
7780

7881
impl<I, P, H, D, S> Container<I, P, H, D, S>
@@ -85,11 +88,20 @@ where
8588
S: Store<I = I, D = D>,
8689
{
8790
pub async fn open(config: Config<I, P, H, S>) -> Result<Self> {
91+
Self::open_with_registry(config, prometheus::Registry::new()).await
92+
}
93+
94+
pub async fn open_with_registry(
95+
config: Config<I, P, H, S>,
96+
registry: prometheus::Registry,
97+
) -> Result<Self> {
8898
let pool_count = 1 << config.pool_count_bits;
8999
let capacity = config.capacity >> config.pool_count_bits;
90100

101+
let metrics = Arc::new(Metrics::new(registry));
102+
91103
let stores = (0..pool_count)
92-
.map(|pool| S::open(pool, config.store_config.clone()))
104+
.map(|pool| S::open(pool, config.store_config.clone(), metrics.clone()))
93105
.collect_vec();
94106
let stores = try_join_all(stores).await?;
95107

@@ -103,17 +115,21 @@ where
103115
size: 0,
104116
handles: BTreeMap::new(),
105117
store,
118+
_metrics: metrics.clone(),
106119
})
107120
.map(Mutex::new)
108121
.collect_vec();
109122

110123
Ok(Self {
111124
pool_count_bits: config.pool_count_bits,
112125
pools,
126+
metrics,
113127
})
114128
}
115129

116130
pub async fn insert(&self, index: I, data: D) -> Result<bool> {
131+
let _timer = self.metrics.latency_insert.start_timer();
132+
117133
let mut pool = self.pool(&index).await;
118134

119135
if pool.handles.get(&index).is_some() {
@@ -131,6 +147,8 @@ where
131147
}
132148

133149
pub async fn remove(&self, index: &I) -> Result<bool> {
150+
let _timer = self.metrics.latency_remove.start_timer();
151+
134152
let mut pool = self.pool(index).await;
135153

136154
if pool.handles.get(index).is_none() {
@@ -144,9 +162,17 @@ where
144162
}
145163

146164
pub async fn get(&self, index: &I) -> Result<Option<D>> {
165+
let _timer = self.metrics.latency_get.start_timer();
166+
147167
let mut pool = self.pool(index).await;
148168

149-
pool.get(index).await
169+
let res = pool.get(index).await?;
170+
171+
if res.is_none() {
172+
self.metrics.miss.inc();
173+
}
174+
175+
Ok(res)
150176
}
151177

152178
// TODO(MrCroxx): optimize this
@@ -186,6 +212,8 @@ where
186212
handles: BTreeMap<I, PoolHandle<I, H>>,
187213

188214
store: S,
215+
216+
_metrics: Arc<Metrics>,
189217
}
190218

191219
impl<I, P, H, D, S> Pool<I, P, H, D, S>

foyer/src/metrics.rs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,30 @@
1313
// limitations under the License.
1414

1515
use prometheus::{
16-
register_counter_vec_with_registry, register_histogram_vec_with_registry,
17-
register_int_counter_with_registry, CounterVec, HistogramVec, IntCounter, Registry,
16+
register_counter_vec_with_registry, register_gauge_with_registry,
17+
register_histogram_vec_with_registry, register_int_counter_with_registry, Counter, CounterVec,
18+
Gauge, Histogram, HistogramVec, IntCounter, Registry,
1819
};
1920

2021
pub struct Metrics {
22+
pub latency_insert: Histogram,
23+
pub latency_get: Histogram,
24+
pub latency_remove: Histogram,
25+
26+
pub latency_store: Histogram,
27+
pub latency_load: Histogram,
28+
pub latency_delete: Histogram,
29+
30+
pub bytes_store: Counter,
31+
pub bytes_load: Counter,
32+
pub bytes_delete: Counter,
33+
34+
pub cache_data_size: Gauge,
35+
2136
pub miss: IntCounter,
2237

23-
pub latency: HistogramVec,
24-
pub bytes: CounterVec,
38+
_latency: HistogramVec,
39+
_bytes: CounterVec,
2540
}
2641

2742
impl Default for Metrics {
@@ -32,10 +47,6 @@ impl Default for Metrics {
3247

3348
impl Metrics {
3449
pub fn new(registry: Registry) -> Self {
35-
let miss =
36-
register_int_counter_with_registry!("foyer_cache_miss", "file cache miss", registry)
37-
.unwrap();
38-
3950
let latency = register_histogram_vec_with_registry!(
4051
"foyer_latency",
4152
"foyer latency",
@@ -52,10 +63,47 @@ impl Metrics {
5263
register_counter_vec_with_registry!("foyer_bytes", "foyer bytes", &["op"], registry)
5364
.unwrap();
5465

66+
let latency_insert = latency.with_label_values(&["insert"]);
67+
let latency_get = latency.with_label_values(&["get"]);
68+
let latency_remove = latency.with_label_values(&["remove"]);
69+
70+
let latency_store = latency.with_label_values(&["store"]);
71+
let latency_load = latency.with_label_values(&["load"]);
72+
let latency_delete = latency.with_label_values(&["delete"]);
73+
74+
let bytes_store = bytes.with_label_values(&["store"]);
75+
let bytes_load = bytes.with_label_values(&["load"]);
76+
let bytes_delete = bytes.with_label_values(&["delete"]);
77+
78+
let miss =
79+
register_int_counter_with_registry!("foyer_cache_miss", "foyer cache miss", registry)
80+
.unwrap();
81+
let cache_data_size = register_gauge_with_registry!(
82+
"foyer_cache_data_size",
83+
"foyer cache data size",
84+
registry
85+
)
86+
.unwrap();
87+
5588
Self {
89+
latency_insert,
90+
latency_get,
91+
latency_remove,
92+
93+
latency_store,
94+
latency_load,
95+
latency_delete,
96+
97+
bytes_store,
98+
bytes_load,
99+
bytes_delete,
100+
101+
cache_data_size,
102+
56103
miss,
57-
latency,
58-
bytes,
104+
105+
_latency: latency,
106+
_bytes: bytes,
59107
}
60108
}
61109
}

foyer/src/store/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ pub mod error;
1717
pub mod file;
1818
pub mod read_only_file_store;
1919

20-
use crate::{Data, Index};
20+
use std::sync::Arc;
21+
22+
use crate::{Data, Index, Metrics};
2123
use async_trait::async_trait;
2224

2325
use error::Result;
@@ -28,7 +30,7 @@ pub trait Store: Send + Sync + Sized + 'static {
2830
type D: Data;
2931
type C: Send + Sync + Clone + std::fmt::Debug + 'static;
3032

31-
async fn open(pool: usize, config: Self::C) -> Result<Self>;
33+
async fn open(pool: usize, config: Self::C, metrics: Arc<Metrics>) -> Result<Self>;
3234

3335
async fn store(&self, index: Self::I, data: Self::D) -> Result<()>;
3436

@@ -81,7 +83,7 @@ pub mod tests {
8183

8284
type C = ();
8385

84-
async fn open(_pool: usize, _: Self::C) -> Result<Self> {
86+
async fn open(_pool: usize, _: Self::C, _metrics: Arc<Metrics>) -> Result<Self> {
8587
Ok(Self::new())
8688
}
8789

foyer/src/store/read_only_file_store.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use itertools::Itertools;
2828
use rand::{thread_rng, Rng};
2929
use tokio::sync::{RwLock, RwLockWriteGuard};
3030

31-
use crate::{Data, Index};
31+
use crate::{Data, Index, Metrics};
3232

3333
use super::error::Result;
3434
use super::file::{AppendableFile, Location, ReadableFile, WritableFile};
@@ -102,6 +102,8 @@ where
102102

103103
size: Arc<AtomicUsize>,
104104

105+
metrics: Arc<Metrics>,
106+
105107
_marker: PhantomData<D>,
106108
}
107109

@@ -117,6 +119,7 @@ where
117119
indices: Arc::clone(&self.indices),
118120
files: Arc::clone(&self.files),
119121
size: Arc::clone(&self.size),
122+
metrics: Arc::clone(&self.metrics),
120123
_marker: PhantomData,
121124
}
122125
}
@@ -134,7 +137,7 @@ where
134137

135138
type C = Config;
136139

137-
async fn open(pool: usize, mut config: Self::C) -> Result<Self> {
140+
async fn open(pool: usize, mut config: Self::C, metrics: Arc<Metrics>) -> Result<Self> {
138141
config.dir = config.dir.join(format!("{:04}", pool));
139142

140143
let ids = asyncify({
@@ -182,12 +185,15 @@ where
182185
indices: Arc::new(RwLock::new(indices)),
183186
files: Arc::new(RwLock::new(files)),
184187
size: Arc::new(AtomicUsize::new(size)),
188+
metrics,
185189
_marker: PhantomData,
186190
})
187191
}
188192

189193
#[allow(clippy::uninit_vec)]
190194
async fn store(&self, index: Self::I, data: Self::D) -> Result<()> {
195+
let _timer = self.metrics.latency_store.start_timer();
196+
191197
// append cache file and meta file
192198
let (fid, sid, location) = {
193199
// randomly drop if size exceeds the threshold
@@ -234,8 +240,13 @@ where
234240
drop(indices);
235241
}
236242

237-
self.size
238-
.fetch_add(location.len as usize, Ordering::Relaxed);
243+
let cache_data_size = self
244+
.size
245+
.fetch_add(location.len as usize, Ordering::Relaxed)
246+
+ location.len as usize;
247+
248+
self.metrics.bytes_store.inc_by(location.len as f64);
249+
self.metrics.cache_data_size.set(cache_data_size as f64);
239250

240251
if active_file_size >= self.config.max_file_size {
241252
let files = self.files.write().await;
@@ -251,6 +262,8 @@ where
251262
}
252263

253264
async fn load(&self, index: &Self::I) -> Result<Option<Self::D>> {
265+
let _timer = self.metrics.latency_load.start_timer();
266+
254267
// TODO(MrCroxx): add bloom filters ?
255268
let (fid, _sid, location) = {
256269
let indices = self.indices.read().await;
@@ -283,12 +296,16 @@ where
283296
}
284297
};
285298

299+
self.metrics.bytes_load.inc_by(location.len as f64);
300+
286301
self.maybe_trigger_reclaim().await?;
287302

288303
Ok(Some(buf.into()))
289304
}
290305

291306
async fn delete(&self, index: &Self::I) -> Result<()> {
307+
let _timer = self.metrics.latency_delete.start_timer();
308+
292309
let (fid, sid, location) = {
293310
let indices = self.indices.read().await;
294311
let (fid, sid, location) = match indices.get(index) {
@@ -318,8 +335,13 @@ where
318335
}
319336
}
320337

321-
self.size
322-
.fetch_sub(location.len as usize, Ordering::Relaxed);
338+
let cache_data_size = self
339+
.size
340+
.fetch_sub(location.len as usize, Ordering::Relaxed)
341+
- location.len as usize;
342+
343+
self.metrics.bytes_delete.inc_by(location.len as f64);
344+
self.metrics.cache_data_size.set(cache_data_size as f64);
323345

324346
self.maybe_trigger_reclaim().await?;
325347

@@ -376,7 +398,8 @@ where
376398
size as usize
377399
};
378400

379-
self.size.fetch_sub(size, Ordering::Relaxed);
401+
let cache_data_size = self.size.fetch_sub(size, Ordering::Relaxed) - size;
402+
self.metrics.cache_data_size.set(cache_data_size as f64);
380403

381404
meta_file.reclaim().await?;
382405
cache_file.reclaim().await?;
@@ -520,7 +543,9 @@ mod tests {
520543
};
521544

522545
let store: ReadOnlyFileStore<u64, Vec<u8>> =
523-
ReadOnlyFileStore::open(0, config).await.unwrap();
546+
ReadOnlyFileStore::open(0, config, Arc::new(Metrics::default()))
547+
.await
548+
.unwrap();
524549

525550
store.store(1, data(1, 1024)).await.unwrap();
526551
assert_eq!(store.load(&1).await.unwrap(), Some(data(1, 1024)));
@@ -572,7 +597,9 @@ mod tests {
572597
};
573598

574599
let store: ReadOnlyFileStore<u64, Vec<u8>> =
575-
ReadOnlyFileStore::open(0, config.clone()).await.unwrap();
600+
ReadOnlyFileStore::open(0, config.clone(), Arc::new(Metrics::default()))
601+
.await
602+
.unwrap();
576603

577604
for i in 0..20 {
578605
store.store(i, data(i as u8, 1024)).await.unwrap();
@@ -589,7 +616,9 @@ mod tests {
589616
drop(store);
590617

591618
let store: ReadOnlyFileStore<u64, Vec<u8>> =
592-
ReadOnlyFileStore::open(0, config).await.unwrap();
619+
ReadOnlyFileStore::open(0, config, Arc::new(Metrics::default()))
620+
.await
621+
.unwrap();
593622

594623
assert_eq!(store.files.read().await.frozens.len(), 3);
595624
for i in 0..12 {

0 commit comments

Comments
 (0)