diff --git a/Makefile b/Makefile index da0606f4..ab6cae05 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ example: full: check-all test-all example udeps -fast: check test example +fast: ffmt check test example msrv: shellcheck ./scripts/* diff --git a/foyer-common/src/metrics/mod.rs b/foyer-common/src/metrics/mod.rs index 8e63bb8f..eaff575f 100644 --- a/foyer-common/src/metrics/mod.rs +++ b/foyer-common/src/metrics/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt::Debug; +use std::{borrow::Cow, fmt::Debug}; /// Counter metric operations. pub trait CounterOps: Send + Sync + 'static + Debug { @@ -39,19 +39,19 @@ pub trait HistogramOps: Send + Sync + 'static + Debug { /// A vector of counters. pub trait CounterVecOps: Send + Sync + 'static + Debug { /// Get a counter within the vector of counters. - fn counter(&self, labels: &[&'static str]) -> impl CounterOps; + fn counter(&self, labels: &[Cow<'static, str>]) -> impl CounterOps; } /// A vector of gauges. pub trait GaugeVecOps: Send + Sync + 'static + Debug { /// Get a gauge within the vector of gauges. - fn gauge(&self, labels: &[&'static str]) -> impl GaugeOps; + fn gauge(&self, labels: &[Cow<'static, str>]) -> impl GaugeOps; } /// A vector of histograms. pub trait HistogramVecOps: Send + Sync + 'static + Debug { /// Get a histogram within the vector of histograms. - fn histogram(&self, labels: &[&'static str]) -> impl HistogramOps; + fn histogram(&self, labels: &[Cow<'static, str>]) -> impl HistogramOps; } /// Metrics registry. @@ -59,24 +59,24 @@ pub trait RegistryOps: Send + Sync + 'static + Debug { /// Register a vector of counters to the registry. fn register_counter_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl CounterVecOps; /// Register a vector of gauges to the registry. fn register_gauge_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl GaugeVecOps; /// Register a vector of histograms to the registry. fn register_histogram_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl HistogramVecOps; } diff --git a/foyer-common/src/metrics/model.rs b/foyer-common/src/metrics/model.rs index ea92d1fe..24aa98c3 100644 --- a/foyer-common/src/metrics/model.rs +++ b/foyer-common/src/metrics/model.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::borrow::Cow; + use super::{BoxedCounter, BoxedGauge, BoxedHistogram, GaugeVecOps, HistogramVecOps, RegistryOps}; use crate::metrics::CounterVecOps; @@ -92,10 +94,12 @@ pub struct Metrics { impl Metrics { /// Create a new metric with the given name. - pub fn new(name: &'static str, registry: &R) -> Self + pub fn new(name: impl Into>, registry: &R) -> Self where R: RegistryOps, { + let name = name.into(); + /* in-memory cache metrics */ let foyer_memory_op_total = registry.register_counter_vec( @@ -106,18 +110,20 @@ impl Metrics { let foyer_memory_usage = registry.register_gauge_vec("foyer_memory_usage", "foyer in-memory cache usage", &["name"]); - let memory_insert = foyer_memory_op_total.counter(&[name, "insert"]).boxed(); - let memory_replace = foyer_memory_op_total.counter(&[name, "replace"]).boxed(); - let memory_hit = foyer_memory_op_total.counter(&[name, "hit"]).boxed(); - let memory_miss = foyer_memory_op_total.counter(&[name, "miss"]).boxed(); - let memory_remove = foyer_memory_op_total.counter(&[name, "remove"]).boxed(); - let memory_evict = foyer_memory_op_total.counter(&[name, "evict"]).boxed(); - let memory_reinsert = foyer_memory_op_total.counter(&[name, "reinsert"]).boxed(); - let memory_release = foyer_memory_op_total.counter(&[name, "release"]).boxed(); - let memory_queue = foyer_memory_op_total.counter(&[name, "queue"]).boxed(); - let memory_fetch = foyer_memory_op_total.counter(&[name, "fetch"]).boxed(); + let memory_insert = foyer_memory_op_total.counter(&[name.clone(), "insert".into()]).boxed(); + let memory_replace = foyer_memory_op_total.counter(&[name.clone(), "replace".into()]).boxed(); + let memory_hit = foyer_memory_op_total.counter(&[name.clone(), "hit".into()]).boxed(); + let memory_miss = foyer_memory_op_total.counter(&[name.clone(), "miss".into()]).boxed(); + let memory_remove = foyer_memory_op_total.counter(&[name.clone(), "remove".into()]).boxed(); + let memory_evict = foyer_memory_op_total.counter(&[name.clone(), "evict".into()]).boxed(); + let memory_reinsert = foyer_memory_op_total + .counter(&[name.clone(), "reinsert".into()]) + .boxed(); + let memory_release = foyer_memory_op_total.counter(&[name.clone(), "release".into()]).boxed(); + let memory_queue = foyer_memory_op_total.counter(&[name.clone(), "queue".into()]).boxed(); + let memory_fetch = foyer_memory_op_total.counter(&[name.clone(), "fetch".into()]).boxed(); - let memory_usage = foyer_memory_usage.gauge(&[name]).boxed(); + let memory_usage = foyer_memory_usage.gauge(&[name.clone()]).boxed(); /* disk cache metrics */ @@ -170,45 +176,75 @@ impl Metrics { &["name", "op"], ); - let storage_enqueue = foyer_storage_op_total.counter(&[name, "enqueue"]).boxed(); - let storage_hit = foyer_storage_op_total.counter(&[name, "hit"]).boxed(); - let storage_miss = foyer_storage_op_total.counter(&[name, "miss"]).boxed(); - let storage_delete = foyer_storage_op_total.counter(&[name, "delete"]).boxed(); + let storage_enqueue = foyer_storage_op_total + .counter(&[name.clone(), "enqueue".into()]) + .boxed(); + let storage_hit = foyer_storage_op_total.counter(&[name.clone(), "hit".into()]).boxed(); + let storage_miss = foyer_storage_op_total.counter(&[name.clone(), "miss".into()]).boxed(); + let storage_delete = foyer_storage_op_total.counter(&[name.clone(), "delete".into()]).boxed(); - let storage_enqueue_duration = foyer_storage_op_duration.histogram(&[name, "enqueue"]).boxed(); - let storage_hit_duration = foyer_storage_op_duration.histogram(&[name, "hit"]).boxed(); - let storage_miss_duration = foyer_storage_op_duration.histogram(&[name, "miss"]).boxed(); - let storage_delete_duration = foyer_storage_op_duration.histogram(&[name, "delete"]).boxed(); + let storage_enqueue_duration = foyer_storage_op_duration + .histogram(&[name.clone(), "enqueue".into()]) + .boxed(); + let storage_hit_duration = foyer_storage_op_duration + .histogram(&[name.clone(), "hit".into()]) + .boxed(); + let storage_miss_duration = foyer_storage_op_duration + .histogram(&[name.clone(), "miss".into()]) + .boxed(); + let storage_delete_duration = foyer_storage_op_duration + .histogram(&[name.clone(), "delete".into()]) + .boxed(); - let storage_queue_rotate = foyer_storage_inner_op_total.counter(&[name, "queue_rotate"]).boxed(); - let storage_queue_drop = foyer_storage_inner_op_total.counter(&[name, "queue_drop"]).boxed(); + let storage_queue_rotate = foyer_storage_inner_op_total + .counter(&[name.clone(), "queue_rotate".into()]) + .boxed(); + let storage_queue_drop = foyer_storage_inner_op_total + .counter(&[name.clone(), "queue_drop".into()]) + .boxed(); let storage_queue_rotate_duration = foyer_storage_inner_op_duration - .histogram(&[name, "queue_rotate"]) + .histogram(&[name.clone(), "queue_rotate".into()]) .boxed(); - let storage_disk_write = foyer_storage_disk_io_total.counter(&[name, "write"]).boxed(); - let storage_disk_read = foyer_storage_disk_io_total.counter(&[name, "read"]).boxed(); - let storage_disk_flush = foyer_storage_disk_io_total.counter(&[name, "flush"]).boxed(); + let storage_disk_write = foyer_storage_disk_io_total + .counter(&[name.clone(), "write".into()]) + .boxed(); + let storage_disk_read = foyer_storage_disk_io_total + .counter(&[name.clone(), "read".into()]) + .boxed(); + let storage_disk_flush = foyer_storage_disk_io_total + .counter(&[name.clone(), "flush".into()]) + .boxed(); - let storage_disk_write_bytes = foyer_storage_disk_io_bytes.counter(&[name, "write"]).boxed(); - let storage_disk_read_bytes = foyer_storage_disk_io_bytes.counter(&[name, "read"]).boxed(); + let storage_disk_write_bytes = foyer_storage_disk_io_bytes + .counter(&[name.clone(), "write".into()]) + .boxed(); + let storage_disk_read_bytes = foyer_storage_disk_io_bytes + .counter(&[name.clone(), "read".into()]) + .boxed(); - let storage_disk_write_duration = foyer_storage_disk_io_duration.histogram(&[name, "write"]).boxed(); - let storage_disk_read_duration = foyer_storage_disk_io_duration.histogram(&[name, "read"]).boxed(); - let storage_disk_flush_duration = foyer_storage_disk_io_duration.histogram(&[name, "flush"]).boxed(); + let storage_disk_write_duration = foyer_storage_disk_io_duration + .histogram(&[name.clone(), "write".into()]) + .boxed(); + let storage_disk_read_duration = foyer_storage_disk_io_duration + .histogram(&[name.clone(), "read".into()]) + .boxed(); + let storage_disk_flush_duration = foyer_storage_disk_io_duration + .histogram(&[name.clone(), "flush".into()]) + .boxed(); - let storage_region_total = foyer_storage_region.gauge(&[name, "total"]).boxed(); - let storage_region_clean = foyer_storage_region.gauge(&[name, "clean"]).boxed(); - let storage_region_evictable = foyer_storage_region.gauge(&[name, "evictable"]).boxed(); + let storage_region_total = foyer_storage_region.gauge(&[name.clone(), "total".into()]).boxed(); + let storage_region_clean = foyer_storage_region.gauge(&[name.clone(), "clean".into()]).boxed(); + let storage_region_evictable = foyer_storage_region.gauge(&[name.clone(), "evictable".into()]).boxed(); - let storage_region_size_bytes = foyer_storage_region_size_bytes.gauge(&[name]).boxed(); + let storage_region_size_bytes = foyer_storage_region_size_bytes.gauge(&[name.clone()]).boxed(); let storage_entry_serialize_duration = foyer_storage_entry_serde_duration - .histogram(&[name, "serialize"]) + .histogram(&[name.clone(), "serialize".into()]) .boxed(); let storage_entry_deserialize_duration = foyer_storage_entry_serde_duration - .histogram(&[name, "deserialize"]) + .histogram(&[name.clone(), "deserialize".into()]) .boxed(); /* hybrid cache metrics */ @@ -224,16 +260,26 @@ impl Metrics { &["name", "op"], ); - let hybrid_insert = foyer_hybrid_op_total.counter(&[name, "insert"]).boxed(); - let hybrid_hit = foyer_hybrid_op_total.counter(&[name, "hit"]).boxed(); - let hybrid_miss = foyer_hybrid_op_total.counter(&[name, "miss"]).boxed(); - let hybrid_remove = foyer_hybrid_op_total.counter(&[name, "remove"]).boxed(); + let hybrid_insert = foyer_hybrid_op_total.counter(&[name.clone(), "insert".into()]).boxed(); + let hybrid_hit = foyer_hybrid_op_total.counter(&[name.clone(), "hit".into()]).boxed(); + let hybrid_miss = foyer_hybrid_op_total.counter(&[name.clone(), "miss".into()]).boxed(); + let hybrid_remove = foyer_hybrid_op_total.counter(&[name.clone(), "remove".into()]).boxed(); - let hybrid_insert_duration = foyer_hybrid_op_duration.histogram(&[name, "insert"]).boxed(); - let hybrid_hit_duration = foyer_hybrid_op_duration.histogram(&[name, "hit"]).boxed(); - let hybrid_miss_duration = foyer_hybrid_op_duration.histogram(&[name, "miss"]).boxed(); - let hybrid_remove_duration = foyer_hybrid_op_duration.histogram(&[name, "remove"]).boxed(); - let hybrid_fetch_duration = foyer_hybrid_op_duration.histogram(&[name, "fetch"]).boxed(); + let hybrid_insert_duration = foyer_hybrid_op_duration + .histogram(&[name.clone(), "insert".into()]) + .boxed(); + let hybrid_hit_duration = foyer_hybrid_op_duration + .histogram(&[name.clone(), "hit".into()]) + .boxed(); + let hybrid_miss_duration = foyer_hybrid_op_duration + .histogram(&[name.clone(), "miss".into()]) + .boxed(); + let hybrid_remove_duration = foyer_hybrid_op_duration + .histogram(&[name.clone(), "remove".into()]) + .boxed(); + let hybrid_fetch_duration = foyer_hybrid_op_duration + .histogram(&[name.clone(), "fetch".into()]) + .boxed(); Self { memory_insert, diff --git a/foyer-common/src/metrics/registry/noop.rs b/foyer-common/src/metrics/registry/noop.rs index 73199d9a..f9b7a0c7 100644 --- a/foyer-common/src/metrics/registry/noop.rs +++ b/foyer-common/src/metrics/registry/noop.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::borrow::Cow; + use crate::metrics::{CounterOps, CounterVecOps, GaugeOps, GaugeVecOps, HistogramOps, HistogramVecOps, RegistryOps}; /// Noop metrics placeholder. @@ -23,7 +25,7 @@ impl CounterOps for NoopMetricsRegistry { } impl CounterVecOps for NoopMetricsRegistry { - fn counter(&self, _: &[&'static str]) -> impl CounterOps { + fn counter(&self, _: &[Cow<'static, str>]) -> impl CounterOps { NoopMetricsRegistry } } @@ -37,7 +39,7 @@ impl GaugeOps for NoopMetricsRegistry { } impl GaugeVecOps for NoopMetricsRegistry { - fn gauge(&self, _: &[&'static str]) -> impl GaugeOps { + fn gauge(&self, _: &[Cow<'static, str>]) -> impl GaugeOps { NoopMetricsRegistry } } @@ -47,24 +49,34 @@ impl HistogramOps for NoopMetricsRegistry { } impl HistogramVecOps for NoopMetricsRegistry { - fn histogram(&self, _: &[&'static str]) -> impl HistogramOps { + fn histogram(&self, _: &[Cow<'static, str>]) -> impl HistogramOps { NoopMetricsRegistry } } impl RegistryOps for NoopMetricsRegistry { - fn register_counter_vec(&self, _: &'static str, _: &'static str, _: &'static [&'static str]) -> impl CounterVecOps { + fn register_counter_vec( + &self, + _: impl Into>, + _: impl Into>, + _: &'static [&'static str], + ) -> impl CounterVecOps { NoopMetricsRegistry } - fn register_gauge_vec(&self, _: &'static str, _: &'static str, _: &'static [&'static str]) -> impl GaugeVecOps { + fn register_gauge_vec( + &self, + _: impl Into>, + _: impl Into>, + _: &'static [&'static str], + ) -> impl GaugeVecOps { NoopMetricsRegistry } fn register_histogram_vec( &self, - _: &'static str, - _: &'static str, + _: impl Into>, + _: impl Into>, _: &'static [&'static str], ) -> impl HistogramVecOps { NoopMetricsRegistry @@ -80,17 +92,17 @@ mod tests { let noop = NoopMetricsRegistry; let cv = noop.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]); - let c = cv.counter(&["l1", "l2"]); + let c = cv.counter(&["l1".into(), "l2".into()]); c.increase(42); let gv = noop.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]); - let g = gv.gauge(&["l1", "l2"]); + let g = gv.gauge(&["l1".into(), "l2".into()]); g.increase(514); g.decrease(114); g.absolute(114514); let hv = noop.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]); - let h = hv.histogram(&["l1", "l2"]); + let h = hv.histogram(&["l1".into(), "l2".into()]); h.record(114.514); } } diff --git a/foyer-common/src/metrics/registry/opentelemetry_0_26.rs b/foyer-common/src/metrics/registry/opentelemetry_0_26.rs index 26e7ef06..f2a1281b 100644 --- a/foyer-common/src/metrics/registry/opentelemetry_0_26.rs +++ b/foyer-common/src/metrics/registry/opentelemetry_0_26.rs @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::atomic::{AtomicU64, Ordering}; +use std::{ + borrow::Cow, + sync::atomic::{AtomicU64, Ordering}, +}; use itertools::Itertools; use opentelemetry::{ @@ -78,32 +81,40 @@ impl HistogramOps for Histogram { #[derive(Debug)] pub struct MetricVec { meter: Meter, - name: &'static str, - desc: &'static str, + name: Cow<'static, str>, + desc: Cow<'static, str>, label_names: &'static [&'static str], } impl CounterVecOps for MetricVec { - fn counter(&self, labels: &[&'static str]) -> impl CounterOps { - let counter = self.meter.u64_counter(self.name).with_description(self.desc).init(); + fn counter(&self, labels: &[Cow<'static, str>]) -> impl CounterOps { + let counter = self + .meter + .u64_counter(self.name.clone()) + .with_description(self.desc.clone()) + .init(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); Counter { counter, labels } } } impl GaugeVecOps for MetricVec { - fn gauge(&self, labels: &[&'static str]) -> impl GaugeOps { - let gauge = self.meter.u64_gauge(self.name).with_description(self.desc).init(); + fn gauge(&self, labels: &[Cow<'static, str>]) -> impl GaugeOps { + let gauge = self + .meter + .u64_gauge(self.name.clone()) + .with_description(self.desc.clone()) + .init(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); let val = AtomicU64::new(0); Gauge { val, gauge, labels } @@ -111,13 +122,17 @@ impl GaugeVecOps for MetricVec { } impl HistogramVecOps for MetricVec { - fn histogram(&self, labels: &[&'static str]) -> impl HistogramOps { - let histogram = self.meter.f64_histogram(self.name).with_description(self.desc).init(); + fn histogram(&self, labels: &[Cow<'static, str>]) -> impl HistogramOps { + let histogram = self + .meter + .f64_histogram(self.name.clone()) + .with_description(self.desc.clone()) + .init(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); Histogram { histogram, labels } } @@ -139,45 +154,42 @@ impl OpenTelemetryMetricsRegistry { impl RegistryOps for OpenTelemetryMetricsRegistry { fn register_counter_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl CounterVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } fn register_gauge_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl GaugeVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } fn register_histogram_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl HistogramVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } @@ -193,17 +205,17 @@ mod tests { let ot = OpenTelemetryMetricsRegistry::new(meter); let cv = ot.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]); - let c = cv.counter(&["l1", "l2"]); + let c = cv.counter(&["l1".into(), "l2".into()]); c.increase(42); let gv = ot.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]); - let g = gv.gauge(&["l1", "l2"]); + let g = gv.gauge(&["l1".into(), "l2".into()]); g.increase(514); g.decrease(114); g.absolute(114514); let hv = ot.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]); - let h = hv.histogram(&["l1", "l2"]); + let h = hv.histogram(&["l1".into(), "l2".into()]); h.record(114.514); } } diff --git a/foyer-common/src/metrics/registry/opentelemetry_0_27.rs b/foyer-common/src/metrics/registry/opentelemetry_0_27.rs index 8df31ef4..ed427f0b 100644 --- a/foyer-common/src/metrics/registry/opentelemetry_0_27.rs +++ b/foyer-common/src/metrics/registry/opentelemetry_0_27.rs @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::atomic::{AtomicU64, Ordering}; +use std::{ + borrow::Cow, + sync::atomic::{AtomicU64, Ordering}, +}; use itertools::Itertools; use opentelemetry::{ @@ -78,32 +81,40 @@ impl HistogramOps for Histogram { #[derive(Debug)] pub struct MetricVec { meter: Meter, - name: &'static str, - desc: &'static str, + name: Cow<'static, str>, + desc: Cow<'static, str>, label_names: &'static [&'static str], } impl CounterVecOps for MetricVec { - fn counter(&self, labels: &[&'static str]) -> impl CounterOps { - let counter = self.meter.u64_counter(self.name).with_description(self.desc).build(); + fn counter(&self, labels: &[Cow<'static, str>]) -> impl CounterOps { + let counter = self + .meter + .u64_counter(self.name.clone()) + .with_description(self.desc.clone()) + .build(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); Counter { counter, labels } } } impl GaugeVecOps for MetricVec { - fn gauge(&self, labels: &[&'static str]) -> impl GaugeOps { - let gauge = self.meter.u64_gauge(self.name).with_description(self.desc).build(); + fn gauge(&self, labels: &[Cow<'static, str>]) -> impl GaugeOps { + let gauge = self + .meter + .u64_gauge(self.name.clone()) + .with_description(self.desc.clone()) + .build(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); let val = AtomicU64::new(0); Gauge { val, gauge, labels } @@ -111,13 +122,17 @@ impl GaugeVecOps for MetricVec { } impl HistogramVecOps for MetricVec { - fn histogram(&self, labels: &[&'static str]) -> impl HistogramOps { - let histogram = self.meter.f64_histogram(self.name).with_description(self.desc).build(); + fn histogram(&self, labels: &[Cow<'static, str>]) -> impl HistogramOps { + let histogram = self + .meter + .f64_histogram(self.name.clone()) + .with_description(self.desc.clone()) + .build(); let labels = self .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| KeyValue::new(name.to_string(), label.to_string())) + .map(|(name, label)| KeyValue::new(name.to_string(), label.clone())) .collect(); Histogram { histogram, labels } } @@ -139,45 +154,42 @@ impl OpenTelemetryMetricsRegistry { impl RegistryOps for OpenTelemetryMetricsRegistry { fn register_counter_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl CounterVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } fn register_gauge_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl GaugeVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } fn register_histogram_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl HistogramVecOps { - let meter = self.meter.clone(); MetricVec { - meter, - name, - desc, + meter: self.meter.clone(), + name: name.into(), + desc: desc.into(), label_names, } } @@ -193,17 +205,17 @@ mod tests { let ot = OpenTelemetryMetricsRegistry::new(meter); let cv = ot.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]); - let c = cv.counter(&["l1", "l2"]); + let c = cv.counter(&["l1".into(), "l2".into()]); c.increase(42); let gv = ot.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]); - let g = gv.gauge(&["l1", "l2"]); + let g = gv.gauge(&["l1".into(), "l2".into()]); g.increase(514); g.decrease(114); g.absolute(114514); let hv = ot.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]); - let h = hv.histogram(&["l1", "l2"]); + let h = hv.histogram(&["l1".into(), "l2".into()]); h.record(114.514); } } diff --git a/foyer-common/src/metrics/registry/prometheus.rs b/foyer-common/src/metrics/registry/prometheus.rs index 3d492264..fa04e911 100644 --- a/foyer-common/src/metrics/registry/prometheus.rs +++ b/foyer-common/src/metrics/registry/prometheus.rs @@ -13,11 +13,13 @@ // limitations under the License. use std::{ + borrow::Cow, collections::HashMap, hash::{Hash, Hasher}, sync::{Arc, LazyLock}, }; +use itertools::Itertools; use parking_lot::Mutex; use prometheus::{ register_histogram_vec_with_registry, register_int_counter_vec_with_registry, register_int_gauge_vec_with_registry, @@ -107,8 +109,8 @@ enum MetricVec { #[derive(Debug, Clone, Hash, PartialEq, Eq)] struct Metadata { - name: &'static str, - desc: &'static str, + name: Cow<'static, str>, + desc: Cow<'static, str>, label_names: &'static [&'static str], } @@ -119,8 +121,9 @@ impl CounterOps for IntCounter { } impl CounterVecOps for IntCounterVec { - fn counter(&self, labels: &[&'static str]) -> impl CounterOps { - self.with_label_values(labels) + fn counter(&self, labels: &[Cow<'static, str>]) -> impl CounterOps { + let labels = labels.iter().map(Cow::as_ref).collect_vec(); + self.with_label_values(&labels) } } @@ -139,8 +142,9 @@ impl GaugeOps for IntGauge { } impl GaugeVecOps for IntGaugeVec { - fn gauge(&self, labels: &[&'static str]) -> impl GaugeOps { - self.with_label_values(labels) + fn gauge(&self, labels: &[Cow<'static, str>]) -> impl GaugeOps { + let labels = labels.iter().map(Cow::as_ref).collect_vec(); + self.with_label_values(&labels) } } @@ -151,8 +155,9 @@ impl HistogramOps for Histogram { } impl HistogramVecOps for HistogramVec { - fn histogram(&self, labels: &[&'static str]) -> impl HistogramOps { - self.with_label_values(labels) + fn histogram(&self, labels: &[Cow<'static, str>]) -> impl HistogramOps { + let labels = labels.iter().map(Cow::as_ref).collect_vec(); + self.with_label_values(&labels) } } @@ -192,15 +197,15 @@ impl PrometheusMetricsRegistry { impl RegistryOps for PrometheusMetricsRegistry { fn register_counter_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl CounterVecOps { get_or_register_counter_vec( self, Metadata { - name, - desc, + name: name.into(), + desc: desc.into(), label_names, }, ) @@ -208,15 +213,15 @@ impl RegistryOps for PrometheusMetricsRegistry { fn register_gauge_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl GaugeVecOps { get_or_register_gauge_vec( self, Metadata { - name, - desc, + name: name.into(), + desc: desc.into(), label_names, }, ) @@ -224,15 +229,15 @@ impl RegistryOps for PrometheusMetricsRegistry { fn register_histogram_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl HistogramVecOps { get_or_register_histogram_vec( self, Metadata { - name, - desc, + name: name.into(), + desc: desc.into(), label_names, }, ) @@ -245,17 +250,17 @@ mod tests { fn case(registry: &PrometheusMetricsRegistry) { let cv = registry.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]); - let c = cv.counter(&["l1", "l2"]); + let c = cv.counter(&["l1".into(), "l2".into()]); c.increase(42); let gv = registry.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]); - let g = gv.gauge(&["l1", "l2"]); + let g = gv.gauge(&["l1".into(), "l2".into()]); g.increase(514); g.decrease(114); g.absolute(114514); let hv = registry.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]); - let h = hv.histogram(&["l1", "l2"]); + let h = hv.histogram(&["l1".into(), "l2".into()]); h.record(114.514); } diff --git a/foyer-common/src/metrics/registry/prometheus_client_0_22.rs b/foyer-common/src/metrics/registry/prometheus_client_0_22.rs index bef64f12..8b4b974b 100644 --- a/foyer-common/src/metrics/registry/prometheus_client_0_22.rs +++ b/foyer-common/src/metrics/registry/prometheus_client_0_22.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use itertools::Itertools; use parking_lot::Mutex; @@ -28,7 +28,7 @@ use crate::metrics::{CounterOps, CounterVecOps, GaugeOps, GaugeVecOps, Histogram #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct Labels { - pairs: Vec<(&'static str, &'static str)>, + pairs: Vec<(&'static str, Cow<'static, str>)>, } impl EncodeLabelSet for Labels { @@ -59,7 +59,7 @@ struct CounterVec { } impl CounterVecOps for CounterVec { - fn counter(&self, labels: &[&'static str]) -> impl CounterOps { + fn counter(&self, labels: &[Cow<'static, str>]) -> impl CounterOps { Counter { counter: self.counter.clone(), labels: Labels { @@ -67,7 +67,7 @@ impl CounterVecOps for CounterVec { .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| (*name, *label)) + .map(|(name, label)| (*name, label.clone())) .collect(), }, } @@ -101,7 +101,7 @@ struct GaugeVec { } impl GaugeVecOps for GaugeVec { - fn gauge(&self, labels: &[&'static str]) -> impl GaugeOps { + fn gauge(&self, labels: &[Cow<'static, str>]) -> impl GaugeOps { Gauge { gauge: self.gauge.clone(), labels: Labels { @@ -109,7 +109,7 @@ impl GaugeVecOps for GaugeVec { .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| (*name, *label)) + .map(|(name, label)| (*name, label.clone())) .collect(), }, } @@ -135,7 +135,7 @@ struct HistogramVec { } impl HistogramVecOps for HistogramVec { - fn histogram(&self, labels: &[&'static str]) -> impl HistogramOps { + fn histogram(&self, labels: &[Cow<'static, str>]) -> impl HistogramOps { Histogram { histogram: self.histogram.clone(), labels: Labels { @@ -143,7 +143,7 @@ impl HistogramVecOps for HistogramVec { .label_names .iter() .zip_eq(labels.iter()) - .map(|(name, label)| (*name, *label)) + .map(|(name, label)| (*name, label.clone())) .collect(), }, } @@ -166,36 +166,38 @@ impl PrometheusClientMetricsRegistry { impl RegistryOps for PrometheusClientMetricsRegistry { fn register_counter_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl CounterVecOps { let counter = Family::::default(); - self.registry.lock().register(name, desc, counter.clone()); + self.registry.lock().register(name.into(), desc.into(), counter.clone()); CounterVec { counter, label_names } } fn register_gauge_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl GaugeVecOps { let gauge = Family::::default(); - self.registry.lock().register(name, desc, gauge.clone()); + self.registry.lock().register(name.into(), desc.into(), gauge.clone()); GaugeVec { gauge, label_names } } fn register_histogram_vec( &self, - name: &'static str, - desc: &'static str, + name: impl Into>, + desc: impl Into>, label_names: &'static [&'static str], ) -> impl HistogramVecOps { let histogram = Family::::new_with_constructor(|| { PcHistogram::new([0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0].into_iter()) }); - self.registry.lock().register(name, desc, histogram.clone()); + self.registry + .lock() + .register(name.into(), desc.into(), histogram.clone()); HistogramVec { histogram, label_names } } } @@ -212,17 +214,17 @@ mod tests { let pc = PrometheusClientMetricsRegistry::new(registry.clone()); let cv = pc.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]); - let c = cv.counter(&["l1", "l2"]); + let c = cv.counter(&["l1".into(), "l2".into()]); c.increase(42); let gv = pc.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]); - let g = gv.gauge(&["l1", "l2"]); + let g = gv.gauge(&["l1".into(), "l2".into()]); g.increase(514); g.decrease(114); g.absolute(114514); let hv = pc.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]); - let h = hv.histogram(&["l1", "l2"]); + let h = hv.histogram(&["l1".into(), "l2".into()]); h.record(114.514); let mut text = String::new(); diff --git a/foyer-memory/src/cache.rs b/foyer-memory/src/cache.rs index 4a4ec71e..59be8408 100644 --- a/foyer-memory/src/cache.rs +++ b/foyer-memory/src/cache.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{fmt::Debug, future::Future, hash::Hash, ops::Deref, sync::Arc}; +use std::{borrow::Cow, fmt::Debug, future::Future, hash::Hash, ops::Deref, sync::Arc}; use ahash::RandomState; use equivalent::Equivalent; @@ -272,7 +272,7 @@ where V: Value, S: HashBuilder, { - name: &'static str, + name: Cow<'static, str>, capacity: usize, shards: usize, @@ -295,7 +295,7 @@ where /// Create a new in-memory cache builder. pub fn new(capacity: usize) -> Self { Self { - name: "foyer", + name: "foyer".into(), capacity, shards: 8, @@ -322,8 +322,8 @@ where /// foyer will use the name as the prefix of the metric names. /// /// Default: `foyer`. - pub fn with_name(mut self, name: &'static str) -> Self { - self.name = name; + pub fn with_name(mut self, name: impl Into>) -> Self { + self.name = name.into(); self } diff --git a/foyer-storage/src/store.rs b/foyer-storage/src/store.rs index 7a7bada8..affba40b 100644 --- a/foyer-storage/src/store.rs +++ b/foyer-storage/src/store.rs @@ -13,6 +13,7 @@ // limitations under the License. use std::{ + borrow::Cow, fmt::{Debug, Display}, hash::Hash, marker::PhantomData, @@ -344,7 +345,7 @@ where V: StorageValue, S: HashBuilder + Debug, { - name: &'static str, + name: Cow<'static, str>, memory: Cache, metrics: Arc, @@ -368,13 +369,18 @@ where S: HashBuilder + Debug, { /// Setup disk cache store for the given in-memory cache. - pub fn new(name: &'static str, memory: Cache, metrics: Arc, engine: Engine) -> Self { + pub fn new( + name: impl Into>, + memory: Cache, + metrics: Arc, + engine: Engine, + ) -> Self { if matches!(engine, Engine::Mixed(ratio) if !(0.0..=1.0).contains(&ratio)) { panic!("mixed engine small object disk cache ratio must be a f64 in range [0.0, 1.0]"); } Self { - name, + name: name.into(), memory, metrics, diff --git a/foyer/src/hybrid/builder.rs b/foyer/src/hybrid/builder.rs index 0f53e7de..dee82046 100644 --- a/foyer/src/hybrid/builder.rs +++ b/foyer/src/hybrid/builder.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{fmt::Debug, sync::Arc}; +use std::{borrow::Cow, fmt::Debug, sync::Arc}; use ahash::RandomState; use foyer_common::{ @@ -31,7 +31,7 @@ use crate::HybridCache; /// Hybrid cache builder. pub struct HybridCacheBuilder { - name: &'static str, + name: Cow<'static, str>, event_listener: Option>>, tracing_options: TracingOptions, registry: M, @@ -47,7 +47,7 @@ impl HybridCacheBuilder { /// Create a new hybrid cache builder. pub fn new() -> Self { Self { - name: "foyer", + name: "foyer".into(), event_listener: None, tracing_options: TracingOptions::default(), registry: NoopMetricsRegistry, @@ -61,8 +61,8 @@ impl HybridCacheBuilder { /// foyer will use the name as the prefix of the metric names. /// /// Default: `foyer`. - pub fn with_name(mut self, name: &'static str) -> Self { - self.name = name; + pub fn with_name(mut self, name: impl Into>) -> Self { + self.name = name.into(); self } @@ -104,9 +104,9 @@ impl HybridCacheBuilder { V: StorageValue, M: RegistryOps, { - let metrics = Arc::new(Metrics::new(self.name, &self.registry)); + let metrics = Arc::new(Metrics::new(self.name.clone(), &self.registry)); let mut builder = CacheBuilder::new(capacity) - .with_name(self.name) + .with_name(self.name.clone()) .with_metrics(metrics.clone()); if let Some(event_listener) = self.event_listener { builder = builder.with_event_listener(event_listener); @@ -127,7 +127,7 @@ where V: StorageValue, S: HashBuilder + Debug, { - name: &'static str, + name: Cow<'static, str>, tracing_options: TracingOptions, metrics: Arc, // `NoopMetricsRegistry` here will be ignored, for its metrics is already set. @@ -194,7 +194,7 @@ where pub fn storage(self, engine: Engine) -> HybridCacheBuilderPhaseStorage { let memory = self.builder.build(); HybridCacheBuilderPhaseStorage { - builder: StoreBuilder::new(self.name, memory.clone(), self.metrics.clone(), engine), + builder: StoreBuilder::new(self.name.clone(), memory.clone(), self.metrics.clone(), engine), name: self.name, tracing_options: self.tracing_options, metrics: self.metrics, @@ -210,7 +210,7 @@ where V: StorageValue, S: HashBuilder + Debug, { - name: &'static str, + name: Cow<'static, str>, tracing_options: TracingOptions, metrics: Arc, memory: Cache,