witchcraft_metrics/
metric_id.rs1use std::borrow::Cow;
15use std::collections::{btree_map, BTreeMap};
16
17#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
21pub struct MetricId {
22 name: Cow<'static, str>,
23 tags: Tags,
24}
25
26impl MetricId {
27 pub fn new<T>(name: T) -> MetricId
29 where
30 T: Into<Cow<'static, str>>,
31 {
32 MetricId {
33 name: name.into(),
34 tags: Tags(BTreeMap::new()),
35 }
36 }
37
38 pub fn with_tag<K, V>(mut self, key: K, value: V) -> MetricId
40 where
41 K: Into<Cow<'static, str>>,
42 V: Into<Cow<'static, str>>,
43 {
44 self.tags.0.insert(key.into(), value.into());
45 self
46 }
47
48 #[inline]
50 pub fn name(&self) -> &str {
51 &self.name
52 }
53
54 #[inline]
56 pub fn tags(&self) -> &Tags {
57 &self.tags
58 }
59}
60
61impl From<String> for MetricId {
62 #[inline]
63 fn from(s: String) -> Self {
64 MetricId::new(s)
65 }
66}
67
68impl From<&'static str> for MetricId {
69 #[inline]
70 fn from(s: &'static str) -> Self {
71 MetricId::new(s)
72 }
73}
74
75impl From<Cow<'static, str>> for MetricId {
76 #[inline]
77 fn from(s: Cow<'static, str>) -> MetricId {
78 MetricId::new(s)
79 }
80}
81
82#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
84pub struct Tags(BTreeMap<Cow<'static, str>, Cow<'static, str>>);
85
86impl Tags {
87 #[inline]
89 pub fn iter(&self) -> TagsIter<'_> {
90 TagsIter(self.0.iter())
91 }
92}
93
94impl<'a> IntoIterator for &'a Tags {
95 type Item = (&'a str, &'a str);
96 type IntoIter = TagsIter<'a>;
97
98 #[inline]
99 fn into_iter(self) -> TagsIter<'a> {
100 self.iter()
101 }
102}
103
104pub struct TagsIter<'a>(btree_map::Iter<'a, Cow<'static, str>, Cow<'static, str>>);
106
107impl<'a> Iterator for TagsIter<'a> {
108 type Item = (&'a str, &'a str);
109
110 #[inline]
111 fn next(&mut self) -> Option<Self::Item> {
112 self.0.next().map(|(k, v)| (&**k, &**v))
113 }
114
115 #[inline]
116 fn size_hint(&self) -> (usize, Option<usize>) {
117 self.0.size_hint()
118 }
119}
120
121impl<'a> ExactSizeIterator for TagsIter<'a> {}
122
123#[cfg(test)]
124mod test {
125 use crate::MetricId;
126
127 #[test]
128 fn basic() {
129 let id = MetricId::new("foo.bar")
130 .with_tag("a", "b")
131 .with_tag("fizz", "buzz")
132 .with_tag("fizz", "bazz");
133
134 assert_eq!(id.name(), "foo.bar");
135 assert_eq!(
136 id.tags().iter().collect::<Vec<_>>(),
137 &[("a", "b"), ("fizz", "bazz")]
138 );
139 }
140}