1#[cfg(feature = "metrics")]
2use http::StatusCode;
3
4#[cfg(feature = "metrics")]
5use std::time::Duration;
6
7#[cfg(feature = "metrics")]
9#[derive(Debug, Clone, Copy)]
10pub struct MetricInfo {
11 pub method: HttpMethod,
13 pub function: Function,
15 pub status: Option<StatusCode>,
17 pub duration: Option<Duration>,
19}
20
21#[cfg(feature = "metrics")]
22impl MetricInfo {
23 fn new(method: HttpMethod, function: Function, status: Option<StatusCode>) -> Self {
24 Self {
25 method,
26 function,
27 status,
28 duration: None,
29 }
30 }
31
32 pub fn labels(&self) -> [&str; 3] {
34 if let Some(status) = self.status.and_then(|o| o.canonical_reason()) {
35 [self.method.as_str(), self.function.as_str(), status]
36 } else {
37 [self.method.as_str(), self.function.as_str(), "unknown"]
38 }
39 }
40}
41
42#[cfg(feature = "metrics")]
43#[derive(Debug, Clone)]
44pub(crate) struct MetricInfoWrapper {
45 metrics: MetricInfo,
46 sender: Option<tokio::sync::mpsc::UnboundedSender<MetricInfo>>,
47 start: std::time::Instant,
48}
49
50#[cfg(feature = "metrics")]
51impl MetricInfoWrapper {
52 pub fn new(
53 method: HttpMethod,
54 function: Function,
55 status: Option<StatusCode>,
56 sender: tokio::sync::mpsc::UnboundedSender<MetricInfo>,
57 ) -> Self {
58 Self {
59 metrics: MetricInfo::new(method, function, status),
60 sender: Some(sender),
61 start: std::time::Instant::now(),
62 }
63 }
64
65 pub fn set_status(&mut self, status: StatusCode) {
66 self.metrics.status = Some(status);
67 }
68
69 pub fn emit_metrics(&mut self) {
70 if let Some(sender) = self.sender.take() {
71 let mut metrics = self.metrics;
72 metrics.duration = Some(self.start.elapsed());
73 let _ = sender.send(metrics);
74 }
75 }
76}
77
78#[cfg(feature = "metrics")]
79impl Drop for MetricInfoWrapper {
80 fn drop(&mut self) {
81 self.emit_metrics();
82 }
83}
84
85#[derive(Debug, Clone, Copy)]
87pub enum HttpMethod {
88 Options,
90 Get,
92 Post,
94 Put,
96 Delete,
98 Head,
100 Trace,
102 Connect,
104 Patch,
106 Extensions,
108}
109
110impl HttpMethod {
111 #[cfg(feature = "metrics")]
112 fn as_str(&self) -> &'static str {
113 match self {
114 HttpMethod::Options => "options",
115 HttpMethod::Get => "get",
116 HttpMethod::Post => "post",
117 HttpMethod::Put => "put",
118 HttpMethod::Delete => "delete",
119 HttpMethod::Head => "head",
120 HttpMethod::Trace => "trace",
121 HttpMethod::Connect => "connect",
122 HttpMethod::Patch => "patch",
123 HttpMethod::Extensions => "extensions",
124 }
125 }
126}
127
128#[cfg(feature = "metrics")]
129impl From<http::Method> for HttpMethod {
130 fn from(method: http::Method) -> Self {
131 match method {
132 http::Method::OPTIONS => HttpMethod::Options,
133 http::Method::GET => HttpMethod::Get,
134 http::Method::POST => HttpMethod::Post,
135 http::Method::PUT => HttpMethod::Put,
136 http::Method::DELETE => HttpMethod::Delete,
137 http::Method::HEAD => HttpMethod::Head,
138 http::Method::TRACE => HttpMethod::Trace,
139 http::Method::CONNECT => HttpMethod::Connect,
140 http::Method::PATCH => HttpMethod::Patch,
141 _ => HttpMethod::Extensions,
142 }
143 }
144}
145
146#[derive(Debug, Clone, Copy)]
148pub enum Function {
149 ReadKey,
151 CreateOrUpdateKey,
153 DeleteKey,
155 RegisterEntity,
157 DeregisterEntity,
159 GetServiceNodes,
161 GetNodes,
163 GetAllRegisteredServices,
165 GetSession,
167 GetAclTokens,
169 CreateACLPolicy,
171 GetACLPolicies,
173 ReadACLPolicies,
175 DeleteACLToken,
177 ReadACLToken,
179 DeleteACLPolicy,
181}
182
183impl Function {
184 #[cfg(feature = "metrics")]
186 pub fn as_str(&self) -> &'static str {
187 match self {
188 Function::ReadKey => "read_key",
189 Function::CreateOrUpdateKey => "create_or_update_key",
190 Function::DeleteKey => "delete_key",
191 Function::RegisterEntity => "register_entity",
192 Function::DeregisterEntity => "deregister_entity",
193 Function::GetServiceNodes => "get_service_nodes",
194 Function::GetNodes => "get_nodes",
195 Function::GetAllRegisteredServices => "get_all_registered_services",
196 Function::GetSession => "get_session",
197 Function::GetAclTokens => "list_acl_tokens",
198 Function::CreateACLPolicy => "create_acl_policy",
199 Function::GetACLPolicies => "get_acl_policies",
200 Function::ReadACLPolicies => "read_acl_policies",
201 Function::DeleteACLToken => "delete_acl_token",
202 Function::ReadACLToken => "read_acl_token",
203 Function::DeleteACLPolicy => "delete_acl_policy",
204 }
205 }
206}