opendal_layer_metrics/
lib.rs1#![doc = include_str!("../README.md")]
19#![cfg_attr(docsrs, feature(doc_cfg))]
20#![cfg_attr(docsrs, doc(auto_cfg))]
21#![deny(missing_docs)]
22use metrics::Label;
23use metrics::counter;
24use metrics::gauge;
25use metrics::histogram;
26use opendal_core::OperationContext;
27use opendal_core::raw::*;
28use opendal_layer_observe_metrics_common as observe;
29
30#[derive(Clone, Debug, Default)]
84#[non_exhaustive]
85pub struct MetricsLayer {}
86
87impl MetricsLayer {
88 pub fn new() -> Self {
90 Self::default()
91 }
92}
93
94impl Layer for MetricsLayer {
95 fn apply_service(&self, inner: Servicer) -> Servicer {
96 let interceptor = MetricsInterceptor {};
97 observe::MetricsLayer::new(interceptor).apply_service(inner)
98 }
99
100 fn apply_context(&self, srv: Servicer, inner: OperationContext) -> OperationContext {
101 let interceptor = MetricsInterceptor {};
102 observe::MetricsLayer::new(interceptor).apply_context(srv, inner)
103 }
104}
105
106#[doc(hidden)]
107#[derive(Clone, Debug)]
108pub struct MetricsInterceptor;
109
110impl observe::MetricsIntercept for MetricsInterceptor {
111 fn observe(&self, labels: observe::MetricLabels, value: observe::MetricValue) {
112 let labels = OperationLabels(labels).into_labels();
113
114 match value {
115 observe::MetricValue::OperationBytes(v) => {
116 histogram!(value.name(), labels).record(v as f64)
117 }
118 observe::MetricValue::OperationBytesRate(v) => {
119 histogram!(value.name(), labels).record(v)
120 }
121 observe::MetricValue::OperationEntries(v) => {
122 histogram!(value.name(), labels).record(v as f64)
123 }
124 observe::MetricValue::OperationEntriesRate(v) => {
125 histogram!(value.name(), labels).record(v)
126 }
127 observe::MetricValue::OperationDurationSeconds(v) => {
128 histogram!(value.name(), labels).record(v)
129 }
130 observe::MetricValue::OperationErrorsTotal => {
131 counter!(value.name(), labels).increment(1)
132 }
133 observe::MetricValue::OperationExecuting(v) => {
134 gauge!(value.name(), labels).increment(v as f64)
135 }
136 observe::MetricValue::OperationTtfbSeconds(v) => {
137 histogram!(value.name(), labels).record(v)
138 }
139
140 observe::MetricValue::HttpExecuting(v) => {
141 gauge!(value.name(), labels).increment(v as f64)
142 }
143 observe::MetricValue::HttpRequestBytes(v) => {
144 histogram!(value.name(), labels).record(v as f64)
145 }
146 observe::MetricValue::HttpRequestBytesRate(v) => {
147 histogram!(value.name(), labels).record(v)
148 }
149 observe::MetricValue::HttpRequestDurationSeconds(v) => {
150 histogram!(value.name(), labels).record(v)
151 }
152 observe::MetricValue::HttpResponseBytes(v) => {
153 histogram!(value.name(), labels).record(v as f64)
154 }
155 observe::MetricValue::HttpResponseBytesRate(v) => {
156 histogram!(value.name(), labels).record(v)
157 }
158 observe::MetricValue::HttpResponseDurationSeconds(v) => {
159 histogram!(value.name(), labels).record(v)
160 }
161 observe::MetricValue::HttpConnectionErrorsTotal => {
162 counter!(value.name(), labels).increment(1)
163 }
164 observe::MetricValue::HttpStatusErrorsTotal => {
165 counter!(value.name(), labels).increment(1)
166 }
167 _ => {}
168 }
169 }
170}
171
172#[derive(Clone, Debug, PartialEq, Eq, Hash)]
173struct OperationLabels(observe::MetricLabels);
174
175impl OperationLabels {
176 fn into_labels(self) -> Vec<Label> {
177 let mut labels = Vec::with_capacity(6);
178
179 labels.extend([
180 Label::new(observe::LABEL_SCHEME, self.0.scheme),
181 Label::new(observe::LABEL_NAMESPACE, self.0.namespace),
182 Label::new(observe::LABEL_ROOT, self.0.root),
183 Label::new(observe::LABEL_OPERATION, self.0.operation),
184 ]);
185
186 if let Some(error) = self.0.error {
187 labels.push(Label::new(observe::LABEL_ERROR, error.into_static()));
188 }
189
190 if let Some(status_code) = self.0.status_code {
191 labels.push(Label::new(
192 observe::LABEL_STATUS_CODE,
193 status_code.as_str().to_owned(),
194 ));
195 }
196
197 if let Some(service_operation) = self.0.service_operation {
198 labels.push(Label::new(
199 observe::LABEL_SERVICE_OPERATION,
200 service_operation,
201 ));
202 }
203
204 labels
205 }
206}