From 3589e3c4ab5680e19df6756b6ccb68be2ad73122 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 18:20:07 +0100 Subject: [PATCH 01/15] Insertion of the first version of the code. --- Cargo.lock | 1 + linera-views/Cargo.toml | 1 + linera-views/src/lib.rs | 3 + linera-views/src/metered_wrapper.rs | 156 ++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 linera-views/src/metered_wrapper.rs diff --git a/Cargo.lock b/Cargo.lock index 6d36105630ef..632c9343164f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3542,6 +3542,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bcs", + "convert_case 0.6.0", "futures", "generic-array", "hex", diff --git a/linera-views/Cargo.toml b/linera-views/Cargo.toml index a2be0d7260cb..f3fa912ff391 100644 --- a/linera-views/Cargo.toml +++ b/linera-views/Cargo.toml @@ -22,6 +22,7 @@ db_timings = [] metrics = ["dep:hex"] [dependencies] +convert_case = { workspace = true } anyhow = { workspace = true } async-graphql = { workspace = true } async-lock = { workspace = true } diff --git a/linera-views/src/lib.rs b/linera-views/src/lib.rs index 5e030069d87a..50b3d4ef7cf5 100644 --- a/linera-views/src/lib.rs +++ b/linera-views/src/lib.rs @@ -62,6 +62,9 @@ pub mod common; /// The code to turn a `DirectKeyValueStore` into a `KeyValueStore` by adding journaling. pub mod journaling; +/// The code for encapsulating one key_value store into another that does metric +pub mod metered_wrapper; + /// The code for handling big values by splitting them into several small ones. pub mod value_splitting; diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs new file mode 100644 index 000000000000..b3e5b7dd9d4f --- /dev/null +++ b/linera-views/src/metered_wrapper.rs @@ -0,0 +1,156 @@ +// Copyright (c) Zefchain Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//use std::time::{Duration, Instant}; +//use linera_base::sync::Lazy; +use convert_case::{Case, Casing}; +use prometheus::HistogramVec; +use prometheus::register_histogram_vec; +use crate::common::KeyValueStore; +use async_trait::async_trait; +use std::future::Future; +use std::time::{Instant}; +use crate::common::ReadableKeyValueStore; +use crate::common::WritableKeyValueStore; +use crate::batch::Batch; + +#[derive(Clone)] +struct MeteredCounter { + read_value_bytes: HistogramVec, + contains_key: HistogramVec, + read_multi_values_bytes: HistogramVec, + find_keys_by_prefix: HistogramVec, + find_key_values_by_prefix: HistogramVec, + write_batch: HistogramVec, + clear_journal: HistogramVec, +} + + +impl MeteredCounter { + fn new(name: String) -> Self { + // name can be "rocks db". Then var_name = "rocks_db" and title_name = "RocksDb" + let var_name = name.replace(" ", "_"); + let title_name = name.to_case(Case::Snake); + + let read_value1 = format!("{}_read_value_bytes", var_name); + let read_value2 = format!("{} read value bytes", title_name); + let read_value_bytes = register_histogram_vec!(read_value1, read_value2, &[]) + .expect("Counter creation should not fail"); + + let contains_key1 = format!("{}_contains_key", var_name); + let contains_key2 = format!("{} contains key", title_name); + let contains_key = register_histogram_vec!(contains_key1, contains_key2, &[]) + .expect("Counter creation should not fail"); + + let read_multi_values1 = format!("{}_read_multi_value_bytes", var_name); + let read_multi_values2 = format!("{} read multi value bytes", title_name); + let read_multi_values_bytes = register_histogram_vec!(read_multi_values1, read_multi_values2, &[]) + .expect("Counter creation should not fail"); + + let find_keys1 = format!("{}_find_keys_by_prefix", var_name); + let find_keys2 = format!("{} find keys by prefix", title_name); + let find_keys_by_prefix = register_histogram_vec!(find_keys1, find_keys2, &[]) + .expect("Counter creation should not fail"); + + let find_key_values1 = format!("{}_find_key_values_by_prefix", var_name); + let find_key_values2 = format!("{} find key values by prefix", title_name); + let find_key_values_by_prefix = register_histogram_vec!(find_key_values1, find_key_values2, &[]) + .expect("Counter creation should not fail"); + + let write_batch1 = format!("{}_write_batch", var_name); + let write_batch2 = format!("{} write batch", title_name); + let write_batch = register_histogram_vec!(write_batch1, write_batch2, &[]) + .expect("Counter creation should not fail"); + + let clear_journal1 = format!("{}_clear_journal", var_name); + let clear_journal2 = format!("{} clear journal", title_name); + let clear_journal = register_histogram_vec!(clear_journal1, clear_journal2, &[]) + .expect("Counter creation should not fail"); + + MeteredCounter { read_value_bytes, contains_key, read_multi_values_bytes, find_keys_by_prefix, find_key_values_by_prefix, write_batch, clear_journal } + } +} + +#[derive(Clone)] +struct MeteredStore { + /// the metrics being stored + pub counter: MeteredCounter, + /// The underlying store of the metered store + pub store: K, +} + +async fn prometheus_async(f: F, hist: &HistogramVec) -> O +where + F: Future, +{ + let start = Instant::now(); + let out = f.await; + let duration = start.elapsed(); + hist.with_label_values(&[]) + .observe(duration.as_micros() as f64); + out +} + + +#[async_trait] +impl ReadableKeyValueStore for MeteredStore +where + K: KeyValueStore + Send + Sync, +{ + const MAX_KEY_SIZE: usize = K::MAX_KEY_SIZE; + type Keys = K::Keys; + type KeyValues = K::KeyValues; + + fn max_stream_queries(&self) -> usize { + self.store.max_stream_queries() + } + + async fn read_value_bytes(&self, key: &[u8]) -> Result>, K::Error> { + prometheus_async(self.store.read_value_bytes(key), &self.counter.read_value_bytes).await + } + + async fn contains_key(&self, key: &[u8]) -> Result { + prometheus_async(self.store.contains_key(key), &self.counter.contains_key).await + } + + async fn read_multi_values_bytes( + &self, + keys: Vec>, + ) -> Result>>, K::Error> { + prometheus_async(self.store.read_multi_values_bytes(keys), &self.counter.read_multi_values_bytes).await + } + + async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result { + prometheus_async(self.store.find_keys_by_prefix(key_prefix), &self.counter.find_keys_by_prefix).await + } + + async fn find_key_values_by_prefix( + &self, + key_prefix: &[u8], + ) -> Result { + prometheus_async(self.store.find_key_values_by_prefix(key_prefix), &self.counter.find_key_values_by_prefix).await + } +} + +#[async_trait] +impl WritableKeyValueStore for MeteredStore +where + K: KeyValueStore + Send + Sync, +{ + const MAX_VALUE_SIZE: usize = K::MAX_VALUE_SIZE; + + async fn write_batch(&self, batch: Batch, base_key: &[u8]) -> Result<(), K::Error> { + prometheus_async(self.store.write_batch(batch, base_key), &self.counter.write_batch).await + } + + async fn clear_journal(&self, base_key: &[u8]) -> Result<(), K::Error> { + prometheus_async(self.store.clear_journal(base_key), &self.counter.clear_journal).await + } +} + +impl KeyValueStore for MeteredStore +where + K: KeyValueStore + Send + Sync, +{ + type Error = K::Error; +} From d1e0f518a7ec0f73f24fc9e35a8d0a90e7479037 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 19:03:12 +0100 Subject: [PATCH 02/15] Generalize a little bit the code. --- linera-views/src/metered_wrapper.rs | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index b3e5b7dd9d4f..f859cd8b80be 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -13,6 +13,7 @@ use std::time::{Instant}; use crate::common::ReadableKeyValueStore; use crate::common::WritableKeyValueStore; use crate::batch::Batch; +use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] struct MeteredCounter { @@ -25,9 +26,8 @@ struct MeteredCounter { clear_journal: HistogramVec, } - impl MeteredCounter { - fn new(name: String) -> Self { + pub fn new(name: String) -> Self { // name can be "rocks db". Then var_name = "rocks_db" and title_name = "RocksDb" let var_name = name.replace(" ", "_"); let title_name = name.to_case(Case::Snake); @@ -93,9 +93,9 @@ where #[async_trait] -impl ReadableKeyValueStore for MeteredStore +impl ReadableKeyValueStore for MeteredStore where - K: KeyValueStore + Send + Sync, + K: ReadableKeyValueStore + Send + Sync, { const MAX_KEY_SIZE: usize = K::MAX_KEY_SIZE; type Keys = K::Keys; @@ -105,45 +105,45 @@ where self.store.max_stream_queries() } - async fn read_value_bytes(&self, key: &[u8]) -> Result>, K::Error> { + async fn read_value_bytes(&self, key: &[u8]) -> Result>, E> { prometheus_async(self.store.read_value_bytes(key), &self.counter.read_value_bytes).await } - async fn contains_key(&self, key: &[u8]) -> Result { + async fn contains_key(&self, key: &[u8]) -> Result { prometheus_async(self.store.contains_key(key), &self.counter.contains_key).await } async fn read_multi_values_bytes( &self, keys: Vec>, - ) -> Result>>, K::Error> { + ) -> Result>>, E> { prometheus_async(self.store.read_multi_values_bytes(keys), &self.counter.read_multi_values_bytes).await } - async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result { + async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result { prometheus_async(self.store.find_keys_by_prefix(key_prefix), &self.counter.find_keys_by_prefix).await } async fn find_key_values_by_prefix( &self, key_prefix: &[u8], - ) -> Result { + ) -> Result { prometheus_async(self.store.find_key_values_by_prefix(key_prefix), &self.counter.find_key_values_by_prefix).await } } #[async_trait] -impl WritableKeyValueStore for MeteredStore +impl WritableKeyValueStore for MeteredStore where - K: KeyValueStore + Send + Sync, + K: WritableKeyValueStore + Send + Sync, { const MAX_VALUE_SIZE: usize = K::MAX_VALUE_SIZE; - async fn write_batch(&self, batch: Batch, base_key: &[u8]) -> Result<(), K::Error> { + async fn write_batch(&self, batch: Batch, base_key: &[u8]) -> Result<(), E> { prometheus_async(self.store.write_batch(batch, base_key), &self.counter.write_batch).await } - async fn clear_journal(&self, base_key: &[u8]) -> Result<(), K::Error> { + async fn clear_journal(&self, base_key: &[u8]) -> Result<(), E> { prometheus_async(self.store.clear_journal(base_key), &self.counter.clear_journal).await } } @@ -154,3 +154,11 @@ where { type Error = K::Error; } + +impl MeteredStore { + pub fn new(name: String, store: K) -> Self { + let counter = MeteredCounter::new(name); + Self { counter, store } + } +} + From e35beebbde07b2c4c0854209859cc42702520961 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 19:26:50 +0100 Subject: [PATCH 03/15] Introduce the metering software in DynamoDb. --- linera-views/src/dynamo_db.rs | 36 +++++++++++++++++++++-------- linera-views/src/lib.rs | 1 + linera-views/src/metered_wrapper.rs | 4 +++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index 8016bdd12b4c..4d3b64821b6d 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -40,6 +40,10 @@ use linera_base::ensure; use std::{collections::HashMap, env, str::FromStr, sync::Arc}; use thiserror::Error; +#[cfg(feature = "metrics")] +use crate::metered_wrapper::MeteredStore; + + #[cfg(any(test, feature = "test"))] use { crate::lru_caching::TEST_CACHE_SIZE, @@ -945,6 +949,9 @@ impl DirectKeyValueStore for DynamoDbStoreInternal { /// A shared DB client for DynamoDb implementing LruCaching #[derive(Clone)] pub struct DynamoDbStore { + #[cfg(feature = "metrics")] + store: MeteredStore>>>>>, + #[cfg(not(feature = "metrics"))] store: LruCachingStore>>, } @@ -1007,6 +1014,23 @@ impl KeyValueStore for DynamoDbStore { } impl DynamoDbStore { + #[cfg(not(feature = "metrics"))] + fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + let store = ValueSplittingStore::new(store); + let store = LruCachingStore::new(store, cache_size); + Self { store } + } + + #[cfg(feature = "metrics")] + fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + let store = MeteredStore::new("DynamoDbInternal".to_string(), store); + let store = ValueSplittingStore::new(store); + let store = MeteredStore::new("ValueSplitting".to_string(), store); + let store = LruCachingStore::new(store, cache_size); + let store = MeteredStore::new("LruCaching".to_string(), store); + Self { store } + } + /// Creates a `DynamoDbStore` from scratch with an LRU cache #[cfg(any(test, feature = "test"))] pub async fn new_for_testing( @@ -1016,9 +1040,7 @@ impl DynamoDbStore { let (simple_store, table_status) = DynamoDbStoreInternal::new_for_testing(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = ValueSplittingStore::new(store); - let store = LruCachingStore::new(store, cache_size); - let store = Self { store }; + let store = Self::get_complete_store(store, cache_size); Ok((store, table_status)) } @@ -1029,9 +1051,7 @@ impl DynamoDbStore { let cache_size = store_config.common_config.cache_size; let simple_store = DynamoDbStoreInternal::initialize(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = ValueSplittingStore::new(store); - let store = LruCachingStore::new(store, cache_size); - let store = Self { store }; + let store = Self::get_complete_store(store, cache_size); Ok(store) } @@ -1068,9 +1088,7 @@ impl DynamoDbStore { let cache_size = store_config.common_config.cache_size; let (simple_store, table_name) = DynamoDbStoreInternal::new(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = ValueSplittingStore::new(store); - let store = LruCachingStore::new(store, cache_size); - let store = Self { store }; + let store = Self::get_complete_store(store, cache_size); Ok((store, table_name)) } } diff --git a/linera-views/src/lib.rs b/linera-views/src/lib.rs index 50b3d4ef7cf5..0fd1c8ad9501 100644 --- a/linera-views/src/lib.rs +++ b/linera-views/src/lib.rs @@ -63,6 +63,7 @@ pub mod common; pub mod journaling; /// The code for encapsulating one key_value store into another that does metric +#[cfg(feature = "metrics")] pub mod metered_wrapper; /// The code for handling big values by splitting them into several small ones. diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index f859cd8b80be..0caecab4af6b 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -71,8 +71,9 @@ impl MeteredCounter { } } +/// A metered wrapper that keeps track of every operation #[derive(Clone)] -struct MeteredStore { +pub struct MeteredStore { /// the metrics being stored pub counter: MeteredCounter, /// The underlying store of the metered store @@ -156,6 +157,7 @@ where } impl MeteredStore { + /// Creates a new Metered store pub fn new(name: String, store: K) -> Self { let counter = MeteredCounter::new(name); Self { counter, store } From 7c0e3584348eb611e9c8ce32e40dd4589e30d43c Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 20:26:26 +0100 Subject: [PATCH 04/15] Some corrections + adding the support for the rocksdb/scylladb. --- linera-views/src/metered_wrapper.rs | 4 ++-- linera-views/src/rocks_db.rs | 28 +++++++++++++++++++--- linera-views/src/scylla_db.rs | 36 ++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index 0caecab4af6b..4d64be69f5fe 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -13,7 +13,7 @@ use std::time::{Instant}; use crate::common::ReadableKeyValueStore; use crate::common::WritableKeyValueStore; use crate::batch::Batch; -use crate::journaling::DirectWritableKeyValueStore; +//use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] struct MeteredCounter { @@ -75,7 +75,7 @@ impl MeteredCounter { #[derive(Clone)] pub struct MeteredStore { /// the metrics being stored - pub counter: MeteredCounter, + counter: MeteredCounter, /// The underlying store of the metered store pub store: K, } diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index 0e4a5e1803a9..eacc22e23286 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -19,6 +19,10 @@ use std::{ sync::Arc, }; use thiserror::Error; + +#[cfg(feature = "metrics")] +use crate::metered_wrapper::MeteredStore; + #[cfg(any(test, feature = "test"))] use {crate::lru_caching::TEST_CACHE_SIZE, tempfile::TempDir}; @@ -231,6 +235,9 @@ impl KeyValueStore for RocksDbStoreInternal { /// A shared DB client for RocksDB implementing LruCaching #[derive(Clone)] pub struct RocksDbStore { + #[cfg(feature = "metrics")] + store: MeteredStore>>>>, + #[cfg(not(feature = "metrics"))] store: LruCachingStore>, } @@ -295,6 +302,23 @@ impl RocksDbStore { Ok(client) } + #[cfg(not(feature = "metrics"))] + fn get_complete_store(store: RocksDbStoreInternal, cache_size: usize) -> Self { + let store = ValueSplittingStore::new(store); + let store = LruCachingStore::new(store, cache_size); + Self { store } + } + + #[cfg(feature = "metrics")] + fn get_complete_store(store: RocksDbStoreInternal, cache_size: usize) -> Self { + let store = MeteredStore::new("RocksDbInternal".to_string(), store); + let store = ValueSplittingStore::new(store); + let store = MeteredStore::new("ValueSplitting".to_string(), store); + let store = LruCachingStore::new(store, cache_size); + let store = MeteredStore::new("LruCaching".to_string(), store); + Self { store } + } + /// Creates a RocksDB database from a specified path. async fn new_internal( store_config: RocksDbStoreConfig, @@ -328,9 +352,7 @@ impl RocksDbStore { db: Arc::new(db), max_stream_queries, }; - let store = ValueSplittingStore::new(store); - let store = LruCachingStore::new(store, cache_size); - let store = Self { store }; + let store = Self::get_complete_store(store, cache_size); Ok((store, table_status)) } } diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index 5af23e9dba31..d6905c440324 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -15,6 +15,9 @@ //! [trait1]: common::KeyValueStore //! [trait2]: common::Context +#[cfg(feature = "metrics")] +use crate::metered_wrapper::MeteredStore; + #[cfg(any(test, feature = "test"))] use crate::{lru_caching::TEST_CACHE_SIZE, test_utils::get_table_name}; @@ -673,6 +676,9 @@ impl ScyllaDbStoreInternal { /// A shared DB store for ScyllaDB implementing LruCaching #[derive(Clone)] pub struct ScyllaDbStore { + #[cfg(feature = "metrics")] + store: MeteredStore>>>, + #[cfg(not(feature = "metrics"))] store: LruCachingStore>, } @@ -749,10 +755,31 @@ impl KeyValueStore for ScyllaDbStore { impl ScyllaDbStore { /// Gets the table name of the ScyllaDB store. + #[cfg(not(feature = "metrics"))] pub async fn get_table_name(&self) -> String { self.store.store.store.get_table_name().await } + /// Gets the table name of the ScyllaDB store. + #[cfg(feature = "metrics")] + pub async fn get_table_name(&self) -> String { + self.store.store.store.store.store.get_table_name().await + } + + #[cfg(not(feature = "metrics"))] + fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + let store = LruCachingStore::new(store, cache_size); + Self { store } + } + + #[cfg(feature = "metrics")] + fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + let store = MeteredStore::new("DynamoDbInternal".to_string(), store); + let store = LruCachingStore::new(store, cache_size); + let store = MeteredStore::new("LruCaching".to_string(), store); + Self { store } + } + /// Creates a [`ScyllaDbStore`] from the input parameters. #[cfg(any(test, feature = "test"))] pub async fn new_for_testing( @@ -762,8 +789,7 @@ impl ScyllaDbStore { let (simple_store, table_status) = ScyllaDbStoreInternal::new_for_testing(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = LruCachingStore::new(store, cache_size); - let store = ScyllaDbStore { store }; + let store = Self::get_complete_store(store, cache_size); Ok((store, table_status)) } @@ -774,8 +800,7 @@ impl ScyllaDbStore { let cache_size = store_config.common_config.cache_size; let simple_store = ScyllaDbStoreInternal::initialize(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = LruCachingStore::new(store, cache_size); - let store = ScyllaDbStore { store }; + let store = Self::get_complete_store(store, cache_size); Ok(store) } @@ -812,8 +837,7 @@ impl ScyllaDbStore { let cache_size = store_config.common_config.cache_size; let (simple_store, table_status) = ScyllaDbStoreInternal::new(store_config).await?; let store = JournalingKeyValueStore::new(simple_store); - let store = LruCachingStore::new(store, cache_size); - let store = ScyllaDbStore { store }; + let store = Self::get_complete_store(store, cache_size); Ok((store, table_status)) } } From 340560113ac6308eaa2415240477615e05e51d58 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 21:16:54 +0100 Subject: [PATCH 05/15] Renaming. --- linera-views/src/dynamo_db.rs | 6 +++--- linera-views/src/rocks_db.rs | 6 +++--- linera-views/src/scylla_db.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index 4d3b64821b6d..8441a361a0c6 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -1023,11 +1023,11 @@ impl DynamoDbStore { #[cfg(feature = "metrics")] fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { - let store = MeteredStore::new("DynamoDbInternal".to_string(), store); + let store = MeteredStore::new("dynamo db internal".to_string(), store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new("ValueSplitting".to_string(), store); + let store = MeteredStore::new("value splitting".to_string(), store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("LruCaching".to_string(), store); + let store = MeteredStore::new("lru caching".to_string(), store); Self { store } } diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index eacc22e23286..5d32861a77ce 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -311,11 +311,11 @@ impl RocksDbStore { #[cfg(feature = "metrics")] fn get_complete_store(store: RocksDbStoreInternal, cache_size: usize) -> Self { - let store = MeteredStore::new("RocksDbInternal".to_string(), store); + let store = MeteredStore::new("rocks db internal".to_string(), store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new("ValueSplitting".to_string(), store); + let store = MeteredStore::new("value splitting".to_string(), store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("LruCaching".to_string(), store); + let store = MeteredStore::new("lru caching".to_string(), store); Self { store } } diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index d6905c440324..ca992edaff84 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -774,9 +774,9 @@ impl ScyllaDbStore { #[cfg(feature = "metrics")] fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { - let store = MeteredStore::new("DynamoDbInternal".to_string(), store); + let store = MeteredStore::new("scylla db internal".to_string(), store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("LruCaching".to_string(), store); + let store = MeteredStore::new("lru caching".to_string(), store); Self { store } } From a3e5810c535c19f5948e500a1f660af8f3be78c0 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Wed, 17 Jan 2024 21:36:01 +0100 Subject: [PATCH 06/15] Reformatting. --- linera-views/src/dynamo_db.rs | 20 +++++-- linera-views/src/metered_wrapper.rs | 86 ++++++++++++++++++----------- linera-views/src/rocks_db.rs | 8 ++- linera-views/src/scylla_db.rs | 19 +++++-- 4 files changed, 89 insertions(+), 44 deletions(-) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index 8441a361a0c6..0e175a5a0d50 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -43,7 +43,6 @@ use thiserror::Error; #[cfg(feature = "metrics")] use crate::metered_wrapper::MeteredStore; - #[cfg(any(test, feature = "test"))] use { crate::lru_caching::TEST_CACHE_SIZE, @@ -948,9 +947,16 @@ impl DirectKeyValueStore for DynamoDbStoreInternal { /// A shared DB client for DynamoDb implementing LruCaching #[derive(Clone)] +#[allow(clippy::type_complexity)] pub struct DynamoDbStore { #[cfg(feature = "metrics")] - store: MeteredStore>>>>>, + store: MeteredStore< + LruCachingStore< + MeteredStore< + ValueSplittingStore>>, + >, + >, + >, #[cfg(not(feature = "metrics"))] store: LruCachingStore>>, } @@ -1015,14 +1021,20 @@ impl KeyValueStore for DynamoDbStore { impl DynamoDbStore { #[cfg(not(feature = "metrics"))] - fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + fn get_complete_store( + store: JournalingKeyValueStore, + cache_size: usize, + ) -> Self { let store = ValueSplittingStore::new(store); let store = LruCachingStore::new(store, cache_size); Self { store } } #[cfg(feature = "metrics")] - fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { + fn get_complete_store( + store: JournalingKeyValueStore, + cache_size: usize, + ) -> Self { let store = MeteredStore::new("dynamo db internal".to_string(), store); let store = ValueSplittingStore::new(store); let store = MeteredStore::new("value splitting".to_string(), store); diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index 4d64be69f5fe..fa37092889d7 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -3,16 +3,14 @@ //use std::time::{Duration, Instant}; //use linera_base::sync::Lazy; -use convert_case::{Case, Casing}; -use prometheus::HistogramVec; -use prometheus::register_histogram_vec; -use crate::common::KeyValueStore; +use crate::{ + batch::Batch, + common::{KeyValueStore, ReadableKeyValueStore, WritableKeyValueStore}, +}; use async_trait::async_trait; -use std::future::Future; -use std::time::{Instant}; -use crate::common::ReadableKeyValueStore; -use crate::common::WritableKeyValueStore; -use crate::batch::Batch; +use convert_case::{Case, Casing}; +use prometheus::{register_histogram_vec, HistogramVec}; +use std::{future::Future, time::Instant}; //use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] @@ -29,7 +27,7 @@ struct MeteredCounter { impl MeteredCounter { pub fn new(name: String) -> Self { // name can be "rocks db". Then var_name = "rocks_db" and title_name = "RocksDb" - let var_name = name.replace(" ", "_"); + let var_name = name.replace(' ', "_"); let title_name = name.to_case(Case::Snake); let read_value1 = format!("{}_read_value_bytes", var_name); @@ -44,8 +42,9 @@ impl MeteredCounter { let read_multi_values1 = format!("{}_read_multi_value_bytes", var_name); let read_multi_values2 = format!("{} read multi value bytes", title_name); - let read_multi_values_bytes = register_histogram_vec!(read_multi_values1, read_multi_values2, &[]) - .expect("Counter creation should not fail"); + let read_multi_values_bytes = + register_histogram_vec!(read_multi_values1, read_multi_values2, &[]) + .expect("Counter creation should not fail"); let find_keys1 = format!("{}_find_keys_by_prefix", var_name); let find_keys2 = format!("{} find keys by prefix", title_name); @@ -54,8 +53,9 @@ impl MeteredCounter { let find_key_values1 = format!("{}_find_key_values_by_prefix", var_name); let find_key_values2 = format!("{} find key values by prefix", title_name); - let find_key_values_by_prefix = register_histogram_vec!(find_key_values1, find_key_values2, &[]) - .expect("Counter creation should not fail"); + let find_key_values_by_prefix = + register_histogram_vec!(find_key_values1, find_key_values2, &[]) + .expect("Counter creation should not fail"); let write_batch1 = format!("{}_write_batch", var_name); let write_batch2 = format!("{} write batch", title_name); @@ -67,7 +67,15 @@ impl MeteredCounter { let clear_journal = register_histogram_vec!(clear_journal1, clear_journal2, &[]) .expect("Counter creation should not fail"); - MeteredCounter { read_value_bytes, contains_key, read_multi_values_bytes, find_keys_by_prefix, find_key_values_by_prefix, write_batch, clear_journal } + MeteredCounter { + read_value_bytes, + contains_key, + read_multi_values_bytes, + find_keys_by_prefix, + find_key_values_by_prefix, + write_batch, + clear_journal, + } } } @@ -92,7 +100,6 @@ where out } - #[async_trait] impl ReadableKeyValueStore for MeteredStore where @@ -107,29 +114,39 @@ where } async fn read_value_bytes(&self, key: &[u8]) -> Result>, E> { - prometheus_async(self.store.read_value_bytes(key), &self.counter.read_value_bytes).await + prometheus_async( + self.store.read_value_bytes(key), + &self.counter.read_value_bytes, + ) + .await } async fn contains_key(&self, key: &[u8]) -> Result { prometheus_async(self.store.contains_key(key), &self.counter.contains_key).await } - async fn read_multi_values_bytes( - &self, - keys: Vec>, - ) -> Result>>, E> { - prometheus_async(self.store.read_multi_values_bytes(keys), &self.counter.read_multi_values_bytes).await + async fn read_multi_values_bytes(&self, keys: Vec>) -> Result>>, E> { + prometheus_async( + self.store.read_multi_values_bytes(keys), + &self.counter.read_multi_values_bytes, + ) + .await } async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result { - prometheus_async(self.store.find_keys_by_prefix(key_prefix), &self.counter.find_keys_by_prefix).await + prometheus_async( + self.store.find_keys_by_prefix(key_prefix), + &self.counter.find_keys_by_prefix, + ) + .await } - async fn find_key_values_by_prefix( - &self, - key_prefix: &[u8], - ) -> Result { - prometheus_async(self.store.find_key_values_by_prefix(key_prefix), &self.counter.find_key_values_by_prefix).await + async fn find_key_values_by_prefix(&self, key_prefix: &[u8]) -> Result { + prometheus_async( + self.store.find_key_values_by_prefix(key_prefix), + &self.counter.find_key_values_by_prefix, + ) + .await } } @@ -141,11 +158,19 @@ where const MAX_VALUE_SIZE: usize = K::MAX_VALUE_SIZE; async fn write_batch(&self, batch: Batch, base_key: &[u8]) -> Result<(), E> { - prometheus_async(self.store.write_batch(batch, base_key), &self.counter.write_batch).await + prometheus_async( + self.store.write_batch(batch, base_key), + &self.counter.write_batch, + ) + .await } async fn clear_journal(&self, base_key: &[u8]) -> Result<(), E> { - prometheus_async(self.store.clear_journal(base_key), &self.counter.clear_journal).await + prometheus_async( + self.store.clear_journal(base_key), + &self.counter.clear_journal, + ) + .await } } @@ -163,4 +188,3 @@ impl MeteredStore { Self { counter, store } } } - diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index 5d32861a77ce..67e51ce5c5dd 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -236,7 +236,9 @@ impl KeyValueStore for RocksDbStoreInternal { #[derive(Clone)] pub struct RocksDbStore { #[cfg(feature = "metrics")] - store: MeteredStore>>>>, + store: MeteredStore< + LruCachingStore>>>, + >, #[cfg(not(feature = "metrics"))] store: LruCachingStore>, } @@ -314,9 +316,9 @@ impl RocksDbStore { let store = MeteredStore::new("rocks db internal".to_string(), store); let store = ValueSplittingStore::new(store); let store = MeteredStore::new("value splitting".to_string(), store); - let store = LruCachingStore::new(store, cache_size); + let store = LruCachingStore::new(store, cache_size); let store = MeteredStore::new("lru caching".to_string(), store); - Self { store } + Self { store } } /// Creates a RocksDB database from a specified path. diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index ca992edaff84..0e1bc0bb84fb 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -677,7 +677,8 @@ impl ScyllaDbStoreInternal { #[derive(Clone)] pub struct ScyllaDbStore { #[cfg(feature = "metrics")] - store: MeteredStore>>>, + store: + MeteredStore>>>, #[cfg(not(feature = "metrics"))] store: LruCachingStore>, } @@ -767,16 +768,22 @@ impl ScyllaDbStore { } #[cfg(not(feature = "metrics"))] - fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { - let store = LruCachingStore::new(store, cache_size); + fn get_complete_store( + store: JournalingKeyValueStore, + cache_size: usize, + ) -> Self { + let store = LruCachingStore::new(store, cache_size); Self { store } } #[cfg(feature = "metrics")] - fn get_complete_store(store: JournalingKeyValueStore, cache_size: usize) -> Self { - let store = MeteredStore::new("scylla db internal".to_string(), store); + fn get_complete_store( + store: JournalingKeyValueStore, + cache_size: usize, + ) -> Self { + let store = MeteredStore::new("scylla db internal".to_string(), store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("lru caching".to_string(), store); + let store = MeteredStore::new("lru caching".to_string(), store); Self { store } } From 0a5686e060ba1729490b2ff4f3a6c09dc919bda4 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Thu, 18 Jan 2024 07:46:39 +0100 Subject: [PATCH 07/15] Some correction for linting. --- examples/Cargo.lock | 1 + linera-views/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/Cargo.lock b/examples/Cargo.lock index bb4e14fa500c..c8b0899de869 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -1801,6 +1801,7 @@ dependencies = [ "async-lock", "async-trait", "bcs", + "convert_case 0.6.0", "futures", "generic-array", "hex", diff --git a/linera-views/Cargo.toml b/linera-views/Cargo.toml index f3fa912ff391..2f00eff0c184 100644 --- a/linera-views/Cargo.toml +++ b/linera-views/Cargo.toml @@ -22,12 +22,12 @@ db_timings = [] metrics = ["dep:hex"] [dependencies] -convert_case = { workspace = true } anyhow = { workspace = true } async-graphql = { workspace = true } async-lock = { workspace = true } async-trait = { workspace = true } bcs = { workspace = true } +convert_case = { workspace = true } futures = { workspace = true } generic-array = { workspace = true } hex = { workspace = true, optional = true } From e6e70d26810b270fe1bb13c364a3b876d8311da9 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Thu, 18 Jan 2024 11:35:06 +0100 Subject: [PATCH 08/15] Make the test pass so that the entries are not registered multiple times. --- linera-views/src/dynamo_db.rs | 11 +++++---- linera-views/src/metered_wrapper.rs | 35 +++++++++++++++++++++++++---- linera-views/src/rocks_db.rs | 17 ++++++++------ linera-views/src/scylla_db.rs | 8 ++++--- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index 0e175a5a0d50..194172fd21d9 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -41,7 +41,10 @@ use std::{collections::HashMap, env, str::FromStr, sync::Arc}; use thiserror::Error; #[cfg(feature = "metrics")] -use crate::metered_wrapper::MeteredStore; +use crate::metered_wrapper::{ + MeteredStore, METERED_COUNTER_DYNAMO_DB, METERED_COUNTER_LRU_CACHING, + METERED_COUNTER_VALUE_SPLITTING, +}; #[cfg(any(test, feature = "test"))] use { @@ -1035,11 +1038,11 @@ impl DynamoDbStore { store: JournalingKeyValueStore, cache_size: usize, ) -> Self { - let store = MeteredStore::new("dynamo db internal".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_DYNAMO_DB, store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new("value splitting".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_VALUE_SPLITTING, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("lru caching".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); Self { store } } diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index fa37092889d7..0b431b6684a6 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -9,12 +9,14 @@ use crate::{ }; use async_trait::async_trait; use convert_case::{Case, Casing}; +use linera_base::sync::Lazy; use prometheus::{register_histogram_vec, HistogramVec}; use std::{future::Future, time::Instant}; //use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] -struct MeteredCounter { +/// The implementation of the `MeteredCounter` for the `KeyValueStore`. +pub struct MeteredCounter { read_value_bytes: HistogramVec, contains_key: HistogramVec, read_multi_values_bytes: HistogramVec, @@ -24,7 +26,33 @@ struct MeteredCounter { clear_journal: HistogramVec, } +/// The metered counter for the "rocks db" +#[cfg(feature = "rocksdb")] +pub static METERED_COUNTER_ROCKS_DB: Lazy = + Lazy::new(|| MeteredCounter::new("rocks db internal".to_string())); + +/// The metered counter for the "dynamo db" +#[cfg(feature = "aws")] +pub static METERED_COUNTER_DYNAMO_DB: Lazy = + Lazy::new(|| MeteredCounter::new("dynamo db internal".to_string())); + +/// The metered counter for the "scylla db" +#[cfg(feature = "scylladb")] +pub static METERED_COUNTER_SCYLLA_DB: Lazy = + Lazy::new(|| MeteredCounter::new("scylla db internal".to_string())); + +/// The metered counter for the "scylla db" +#[cfg(any(feature = "rocksdb", feature = "aws"))] +pub static METERED_COUNTER_VALUE_SPLITTING: Lazy = + Lazy::new(|| MeteredCounter::new("value splitting".to_string())); + +/// The metered counter for the "lru caching" +#[cfg(any(feature = "rocksdb", feature = "aws", feature = "scylladb"))] +pub static METERED_COUNTER_LRU_CACHING: Lazy = + Lazy::new(|| MeteredCounter::new("lru caching".to_string())); + impl MeteredCounter { + /// Creation of a named Metered counter. pub fn new(name: String) -> Self { // name can be "rocks db". Then var_name = "rocks_db" and title_name = "RocksDb" let var_name = name.replace(' ', "_"); @@ -83,7 +111,7 @@ impl MeteredCounter { #[derive(Clone)] pub struct MeteredStore { /// the metrics being stored - counter: MeteredCounter, + counter: &'static Lazy, /// The underlying store of the metered store pub store: K, } @@ -183,8 +211,7 @@ where impl MeteredStore { /// Creates a new Metered store - pub fn new(name: String, store: K) -> Self { - let counter = MeteredCounter::new(name); + pub fn new(counter: &'static Lazy, store: K) -> Self { Self { counter, store } } } diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index 67e51ce5c5dd..4e6d654fe9b5 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -21,7 +21,10 @@ use std::{ use thiserror::Error; #[cfg(feature = "metrics")] -use crate::metered_wrapper::MeteredStore; +use crate::metered_wrapper::{ + MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_ROCKS_DB, + METERED_COUNTER_VALUE_SPLITTING, +}; #[cfg(any(test, feature = "test"))] use {crate::lru_caching::TEST_CACHE_SIZE, tempfile::TempDir}; @@ -263,7 +266,7 @@ impl RocksDbStore { #[cfg(any(test, feature = "test"))] pub async fn new_for_testing( store_config: RocksDbStoreConfig, - ) -> Result<(RocksDbStore, TableStatus), RocksDbContextError> { + ) -> Result<(Self, TableStatus), RocksDbContextError> { let path = store_config.path_buf.as_path(); fs::remove_dir_all(path)?; let create_if_missing = true; @@ -289,7 +292,7 @@ impl RocksDbStore { /// Creates a RocksDB database from a specified path. pub async fn new( store_config: RocksDbStoreConfig, - ) -> Result<(RocksDbStore, TableStatus), RocksDbContextError> { + ) -> Result<(Self, TableStatus), RocksDbContextError> { let create_if_missing = false; Self::new_internal(store_config, create_if_missing).await } @@ -313,11 +316,11 @@ impl RocksDbStore { #[cfg(feature = "metrics")] fn get_complete_store(store: RocksDbStoreInternal, cache_size: usize) -> Self { - let store = MeteredStore::new("rocks db internal".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_ROCKS_DB, store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new("value splitting".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_VALUE_SPLITTING, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("lru caching".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); Self { store } } @@ -325,7 +328,7 @@ impl RocksDbStore { async fn new_internal( store_config: RocksDbStoreConfig, create_if_missing: bool, - ) -> Result<(RocksDbStore, TableStatus), RocksDbContextError> { + ) -> Result<(Self, TableStatus), RocksDbContextError> { let kv_name = format!( "store_config={:?} create_if_missing={:?}", store_config, create_if_missing diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index 0e1bc0bb84fb..607f38e92509 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -16,7 +16,9 @@ //! [trait2]: common::Context #[cfg(feature = "metrics")] -use crate::metered_wrapper::MeteredStore; +use crate::metered_wrapper::{ + MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_SCYLLA_DB, +}; #[cfg(any(test, feature = "test"))] use crate::{lru_caching::TEST_CACHE_SIZE, test_utils::get_table_name}; @@ -781,9 +783,9 @@ impl ScyllaDbStore { store: JournalingKeyValueStore, cache_size: usize, ) -> Self { - let store = MeteredStore::new("scylla db internal".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_SCYLLA_DB, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new("lru caching".to_string(), store); + let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); Self { store } } From 1bf3a915feffe2b665723164ba013f41464d927c Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 08:45:19 +0100 Subject: [PATCH 09/15] Rename prometheus_async. --- linera-views/src/metered_wrapper.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metered_wrapper.rs index 0b431b6684a6..72af4f69da51 100644 --- a/linera-views/src/metered_wrapper.rs +++ b/linera-views/src/metered_wrapper.rs @@ -116,7 +116,7 @@ pub struct MeteredStore { pub store: K, } -async fn prometheus_async(f: F, hist: &HistogramVec) -> O +async fn run_with_execution_time_metric(f: F, hist: &HistogramVec) -> O where F: Future, { @@ -142,7 +142,7 @@ where } async fn read_value_bytes(&self, key: &[u8]) -> Result>, E> { - prometheus_async( + run_with_execution_time_metric( self.store.read_value_bytes(key), &self.counter.read_value_bytes, ) @@ -150,11 +150,11 @@ where } async fn contains_key(&self, key: &[u8]) -> Result { - prometheus_async(self.store.contains_key(key), &self.counter.contains_key).await + run_with_execution_time_metric(self.store.contains_key(key), &self.counter.contains_key).await } async fn read_multi_values_bytes(&self, keys: Vec>) -> Result>>, E> { - prometheus_async( + run_with_execution_time_metric( self.store.read_multi_values_bytes(keys), &self.counter.read_multi_values_bytes, ) @@ -162,7 +162,7 @@ where } async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result { - prometheus_async( + run_with_execution_time_metric( self.store.find_keys_by_prefix(key_prefix), &self.counter.find_keys_by_prefix, ) @@ -170,7 +170,7 @@ where } async fn find_key_values_by_prefix(&self, key_prefix: &[u8]) -> Result { - prometheus_async( + run_with_execution_time_metric( self.store.find_key_values_by_prefix(key_prefix), &self.counter.find_key_values_by_prefix, ) @@ -186,7 +186,7 @@ where const MAX_VALUE_SIZE: usize = K::MAX_VALUE_SIZE; async fn write_batch(&self, batch: Batch, base_key: &[u8]) -> Result<(), E> { - prometheus_async( + run_with_execution_time_metric( self.store.write_batch(batch, base_key), &self.counter.write_batch, ) @@ -194,7 +194,7 @@ where } async fn clear_journal(&self, base_key: &[u8]) -> Result<(), E> { - prometheus_async( + run_with_execution_time_metric( self.store.clear_journal(base_key), &self.counter.clear_journal, ) From 6d50ddbf69b3301e61da464c320eecfcf9539176 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 08:48:27 +0100 Subject: [PATCH 10/15] More renaming. --- linera-views/src/dynamo_db.rs | 2 +- linera-views/src/lib.rs | 2 +- linera-views/src/{metered_wrapper.rs => metering.rs} | 0 linera-views/src/rocks_db.rs | 2 +- linera-views/src/scylla_db.rs | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename linera-views/src/{metered_wrapper.rs => metering.rs} (100%) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index 194172fd21d9..ad0caa97fc07 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -41,7 +41,7 @@ use std::{collections::HashMap, env, str::FromStr, sync::Arc}; use thiserror::Error; #[cfg(feature = "metrics")] -use crate::metered_wrapper::{ +use crate::metering::{ MeteredStore, METERED_COUNTER_DYNAMO_DB, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_VALUE_SPLITTING, }; diff --git a/linera-views/src/lib.rs b/linera-views/src/lib.rs index 0fd1c8ad9501..44cd607b6bc3 100644 --- a/linera-views/src/lib.rs +++ b/linera-views/src/lib.rs @@ -64,7 +64,7 @@ pub mod journaling; /// The code for encapsulating one key_value store into another that does metric #[cfg(feature = "metrics")] -pub mod metered_wrapper; +pub mod metering; /// The code for handling big values by splitting them into several small ones. pub mod value_splitting; diff --git a/linera-views/src/metered_wrapper.rs b/linera-views/src/metering.rs similarity index 100% rename from linera-views/src/metered_wrapper.rs rename to linera-views/src/metering.rs diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index 4e6d654fe9b5..8cf2ec8062e8 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -21,7 +21,7 @@ use std::{ use thiserror::Error; #[cfg(feature = "metrics")] -use crate::metered_wrapper::{ +use crate::metering::{ MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_ROCKS_DB, METERED_COUNTER_VALUE_SPLITTING, }; diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index 607f38e92509..9f55612a2d40 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -16,7 +16,7 @@ //! [trait2]: common::Context #[cfg(feature = "metrics")] -use crate::metered_wrapper::{ +use crate::metering::{ MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_SCYLLA_DB, }; From 855afbc4f1aaae00f5328497fde406365abed818 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 08:57:06 +0100 Subject: [PATCH 11/15] Another rename. --- linera-views/src/metering.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/linera-views/src/metering.rs b/linera-views/src/metering.rs index 72af4f69da51..14e584e306af 100644 --- a/linera-views/src/metering.rs +++ b/linera-views/src/metering.rs @@ -15,8 +15,8 @@ use std::{future::Future, time::Instant}; //use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] -/// The implementation of the `MeteredCounter` for the `KeyValueStore`. -pub struct MeteredCounter { +/// The implementation of the `KeyValueStoreMetrics` for the `KeyValueStore`. +pub struct KeyValueStoreMetrics { read_value_bytes: HistogramVec, contains_key: HistogramVec, read_multi_values_bytes: HistogramVec, @@ -28,30 +28,30 @@ pub struct MeteredCounter { /// The metered counter for the "rocks db" #[cfg(feature = "rocksdb")] -pub static METERED_COUNTER_ROCKS_DB: Lazy = - Lazy::new(|| MeteredCounter::new("rocks db internal".to_string())); +pub static METERED_COUNTER_ROCKS_DB: Lazy = + Lazy::new(|| KeyValueStoreMetrics::new("rocks db internal".to_string())); /// The metered counter for the "dynamo db" #[cfg(feature = "aws")] -pub static METERED_COUNTER_DYNAMO_DB: Lazy = - Lazy::new(|| MeteredCounter::new("dynamo db internal".to_string())); +pub static METERED_COUNTER_DYNAMO_DB: Lazy = + Lazy::new(|| KeyValueStoreMetrics::new("dynamo db internal".to_string())); /// The metered counter for the "scylla db" #[cfg(feature = "scylladb")] -pub static METERED_COUNTER_SCYLLA_DB: Lazy = - Lazy::new(|| MeteredCounter::new("scylla db internal".to_string())); +pub static METERED_COUNTER_SCYLLA_DB: Lazy = + Lazy::new(|| KeyValueStoreMetrics::new("scylla db internal".to_string())); /// The metered counter for the "scylla db" #[cfg(any(feature = "rocksdb", feature = "aws"))] -pub static METERED_COUNTER_VALUE_SPLITTING: Lazy = - Lazy::new(|| MeteredCounter::new("value splitting".to_string())); +pub static METERED_COUNTER_VALUE_SPLITTING: Lazy = + Lazy::new(|| KeyValueStoreMetrics::new("value splitting".to_string())); /// The metered counter for the "lru caching" #[cfg(any(feature = "rocksdb", feature = "aws", feature = "scylladb"))] -pub static METERED_COUNTER_LRU_CACHING: Lazy = - Lazy::new(|| MeteredCounter::new("lru caching".to_string())); +pub static METERED_COUNTER_LRU_CACHING: Lazy = + Lazy::new(|| KeyValueStoreMetrics::new("lru caching".to_string())); -impl MeteredCounter { +impl KeyValueStoreMetrics { /// Creation of a named Metered counter. pub fn new(name: String) -> Self { // name can be "rocks db". Then var_name = "rocks_db" and title_name = "RocksDb" @@ -95,7 +95,7 @@ impl MeteredCounter { let clear_journal = register_histogram_vec!(clear_journal1, clear_journal2, &[]) .expect("Counter creation should not fail"); - MeteredCounter { + KeyValueStoreMetrics { read_value_bytes, contains_key, read_multi_values_bytes, @@ -111,7 +111,7 @@ impl MeteredCounter { #[derive(Clone)] pub struct MeteredStore { /// the metrics being stored - counter: &'static Lazy, + counter: &'static Lazy, /// The underlying store of the metered store pub store: K, } @@ -211,7 +211,7 @@ where impl MeteredStore { /// Creates a new Metered store - pub fn new(counter: &'static Lazy, store: K) -> Self { + pub fn new(counter: &'static Lazy, store: K) -> Self { Self { counter, store } } } From 5d10281b13ec4527c5327f8ec479154c2ed8afa0 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 09:00:58 +0100 Subject: [PATCH 12/15] More renaming. --- linera-views/src/metering.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/linera-views/src/metering.rs b/linera-views/src/metering.rs index 14e584e306af..cba53229901c 100644 --- a/linera-views/src/metering.rs +++ b/linera-views/src/metering.rs @@ -26,27 +26,27 @@ pub struct KeyValueStoreMetrics { clear_journal: HistogramVec, } -/// The metered counter for the "rocks db" +/// The metrics for the "rocks db" #[cfg(feature = "rocksdb")] pub static METERED_COUNTER_ROCKS_DB: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("rocks db internal".to_string())); -/// The metered counter for the "dynamo db" +/// The metrics for the "dynamo db" #[cfg(feature = "aws")] pub static METERED_COUNTER_DYNAMO_DB: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("dynamo db internal".to_string())); -/// The metered counter for the "scylla db" +/// The metrics for the "scylla db" #[cfg(feature = "scylladb")] pub static METERED_COUNTER_SCYLLA_DB: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("scylla db internal".to_string())); -/// The metered counter for the "scylla db" +/// The metrics for the "scylla db" #[cfg(any(feature = "rocksdb", feature = "aws"))] pub static METERED_COUNTER_VALUE_SPLITTING: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("value splitting".to_string())); -/// The metered counter for the "lru caching" +/// The metrics for the "lru caching" #[cfg(any(feature = "rocksdb", feature = "aws", feature = "scylladb"))] pub static METERED_COUNTER_LRU_CACHING: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("lru caching".to_string())); From 3ddec71425dc7333d258a942cacda60ec4362739 Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 09:07:00 +0100 Subject: [PATCH 13/15] formatting. --- linera-views/src/metering.rs | 3 ++- linera-views/src/scylla_db.rs | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/linera-views/src/metering.rs b/linera-views/src/metering.rs index cba53229901c..2579e78e7e17 100644 --- a/linera-views/src/metering.rs +++ b/linera-views/src/metering.rs @@ -150,7 +150,8 @@ where } async fn contains_key(&self, key: &[u8]) -> Result { - run_with_execution_time_metric(self.store.contains_key(key), &self.counter.contains_key).await + run_with_execution_time_metric(self.store.contains_key(key), &self.counter.contains_key) + .await } async fn read_multi_values_bytes(&self, keys: Vec>) -> Result>>, E> { diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index 9f55612a2d40..2651ed29b05c 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -16,9 +16,7 @@ //! [trait2]: common::Context #[cfg(feature = "metrics")] -use crate::metering::{ - MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_SCYLLA_DB, -}; +use crate::metering::{MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_SCYLLA_DB}; #[cfg(any(test, feature = "test"))] use crate::{lru_caching::TEST_CACHE_SIZE, test_utils::get_table_name}; From ac7790a0ecfdafff467709812fbb20b4b27cfdef Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 20:44:46 +0100 Subject: [PATCH 14/15] Simplification of the names. --- linera-views/src/dynamo_db.rs | 9 ++++----- linera-views/src/metering.rs | 10 +++++----- linera-views/src/rocks_db.rs | 9 ++++----- linera-views/src/scylla_db.rs | 6 +++--- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/linera-views/src/dynamo_db.rs b/linera-views/src/dynamo_db.rs index ad0caa97fc07..301f386381ee 100644 --- a/linera-views/src/dynamo_db.rs +++ b/linera-views/src/dynamo_db.rs @@ -42,8 +42,7 @@ use thiserror::Error; #[cfg(feature = "metrics")] use crate::metering::{ - MeteredStore, METERED_COUNTER_DYNAMO_DB, METERED_COUNTER_LRU_CACHING, - METERED_COUNTER_VALUE_SPLITTING, + MeteredStore, DYNAMO_DB_METRICS, LRU_CACHING_METRICS, VALUE_SPLITTING_METRICS, }; #[cfg(any(test, feature = "test"))] @@ -1038,11 +1037,11 @@ impl DynamoDbStore { store: JournalingKeyValueStore, cache_size: usize, ) -> Self { - let store = MeteredStore::new(&METERED_COUNTER_DYNAMO_DB, store); + let store = MeteredStore::new(&DYNAMO_DB_METRICS, store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new(&METERED_COUNTER_VALUE_SPLITTING, store); + let store = MeteredStore::new(&VALUE_SPLITTING_METRICS, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); + let store = MeteredStore::new(&LRU_CACHING_METRICS, store); Self { store } } diff --git a/linera-views/src/metering.rs b/linera-views/src/metering.rs index 2579e78e7e17..6233d5b1892c 100644 --- a/linera-views/src/metering.rs +++ b/linera-views/src/metering.rs @@ -28,27 +28,27 @@ pub struct KeyValueStoreMetrics { /// The metrics for the "rocks db" #[cfg(feature = "rocksdb")] -pub static METERED_COUNTER_ROCKS_DB: Lazy = +pub static ROCKS_DB_METRICS: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("rocks db internal".to_string())); /// The metrics for the "dynamo db" #[cfg(feature = "aws")] -pub static METERED_COUNTER_DYNAMO_DB: Lazy = +pub static DYNAMO_DB_METRICS: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("dynamo db internal".to_string())); /// The metrics for the "scylla db" #[cfg(feature = "scylladb")] -pub static METERED_COUNTER_SCYLLA_DB: Lazy = +pub static SCYLLA_DB_METRICS: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("scylla db internal".to_string())); /// The metrics for the "scylla db" #[cfg(any(feature = "rocksdb", feature = "aws"))] -pub static METERED_COUNTER_VALUE_SPLITTING: Lazy = +pub static VALUE_SPLITTING_METRICS: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("value splitting".to_string())); /// The metrics for the "lru caching" #[cfg(any(feature = "rocksdb", feature = "aws", feature = "scylladb"))] -pub static METERED_COUNTER_LRU_CACHING: Lazy = +pub static LRU_CACHING_METRICS: Lazy = Lazy::new(|| KeyValueStoreMetrics::new("lru caching".to_string())); impl KeyValueStoreMetrics { diff --git a/linera-views/src/rocks_db.rs b/linera-views/src/rocks_db.rs index 8cf2ec8062e8..3ed7fd76c9df 100644 --- a/linera-views/src/rocks_db.rs +++ b/linera-views/src/rocks_db.rs @@ -22,8 +22,7 @@ use thiserror::Error; #[cfg(feature = "metrics")] use crate::metering::{ - MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_ROCKS_DB, - METERED_COUNTER_VALUE_SPLITTING, + MeteredStore, LRU_CACHING_METRICS, ROCKS_DB_METRICS, VALUE_SPLITTING_METRICS, }; #[cfg(any(test, feature = "test"))] @@ -316,11 +315,11 @@ impl RocksDbStore { #[cfg(feature = "metrics")] fn get_complete_store(store: RocksDbStoreInternal, cache_size: usize) -> Self { - let store = MeteredStore::new(&METERED_COUNTER_ROCKS_DB, store); + let store = MeteredStore::new(&ROCKS_DB_METRICS, store); let store = ValueSplittingStore::new(store); - let store = MeteredStore::new(&METERED_COUNTER_VALUE_SPLITTING, store); + let store = MeteredStore::new(&VALUE_SPLITTING_METRICS, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); + let store = MeteredStore::new(&LRU_CACHING_METRICS, store); Self { store } } diff --git a/linera-views/src/scylla_db.rs b/linera-views/src/scylla_db.rs index 2651ed29b05c..edf030576062 100644 --- a/linera-views/src/scylla_db.rs +++ b/linera-views/src/scylla_db.rs @@ -16,7 +16,7 @@ //! [trait2]: common::Context #[cfg(feature = "metrics")] -use crate::metering::{MeteredStore, METERED_COUNTER_LRU_CACHING, METERED_COUNTER_SCYLLA_DB}; +use crate::metering::{MeteredStore, LRU_CACHING_METRICS, SCYLLA_DB_METRICS}; #[cfg(any(test, feature = "test"))] use crate::{lru_caching::TEST_CACHE_SIZE, test_utils::get_table_name}; @@ -781,9 +781,9 @@ impl ScyllaDbStore { store: JournalingKeyValueStore, cache_size: usize, ) -> Self { - let store = MeteredStore::new(&METERED_COUNTER_SCYLLA_DB, store); + let store = MeteredStore::new(&SCYLLA_DB_METRICS, store); let store = LruCachingStore::new(store, cache_size); - let store = MeteredStore::new(&METERED_COUNTER_LRU_CACHING, store); + let store = MeteredStore::new(&LRU_CACHING_METRICS, store); Self { store } } From e1ed7c67b508815a0d211fa9926d3d30ad0ecb4f Mon Sep 17 00:00:00 2001 From: Mathieu Dutour Sikiric Date: Fri, 19 Jan 2024 20:53:39 +0100 Subject: [PATCH 15/15] Remove unused includes. --- linera-views/src/metering.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/linera-views/src/metering.rs b/linera-views/src/metering.rs index 6233d5b1892c..d867f68e27bc 100644 --- a/linera-views/src/metering.rs +++ b/linera-views/src/metering.rs @@ -1,8 +1,6 @@ // Copyright (c) Zefchain Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -//use std::time::{Duration, Instant}; -//use linera_base::sync::Lazy; use crate::{ batch::Batch, common::{KeyValueStore, ReadableKeyValueStore, WritableKeyValueStore}, @@ -12,7 +10,6 @@ use convert_case::{Case, Casing}; use linera_base::sync::Lazy; use prometheus::{register_histogram_vec, HistogramVec}; use std::{future::Future, time::Instant}; -//use crate::journaling::DirectWritableKeyValueStore; #[derive(Clone)] /// The implementation of the `KeyValueStoreMetrics` for the `KeyValueStore`.