rocketmq_observability/
attributes.rs1use crate::config::ObservabilityConfig;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct Attribute {
19 pub key: &'static str,
20 pub value: String,
21}
22
23pub fn base_attributes(config: &ObservabilityConfig) -> Vec<Attribute> {
24 let mut attributes = vec![
25 Attribute::new("cluster", &config.cluster),
26 Attribute::new("node_type", &config.node_type),
27 ];
28
29 if !config.node_id.is_empty() {
30 attributes.push(Attribute::new("node_id", &config.node_id));
31 }
32
33 attributes
34}
35
36impl Attribute {
37 pub fn new(key: &'static str, value: impl Into<String>) -> Self {
38 Self {
39 key,
40 value: value.into(),
41 }
42 }
43}
44
45#[cfg(feature = "otel-metrics")]
47type KeyValues = smallvec::SmallVec<[opentelemetry::KeyValue; 4]>;
48
49#[derive(Debug, Clone, Default, PartialEq)]
55pub struct MetricAttributes {
56 #[cfg(feature = "otel-metrics")]
57 key_values: KeyValues,
58}
59
60impl MetricAttributes {
61 pub fn new() -> Self {
63 Self::default()
64 }
65
66 #[must_use]
68 pub fn with(self, key: &'static str, value: impl Into<String>) -> Self {
69 #[cfg(feature = "otel-metrics")]
70 {
71 let mut attributes = self;
72 attributes
73 .key_values
74 .push(opentelemetry::KeyValue::new(key, value.into()));
75 attributes
76 }
77 #[cfg(not(feature = "otel-metrics"))]
78 {
79 let _ = (key, value);
80 self
81 }
82 }
83}
84
85#[cfg(feature = "otel-metrics")]
86impl MetricAttributes {
87 pub(crate) fn from_key_values(key_values: Vec<opentelemetry::KeyValue>) -> Self {
89 Self {
90 key_values: KeyValues::from_vec(key_values),
91 }
92 }
93
94 pub(crate) fn from_array<const N: usize>(key_values: [opentelemetry::KeyValue; N]) -> Self {
96 Self {
97 key_values: key_values.into_iter().collect(),
98 }
99 }
100
101 pub(crate) fn as_key_values(&self) -> &[opentelemetry::KeyValue] {
102 &self.key_values
103 }
104
105 pub(crate) fn push(&mut self, key_value: opentelemetry::KeyValue) {
106 self.key_values.push(key_value);
107 }
108
109 pub(crate) fn extend(&mut self, key_values: impl IntoIterator<Item = opentelemetry::KeyValue>) {
110 self.key_values.extend(key_values);
111 }
112}
113
114#[cfg(all(test, feature = "otel-metrics"))]
115mod tests {
116 use opentelemetry::KeyValue;
117
118 use super::MetricAttributes;
119
120 #[test]
121 fn with_appends_string_attributes_in_order() {
122 let attributes = MetricAttributes::new()
123 .with("topic", "TopicA")
124 .with("group", String::from("GroupA"));
125
126 assert_eq!(
127 attributes.as_key_values(),
128 &[KeyValue::new("topic", "TopicA"), KeyValue::new("group", "GroupA")]
129 );
130 }
131}