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 ListJobs,
151 CreateJobPlan,
153 RetrieveMostRecentJobDeployment,
155 CreateOrUpdateJob,
157 ReadJob,
159 StopJob,
161}
162
163impl Function {
164 #[cfg(feature = "metrics")]
166 pub fn as_str(&self) -> &'static str {
167 match self {
168 Function::ListJobs => "list_jobs",
169 Function::CreateJobPlan => "create_job_plan",
170 Function::RetrieveMostRecentJobDeployment => "retrieve_most_recent_job_deployment",
171 Function::CreateOrUpdateJob => "create_or_update_job",
172 Function::ReadJob => "read_job",
173 Function::StopJob => "stop_job",
174 }
175 }
176}