Skip to content

Commit

Permalink
use AsRef<str> for slice of string labels
Browse files Browse the repository at this point in the history
Signed-off-by: Xinye <[email protected]>
  • Loading branch information
Xinye committed Nov 8, 2024
1 parent f0c9bc2 commit ae26914
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 35 deletions.
20 changes: 13 additions & 7 deletions src/counter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ impl<P: Atomic> GenericCounter<P> {

/// Create a [`GenericCounter`] with the `opts` options.
pub fn with_opts(opts: Opts) -> Result<Self> {
Self::with_opts_and_label_values(&opts, &[])
Self::with_opts_and_label_values::<&str>(&opts, &[])
}

fn with_opts_and_label_values(opts: &Opts, label_values: &[&str]) -> Result<Self> {
fn with_opts_and_label_values<L: AsRef<str>>(opts: &Opts, label_values: &[L]) -> Result<Self> {
let v = Value::new(opts, ValueType::Counter, P::T::from_i64(0), label_values)?;
Ok(Self { v: Arc::new(v) })
}
Expand Down Expand Up @@ -126,7 +126,7 @@ impl<P: Atomic> MetricVecBuilder for CounterVecBuilder<P> {
type M = GenericCounter<P>;
type P = Opts;

fn build(&self, opts: &Opts, vals: &[&str]) -> Result<Self::M> {
fn build<L: AsRef<str>>(&self, opts: &Opts, vals: &[L]) -> Result<Self::M> {
Self::M::with_opts_and_label_values(opts, vals)
}
}
Expand All @@ -148,8 +148,11 @@ impl<P: Atomic> GenericCounterVec<P> {
/// Create a new [`GenericCounterVec`] based on the provided
/// [`Opts`] and partitioned by the given label names. At least one label name must be
/// provided.
pub fn new(opts: Opts, label_names: &[&str]) -> Result<Self> {
let variable_names = label_names.iter().map(|s| (*s).to_owned()).collect();
pub fn new<L: AsRef<str>>(opts: Opts, label_names: &[L]) -> Result<Self> {
let variable_names = label_names
.iter()
.map(|s| (*s).as_ref().to_owned())
.collect();
let opts = opts.variable_labels(variable_names);
let metric_vec =
MetricVec::create(proto::MetricType::COUNTER, CounterVecBuilder::new(), opts)?;
Expand Down Expand Up @@ -283,7 +286,10 @@ impl<P: Atomic> GenericLocalCounterVec<P> {

/// Get a [`GenericLocalCounter`] by label values.
/// See more [MetricVec::with_label_values].
pub fn with_label_values<'a>(&'a mut self, vals: &[&str]) -> &'a mut GenericLocalCounter<P> {
pub fn with_label_values<'a, L: AsRef<str>>(
&'a mut self,
vals: &[L],
) -> &'a mut GenericLocalCounter<P> {
let hash = self.vec.v.hash_label_values(vals).unwrap();
let vec = &self.vec;
self.local
Expand All @@ -293,7 +299,7 @@ impl<P: Atomic> GenericLocalCounterVec<P> {

/// Remove a [`GenericLocalCounter`] by label values.
/// See more [MetricVec::remove_label_values].
pub fn remove_label_values(&mut self, vals: &[&str]) -> Result<()> {
pub fn remove_label_values<L: AsRef<str>>(&mut self, vals: &[L]) -> Result<()> {
let hash = self.vec.v.hash_label_values(vals)?;
self.local.remove(&hash);
self.vec.v.delete_label_values(vals)
Expand Down
13 changes: 8 additions & 5 deletions src/gauge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ impl<P: Atomic> GenericGauge<P> {

/// Create a [`GenericGauge`] with the `opts` options.
pub fn with_opts(opts: Opts) -> Result<Self> {
Self::with_opts_and_label_values(&opts, &[])
Self::with_opts_and_label_values::<&str>(&opts, &[])
}

fn with_opts_and_label_values(opts: &Opts, label_values: &[&str]) -> Result<Self> {
fn with_opts_and_label_values<L: AsRef<str>>(opts: &Opts, label_values: &[L]) -> Result<Self> {
let v = Value::new(opts, ValueType::Gauge, P::T::from_i64(0), label_values)?;
Ok(Self { v: Arc::new(v) })
}
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<P: Atomic> MetricVecBuilder for GaugeVecBuilder<P> {
type M = GenericGauge<P>;
type P = Opts;

fn build(&self, opts: &Opts, vals: &[&str]) -> Result<Self::M> {
fn build<L: AsRef<str>>(&self, opts: &Opts, vals: &[L]) -> Result<Self::M> {
Self::M::with_opts_and_label_values(opts, vals)
}
}
Expand All @@ -151,8 +151,11 @@ impl<P: Atomic> GenericGaugeVec<P> {
/// Create a new [`GenericGaugeVec`] based on the provided
/// [`Opts`] and partitioned by the given label names. At least one label name must
/// be provided.
pub fn new(opts: Opts, label_names: &[&str]) -> Result<Self> {
let variable_names = label_names.iter().map(|s| (*s).to_owned()).collect();
pub fn new<L: AsRef<str>>(opts: Opts, label_names: &[L]) -> Result<Self> {
let variable_names = label_names
.iter()
.map(|s| (*s).as_ref().to_owned())
.collect();
let opts = opts.variable_labels(variable_names);
let metric_vec = MetricVec::create(proto::MetricType::GAUGE, GaugeVecBuilder::new(), opts)?;

Expand Down
21 changes: 12 additions & 9 deletions src/histogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ pub struct HistogramCore {
}

impl HistogramCore {
pub fn new(opts: &HistogramOpts, label_values: &[&str]) -> Result<HistogramCore> {
pub fn new<L: AsRef<str>>(opts: &HistogramOpts, label_values: &[L]) -> Result<HistogramCore> {
let desc = opts.describe()?;

for name in &desc.variable_labels {
Expand Down Expand Up @@ -674,12 +674,12 @@ pub struct Histogram {
impl Histogram {
/// `with_opts` creates a [`Histogram`] with the `opts` options.
pub fn with_opts(opts: HistogramOpts) -> Result<Histogram> {
Histogram::with_opts_and_label_values(&opts, &[])
Histogram::with_opts_and_label_values::<&str>(&opts, &[])
}

fn with_opts_and_label_values(
fn with_opts_and_label_values<L: AsRef<str>>(
opts: &HistogramOpts,
label_values: &[&str],
label_values: &[L],
) -> Result<Histogram> {
let core = HistogramCore::new(opts, label_values)?;

Expand Down Expand Up @@ -783,7 +783,7 @@ impl MetricVecBuilder for HistogramVecBuilder {
type M = Histogram;
type P = HistogramOpts;

fn build(&self, opts: &HistogramOpts, vals: &[&str]) -> Result<Histogram> {
fn build<L: AsRef<str>>(&self, opts: &HistogramOpts, vals: &[L]) -> Result<Histogram> {
Histogram::with_opts_and_label_values(opts, vals)
}
}
Expand All @@ -798,8 +798,11 @@ impl HistogramVec {
/// Create a new [`HistogramVec`] based on the provided
/// [`HistogramOpts`] and partitioned by the given label names. At least
/// one label name must be provided.
pub fn new(opts: HistogramOpts, label_names: &[&str]) -> Result<HistogramVec> {
let variable_names = label_names.iter().map(|s| (*s).to_owned()).collect();
pub fn new<L: AsRef<str>>(opts: HistogramOpts, label_names: &[L]) -> Result<HistogramVec> {
let variable_names = label_names
.iter()
.map(|s| (*s).as_ref().to_owned())
.collect();
let opts = opts.variable_labels(variable_names);
let metric_vec =
MetricVec::create(proto::MetricType::HISTOGRAM, HistogramVecBuilder {}, opts)?;
Expand Down Expand Up @@ -1168,7 +1171,7 @@ impl LocalHistogramVec {

/// Get a [`LocalHistogram`] by label values.
/// See more [`MetricVec::with_label_values`].
pub fn with_label_values<'a>(&'a mut self, vals: &[&str]) -> &'a LocalHistogram {
pub fn with_label_values<'a, L: AsRef<str>>(&'a mut self, vals: &[L]) -> &'a LocalHistogram {
let hash = self.vec.v.hash_label_values(vals).unwrap();
let vec = &self.vec;
self.local
Expand All @@ -1178,7 +1181,7 @@ impl LocalHistogramVec {

/// Remove a [`LocalHistogram`] by label values.
/// See more [`MetricVec::remove_label_values`].
pub fn remove_label_values(&mut self, vals: &[&str]) -> Result<()> {
pub fn remove_label_values<L: AsRef<str>>(&mut self, vals: &[L]) -> Result<()> {
let hash = self.vec.v.hash_label_values(vals)?;
self.local.remove(&hash);
self.vec.v.delete_label_values(vals)
Expand Down
8 changes: 4 additions & 4 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ pub struct Value<P: Atomic> {
}

impl<P: Atomic> Value<P> {
pub fn new<D: Describer>(
pub fn new<D: Describer, L: AsRef<str>>(
describer: &D,
val_type: ValueType,
val: P::T,
label_values: &[&str],
label_values: &[L],
) -> Result<Self> {
let desc = describer.describe()?;
let label_pairs = make_label_pairs(&desc, label_values)?;
Expand Down Expand Up @@ -115,7 +115,7 @@ impl<P: Atomic> Value<P> {
}
}

pub fn make_label_pairs(desc: &Desc, label_values: &[&str]) -> Result<Vec<LabelPair>> {
pub fn make_label_pairs<L: AsRef<str>>(desc: &Desc, label_values: &[L]) -> Result<Vec<LabelPair>> {
if desc.variable_labels.len() != label_values.len() {
return Err(Error::InconsistentCardinality {
expect: desc.variable_labels.len(),
Expand All @@ -136,7 +136,7 @@ pub fn make_label_pairs(desc: &Desc, label_values: &[&str]) -> Result<Vec<LabelP
for (i, n) in desc.variable_labels.iter().enumerate() {
let mut label_pair = LabelPair::default();
label_pair.set_name(n.clone());
label_pair.set_value(label_values[i].to_owned());
label_pair.set_value(label_values[i].as_ref().to_owned());
label_pairs.push(label_pair);
}

Expand Down
28 changes: 18 additions & 10 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub trait MetricVecBuilder: Send + Sync + Clone {
type P: Describer + Sync + Send + Clone;

/// `build` builds a [`Metric`] with option and corresponding label names.
fn build(&self, _: &Self::P, _: &[&str]) -> Result<Self::M>;
fn build<L: AsRef<str>>(&self, _: &Self::P, _: &[L]) -> Result<Self::M>;
}

#[derive(Debug)]
Expand Down Expand Up @@ -49,7 +49,7 @@ impl<T: MetricVecBuilder> MetricVecCore<T> {
m
}

pub fn get_metric_with_label_values(&self, vals: &[&str]) -> Result<T::M> {
pub fn get_metric_with_label_values<L: AsRef<str>>(&self, vals: &[L]) -> Result<T::M> {
let h = self.hash_label_values(vals)?;

if let Some(metric) = self.children.read().get(&h).cloned() {
Expand All @@ -70,12 +70,20 @@ impl<T: MetricVecBuilder> MetricVecCore<T> {
self.get_or_create_metric(h, &vals)
}

pub fn delete_label_values(&self, vals: &[&str]) -> Result<()> {
pub fn delete_label_values<L: AsRef<str>>(&self, vals: &[L]) -> Result<()> {
let h = self.hash_label_values(vals)?;

let mut children = self.children.write();
if children.remove(&h).is_none() {
return Err(Error::Msg(format!("missing label values {:?}", vals)));
let format_labels = vals
.iter()
.map(|l| l.as_ref())
.collect::<Vec<&str>>()
.join(", ");
return Err(Error::Msg(format!(
"missing label values [{}]",
format_labels
)));
}

Ok(())
Expand All @@ -97,7 +105,7 @@ impl<T: MetricVecBuilder> MetricVecCore<T> {
self.children.write().clear();
}

pub(crate) fn hash_label_values(&self, vals: &[&str]) -> Result<u64> {
pub(crate) fn hash_label_values<L: AsRef<str>>(&self, vals: &[L]) -> Result<u64> {
if vals.len() != self.desc.variable_labels.len() {
return Err(Error::InconsistentCardinality {
expect: self.desc.variable_labels.len(),
Expand All @@ -107,7 +115,7 @@ impl<T: MetricVecBuilder> MetricVecCore<T> {

let mut h = FnvHasher::default();
for val in vals {
h.write(val.as_bytes());
h.write(val.as_ref().as_bytes());
}

Ok(h.finish())
Expand Down Expand Up @@ -153,7 +161,7 @@ impl<T: MetricVecBuilder> MetricVecCore<T> {
Ok(values)
}

fn get_or_create_metric(&self, hash: u64, label_values: &[&str]) -> Result<T::M> {
fn get_or_create_metric<L: AsRef<str>>(&self, hash: u64, label_values: &[L]) -> Result<T::M> {
let mut children = self.children.write();
// Check exist first.
if let Some(metric) = children.get(&hash).cloned() {
Expand Down Expand Up @@ -221,7 +229,7 @@ impl<T: MetricVecBuilder> MetricVec<T> {
/// an alternative to avoid that type of mistake. For higher label numbers, the
/// latter has a much more readable (albeit more verbose) syntax, but it comes
/// with a performance overhead (for creating and processing the Labels map).
pub fn get_metric_with_label_values(&self, vals: &[&str]) -> Result<T::M> {
pub fn get_metric_with_label_values<L: AsRef<str>>(&self, vals: &[L]) -> Result<T::M> {
self.v.get_metric_with_label_values(vals)
}

Expand Down Expand Up @@ -254,7 +262,7 @@ impl<T: MetricVecBuilder> MetricVec<T> {
/// ).unwrap();
/// vec.with_label_values(&["404", "POST"]).inc()
/// ```
pub fn with_label_values(&self, vals: &[&str]) -> T::M {
pub fn with_label_values<L: AsRef<str>>(&self, vals: &[L]) -> T::M {
self.get_metric_with_label_values(vals).unwrap()
}

Expand All @@ -277,7 +285,7 @@ impl<T: MetricVecBuilder> MetricVec<T> {
/// alternative to avoid that type of mistake. For higher label numbers, the
/// latter has a much more readable (albeit more verbose) syntax, but it comes
/// with a performance overhead (for creating and processing the Labels map).
pub fn remove_label_values(&self, vals: &[&str]) -> Result<()> {
pub fn remove_label_values<L: AsRef<str>>(&self, vals: &[L]) -> Result<()> {
self.v.delete_label_values(vals)
}

Expand Down

0 comments on commit ae26914

Please sign in to comment.