Skip to main content

zenoh_stats/
labels.rs

1use std::{
2    borrow::Cow,
3    fmt,
4    fmt::{Error, Write},
5    ops::Deref,
6};
7
8use prometheus_client::encoding::{
9    EncodeLabelSet, EncodeLabelValue, LabelSetEncoder, LabelValueEncoder,
10};
11use zenoh_protocol::{
12    core::{Locator, Priority, WhatAmI, ZenohIdProto},
13    network::NetworkBodyRef,
14    zenoh::{PushBody, ResponseBody},
15};
16
17// Because of `prometheus_client` lack of blanket impl
18pub(crate) struct LabelsSetRef<'a, S>(pub(crate) &'a S);
19impl<S: EncodeLabelSet> EncodeLabelSet for LabelsSetRef<'_, S> {
20    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), Error> {
21        self.0.encode(encoder)
22    }
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub enum ResourceLabel {
27    Subscriber,
28    Queryable,
29    Token,
30}
31
32impl EncodeLabelValue for ResourceLabel {
33    fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
34        encoder.write_str(match self {
35            Self::Subscriber => "subscriber",
36            Self::Queryable => "queryable",
37            Self::Token => "token",
38        })
39    }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub enum LocalityLabel {
44    Local,
45    Remote,
46}
47
48impl EncodeLabelValue for LocalityLabel {
49    fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
50        encoder.write_str(match self {
51            Self::Local => "local",
52            Self::Remote => "remote",
53        })
54    }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
58pub enum MessageLabel {
59    Put,
60    Del,
61    Query,
62    Reply,
63    ReplyErr,
64    ResponseFinal,
65    Interest,
66    Declare,
67    Oam,
68}
69
70impl MessageLabel {
71    pub(crate) const NUM: usize = 9;
72}
73
74impl EncodeLabelValue for MessageLabel {
75    fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
76        encoder.write_str(match self {
77            Self::Put => "put",
78            Self::Del => "delete",
79            Self::Query => "query",
80            Self::Reply => "reply",
81            Self::ReplyErr => "reply-err",
82            Self::ResponseFinal => "response-final",
83            Self::Interest => "interest",
84            Self::Declare => "declare",
85            Self::Oam => "oam",
86        })
87    }
88}
89
90impl From<NetworkBodyRef<'_>> for MessageLabel {
91    fn from(value: NetworkBodyRef<'_>) -> Self {
92        match value {
93            NetworkBodyRef::Push(push) => match push.payload {
94                PushBody::Put(_) => MessageLabel::Put,
95                PushBody::Del(_) => MessageLabel::Del,
96            },
97            NetworkBodyRef::Request(_) => MessageLabel::Query,
98            NetworkBodyRef::Response(res) => match res.payload {
99                ResponseBody::Reply(_) => MessageLabel::Reply,
100                ResponseBody::Err(_) => MessageLabel::ReplyErr,
101            },
102            NetworkBodyRef::ResponseFinal(_) => MessageLabel::ResponseFinal,
103            NetworkBodyRef::Interest(_) => MessageLabel::Interest,
104            NetworkBodyRef::Declare(_) => MessageLabel::Declare,
105            NetworkBodyRef::OAM(_) => MessageLabel::Oam,
106        }
107    }
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub enum SpaceLabel {
112    User,
113    Admin,
114}
115
116impl SpaceLabel {
117    pub(crate) const NUM: usize = 2;
118}
119
120impl EncodeLabelValue for SpaceLabel {
121    fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
122        encoder.write_str(match self {
123            Self::User => "user",
124            Self::Admin => "admin",
125        })
126    }
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
130pub enum ReasonLabel {
131    AccessControl,
132    Congestion,
133    Downsampling,
134    LowPass,
135    NoLink,
136}
137
138impl EncodeLabelValue for ReasonLabel {
139    fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
140        encoder.write_str(match self {
141            Self::AccessControl => "access-control",
142            Self::Congestion => "congestion",
143            Self::Downsampling => "downsampling",
144            Self::LowPass => "low-pass",
145            Self::NoLink => "no-link",
146        })
147    }
148}
149
150pub(crate) const SHM_NUM: usize = 2;
151
152macro_rules! wrap_label {
153    ($ty:ty, $label:ident $(, $derive:ty)*) => {
154        #[derive(Debug, Clone, PartialEq, Eq, Hash, $($derive),*)]
155        pub(crate) struct $label(pub(crate) $ty);
156
157        impl EncodeLabelValue for $label {
158            fn encode(&self, encoder: &mut LabelValueEncoder) -> fmt::Result {
159                write!(encoder, "{}", self.0)
160            }
161        }
162
163        impl<T: Into<$ty>> From<T> for $label {
164            fn from(value: T) -> Self {
165                Self(value.into())
166            }
167        }
168
169        impl Deref for $label {
170            type Target = $ty;
171
172            fn deref(&self) -> &Self::Target {
173                &self.0
174            }
175        }
176    };
177}
178
179wrap_label!(ZenohIdProto, ZidLabel, Copy);
180wrap_label!(WhatAmI, WhatAmILabel, Copy);
181wrap_label!(Priority, PriorityLabel, Copy);
182wrap_label!(Locator, LocatorLabel);
183
184pub(crate) type ProtocolLabel = Cow<'static, str>;
185
186#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
187pub(crate) struct TransportLabels {
188    pub(crate) remote_zid: Option<ZidLabel>,
189    pub(crate) remote_whatami: Option<WhatAmILabel>,
190    pub(crate) remote_group: Option<String>,
191    pub(crate) remote_cn: Option<String>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
195pub(crate) struct ProtocolLabels {
196    pub(crate) protocol: ProtocolLabel,
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EncodeLabelSet)]
200pub(crate) struct DisconnectedLabels {
201    pub(crate) disconnected: bool,
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
205pub(crate) struct LinkLabels {
206    pub(crate) src_locator: LocatorLabel,
207    pub(crate) dst_locator: LocatorLabel,
208}
209
210impl LinkLabels {
211    pub(crate) fn protocol(&self) -> ProtocolLabel {
212        static KNOWN_PROTOCOLS: &[&str] = &[
213            "tcp",
214            "udp",
215            "tls",
216            "quic",
217            "unixsock-stream",
218            "ws",
219            "serial",
220            "unixpipe",
221            "vsock",
222        ];
223        let protocol = self.dst_locator.protocol().as_str();
224        match KNOWN_PROTOCOLS.iter().find(|p| **p == protocol) {
225            Some(p) => Cow::Borrowed(*p),
226            None => Cow::Owned(self.dst_locator.to_string()),
227        }
228    }
229}
230
231impl From<(&Locator, &Locator)> for LinkLabels {
232    fn from(value: (&Locator, &Locator)) -> Self {
233        Self {
234            src_locator: value.0.clone().into(),
235            dst_locator: value.1.clone().into(),
236        }
237    }
238}
239
240#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
241pub(crate) struct ResourceDeclaredLabels {
242    pub(crate) resource: ResourceLabel,
243    pub(crate) locality: LocalityLabel,
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
247pub(crate) struct BytesLabels {
248    pub(crate) protocol: ProtocolLabel,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
252pub(crate) struct TransportMessageLabels {
253    pub(crate) protocol: ProtocolLabel,
254}
255
256#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
257pub(crate) struct NetworkMessageLabels {
258    pub(crate) priority: PriorityLabel,
259    pub(crate) message: MessageLabel,
260    pub(crate) shm: bool,
261    pub(crate) protocol: ProtocolLabel,
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
265pub(crate) struct NetworkMessagePayloadLabels {
266    pub(crate) space: SpaceLabel,
267    pub(crate) priority: PriorityLabel,
268    pub(crate) message: MessageLabel,
269    pub(crate) shm: bool,
270}
271
272#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
273pub(crate) struct NetworkMessageDroppedPayloadLabels {
274    pub(crate) priority: PriorityLabel,
275    pub(crate) message: MessageLabel,
276    pub(crate) protocol: Option<ProtocolLabel>,
277    pub(crate) reason: ReasonLabel,
278}