1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
use core::fmt;
use vector_common::byte_size_of::ByteSizeOf;
use vector_config::configurable_component;
use super::{write_list, write_word, MetricTags, TagValue};
/// Metrics series.
#[configurable_component]
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct MetricSeries {
#[serde(flatten)]
pub name: MetricName,
#[configurable(derived)]
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<MetricTags>,
}
impl MetricSeries {
/// Gets a reference to the name of the series.
pub fn name(&self) -> &MetricName {
&self.name
}
/// Gets a mutable reference to the name of the series.
pub fn name_mut(&mut self) -> &mut MetricName {
&mut self.name
}
/// Gets an optional reference to the tags of the series.
pub fn tags(&self) -> Option<&MetricTags> {
self.tags.as_ref()
}
/// Gets an optional mutable reference to the tags of the series.
pub fn tags_mut(&mut self) -> &mut Option<MetricTags> {
&mut self.tags
}
/// Sets or updates the string value of a tag.
///
/// *Note:* This will create the tags map if it is not present.
pub fn replace_tag(&mut self, key: String, value: impl Into<TagValue>) -> Option<String> {
(self.tags.get_or_insert_with(Default::default)).replace(key, value)
}
pub fn set_multi_value_tag(&mut self, key: String, values: impl IntoIterator<Item = TagValue>) {
(self.tags.get_or_insert_with(Default::default)).set_multi_value(key, values);
}
/// Removes all the tags.
pub fn remove_tags(&mut self) {
self.tags = None;
}
/// Removes the tag entry for the named key, if it exists, and returns the old value.
///
/// *Note:* This will drop the tags map if the tag was the last entry in it.
pub fn remove_tag(&mut self, key: &str) -> Option<String> {
match &mut self.tags {
None => None,
Some(tags) => {
let result = tags.remove(key);
if tags.is_empty() {
self.tags = None;
}
result
}
}
}
}
impl ByteSizeOf for MetricSeries {
fn allocated_bytes(&self) -> usize {
self.name.allocated_bytes() + self.tags.allocated_bytes()
}
}
/// Metric name.
#[configurable_component]
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct MetricName {
/// The name of the metric.
///
/// This would typically be a name for the metric itself, unrelated to where the metric
/// originates from. For example, if the metric represented the amount of used system memory, it
/// may be called `memory.used`.
pub name: String,
/// The namespace of the metric.
///
/// Namespace represents a grouping for a metric where the name itself may otherwise be too
/// generic. For example, while the name of a metric may be `memory.used` for the amount of used
/// system memory, the namespace could differentiate that by being `system` for the total amount
/// of used memory across the system, or `vector` for the amount of used system memory specific
/// to Vector, and so on.
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
}
impl MetricName {
/// Gets a reference to the name component of this name.
pub fn name(&self) -> &str {
self.name.as_str()
}
/// Gets a mutable reference to the name component of this name.
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
/// Gets a reference to the namespace component of this name.
pub fn namespace(&self) -> Option<&String> {
self.namespace.as_ref()
}
/// Gets a mutable reference to the namespace component of this name.
pub fn namespace_mut(&mut self) -> &mut Option<String> {
&mut self.namespace
}
}
impl fmt::Display for MetricSeries {
/// Display a metric series name using something like Prometheus' text format:
///
/// ```text
/// NAMESPACE_NAME{TAGS}
/// ```
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
if let Some(namespace) = &self.name.namespace {
write_word(fmt, namespace)?;
write!(fmt, "_")?;
}
write_word(fmt, &self.name.name)?;
write!(fmt, "{{")?;
if let Some(tags) = &self.tags {
write_list(fmt, ",", tags.iter_all(), |fmt, (tag, value)| {
write_word(fmt, tag).and_then(|()| match value {
Some(value) => write!(fmt, "={value:?}"),
None => Ok(()),
})
})?;
}
write!(fmt, "}}")
}
}
impl ByteSizeOf for MetricName {
fn allocated_bytes(&self) -> usize {
self.name.allocated_bytes() + self.namespace.allocated_bytes()
}
}