1use std::fmt;
19use std::time::Duration;
20
21use fastmetrics::encoder::EncodeLabelSet;
22use fastmetrics::encoder::LabelSetEncoder;
23use fastmetrics::metrics::counter::Counter;
24use fastmetrics::metrics::family::Family;
25use fastmetrics::metrics::family::MetricFactory;
26use fastmetrics::metrics::gauge::Gauge;
27use fastmetrics::metrics::histogram::Histogram;
28use fastmetrics::registry::with_global_registry_mut;
29use fastmetrics::registry::Register;
30use fastmetrics::registry::Registry;
31use fastmetrics::registry::RegistryError;
32
33use crate::layers::observe;
34use crate::raw::*;
35use crate::*;
36
37#[derive(Clone, Debug)]
129pub struct FastmetricsLayer {
130 interceptor: FastmetricsInterceptor,
131}
132
133impl FastmetricsLayer {
134 pub fn builder() -> FastmetricsLayerBuilder {
136 FastmetricsLayerBuilder::default()
137 }
138}
139
140impl<A: Access> Layer<A> for FastmetricsLayer {
141 type LayeredAccess = observe::MetricsAccessor<A, FastmetricsInterceptor>;
142
143 fn layer(&self, inner: A) -> Self::LayeredAccess {
144 observe::MetricsLayer::new(self.interceptor.clone()).layer(inner)
145 }
146}
147
148pub struct FastmetricsLayerBuilder {
150 bytes_buckets: Vec<f64>,
151 bytes_rate_buckets: Vec<f64>,
152 entries_buckets: Vec<f64>,
153 entries_rate_buckets: Vec<f64>,
154 duration_seconds_buckets: Vec<f64>,
155 ttfb_buckets: Vec<f64>,
156 disable_label_root: bool,
157}
158
159impl Default for FastmetricsLayerBuilder {
160 fn default() -> Self {
161 Self {
162 bytes_buckets: observe::DEFAULT_BYTES_BUCKETS.to_vec(),
163 bytes_rate_buckets: observe::DEFAULT_BYTES_RATE_BUCKETS.to_vec(),
164 entries_buckets: observe::DEFAULT_ENTRIES_BUCKETS.to_vec(),
165 entries_rate_buckets: observe::DEFAULT_ENTRIES_RATE_BUCKETS.to_vec(),
166 duration_seconds_buckets: observe::DEFAULT_DURATION_SECONDS_BUCKETS.to_vec(),
167 ttfb_buckets: observe::DEFAULT_TTFB_BUCKETS.to_vec(),
168 disable_label_root: false,
169 }
170 }
171}
172
173impl FastmetricsLayerBuilder {
174 pub fn bytes_buckets(mut self, buckets: Vec<f64>) -> Self {
176 if !buckets.is_empty() {
177 self.bytes_buckets = buckets;
178 }
179 self
180 }
181
182 pub fn bytes_rate_buckets(mut self, buckets: Vec<f64>) -> Self {
184 if !buckets.is_empty() {
185 self.bytes_rate_buckets = buckets;
186 }
187 self
188 }
189
190 pub fn entries_buckets(mut self, buckets: Vec<f64>) -> Self {
192 if !buckets.is_empty() {
193 self.entries_buckets = buckets;
194 }
195 self
196 }
197
198 pub fn entries_rate_buckets(mut self, buckets: Vec<f64>) -> Self {
200 if !buckets.is_empty() {
201 self.entries_rate_buckets = buckets;
202 }
203 self
204 }
205
206 pub fn duration_seconds_buckets(mut self, buckets: Vec<f64>) -> Self {
208 if !buckets.is_empty() {
209 self.duration_seconds_buckets = buckets;
210 }
211 self
212 }
213
214 pub fn ttfb_buckets(mut self, buckets: Vec<f64>) -> Self {
216 if !buckets.is_empty() {
217 self.ttfb_buckets = buckets;
218 }
219 self
220 }
221
222 pub fn disable_label_root(mut self, disable: bool) -> Self {
225 self.disable_label_root = disable;
226 self
227 }
228
229 pub fn register(self, registry: &mut Registry) -> Result<FastmetricsLayer> {
252 let operation_bytes = Family::new(HistogramFactory {
253 buckets: self.bytes_buckets.clone(),
254 });
255 let operation_bytes_rate = Family::new(HistogramFactory {
256 buckets: self.bytes_rate_buckets.clone(),
257 });
258 let operation_entries = Family::new(HistogramFactory {
259 buckets: self.entries_buckets.clone(),
260 });
261 let operation_entries_rate = Family::new(HistogramFactory {
262 buckets: self.entries_rate_buckets.clone(),
263 });
264 let operation_duration_seconds = Family::new(HistogramFactory {
265 buckets: self.duration_seconds_buckets.clone(),
266 });
267 let operation_errors_total = Family::default();
268 let operation_executing = Family::default();
269 let operation_ttfb_seconds = Family::new(HistogramFactory {
270 buckets: self.ttfb_buckets.clone(),
271 });
272
273 let http_executing = Family::default();
274 let http_request_bytes = Family::new(HistogramFactory {
275 buckets: self.bytes_buckets.clone(),
276 });
277 let http_request_bytes_rate = Family::new(HistogramFactory {
278 buckets: self.bytes_rate_buckets.clone(),
279 });
280 let http_request_duration_seconds = Family::new(HistogramFactory {
281 buckets: self.duration_seconds_buckets.clone(),
282 });
283 let http_response_bytes = Family::new(HistogramFactory {
284 buckets: self.bytes_buckets.clone(),
285 });
286 let http_response_bytes_rate = Family::new(HistogramFactory {
287 buckets: self.bytes_rate_buckets.clone(),
288 });
289 let http_response_duration_seconds = Family::new(HistogramFactory {
290 buckets: self.duration_seconds_buckets.clone(),
291 });
292 let http_connection_errors_total = Family::default();
293 let http_status_errors_total = Family::default();
294
295 let interceptor = FastmetricsInterceptor {
296 operation_bytes,
297 operation_bytes_rate,
298 operation_entries,
299 operation_entries_rate,
300 operation_duration_seconds,
301 operation_errors_total,
302 operation_executing,
303 operation_ttfb_seconds,
304
305 http_executing,
306 http_request_bytes,
307 http_request_bytes_rate,
308 http_request_duration_seconds,
309 http_response_bytes,
310 http_response_bytes_rate,
311 http_response_duration_seconds,
312 http_connection_errors_total,
313 http_status_errors_total,
314
315 disable_label_root: self.disable_label_root,
316 };
317 interceptor
318 .register(registry)
319 .map_err(|err| Error::new(ErrorKind::Unexpected, err.to_string()).set_source(err))?;
320
321 Ok(FastmetricsLayer { interceptor })
322 }
323
324 pub fn register_global(self) -> Result<FastmetricsLayer> {
344 with_global_registry_mut(|registry| self.register(registry))
345 }
346}
347
348#[derive(Clone)]
349struct HistogramFactory {
350 buckets: Vec<f64>,
351}
352
353impl MetricFactory<Histogram> for HistogramFactory {
354 fn new_metric(&self) -> Histogram {
355 Histogram::new(self.buckets.iter().cloned())
356 }
357}
358
359#[derive(Clone, Debug)]
360pub struct FastmetricsInterceptor {
361 operation_bytes: Family<OperationLabels, Histogram, HistogramFactory>,
362 operation_bytes_rate: Family<OperationLabels, Histogram, HistogramFactory>,
363 operation_entries: Family<OperationLabels, Histogram, HistogramFactory>,
364 operation_entries_rate: Family<OperationLabels, Histogram, HistogramFactory>,
365 operation_duration_seconds: Family<OperationLabels, Histogram, HistogramFactory>,
366 operation_errors_total: Family<OperationLabels, Counter>,
367 operation_executing: Family<OperationLabels, Gauge>,
368 operation_ttfb_seconds: Family<OperationLabels, Histogram, HistogramFactory>,
369
370 http_executing: Family<OperationLabels, Gauge>,
371 http_request_bytes: Family<OperationLabels, Histogram, HistogramFactory>,
372 http_request_bytes_rate: Family<OperationLabels, Histogram, HistogramFactory>,
373 http_request_duration_seconds: Family<OperationLabels, Histogram, HistogramFactory>,
374 http_response_bytes: Family<OperationLabels, Histogram, HistogramFactory>,
375 http_response_bytes_rate: Family<OperationLabels, Histogram, HistogramFactory>,
376 http_response_duration_seconds: Family<OperationLabels, Histogram, HistogramFactory>,
377 http_connection_errors_total: Family<OperationLabels, Counter>,
378 http_status_errors_total: Family<OperationLabels, Counter>,
379
380 disable_label_root: bool,
381}
382
383impl Register for FastmetricsInterceptor {
384 fn register(&self, registry: &mut Registry) -> Result<(), RegistryError> {
385 macro_rules! register_metrics {
386 ($($field:ident => $value:expr),* $(,)?) => {
387 $(
388 {
389 let ((name, unit), help) = ($value.name_with_unit(), $value.help());
390 registry.register_metric(name, help, unit, self.$field.clone())?;
391 }
392 )*
393 };
394 }
395
396 register_metrics! {
397 operation_bytes => observe::MetricValue::OperationBytes(0),
399 operation_bytes_rate => observe::MetricValue::OperationBytesRate(0.0),
400 operation_entries => observe::MetricValue::OperationEntries(0),
401 operation_entries_rate => observe::MetricValue::OperationEntriesRate(0.0),
402 operation_duration_seconds => observe::MetricValue::OperationDurationSeconds(Duration::default()),
403 operation_errors_total => observe::MetricValue::OperationErrorsTotal,
404 operation_executing => observe::MetricValue::OperationExecuting(0),
405 operation_ttfb_seconds => observe::MetricValue::OperationTtfbSeconds(Duration::default()),
406
407 http_executing => observe::MetricValue::HttpExecuting(0),
409 http_request_bytes => observe::MetricValue::HttpRequestBytes(0),
410 http_request_bytes_rate => observe::MetricValue::HttpRequestBytesRate(0.0),
411 http_request_duration_seconds => observe::MetricValue::HttpRequestDurationSeconds(Duration::default()),
412 http_response_bytes => observe::MetricValue::HttpResponseBytes(0),
413 http_response_bytes_rate => observe::MetricValue::HttpResponseBytesRate(0.0),
414 http_response_duration_seconds => observe::MetricValue::HttpResponseDurationSeconds(Duration::default()),
415 http_connection_errors_total => observe::MetricValue::HttpConnectionErrorsTotal,
416 http_status_errors_total => observe::MetricValue::HttpStatusErrorsTotal,
417 }
418
419 Ok(())
420 }
421}
422
423impl observe::MetricsIntercept for FastmetricsInterceptor {
424 fn observe(&self, labels: observe::MetricLabels, value: observe::MetricValue) {
425 let labels = OperationLabels {
426 labels,
427 disable_label_root: self.disable_label_root,
428 };
429 match value {
430 observe::MetricValue::OperationBytes(v) => {
431 self.operation_bytes
432 .with_or_new(&labels, |hist| hist.observe(v as f64));
433 }
434 observe::MetricValue::OperationBytesRate(v) => {
435 self.operation_bytes_rate
436 .with_or_new(&labels, |hist| hist.observe(v));
437 }
438 observe::MetricValue::OperationEntries(v) => {
439 self.operation_entries
440 .with_or_new(&labels, |hist| hist.observe(v as f64));
441 }
442 observe::MetricValue::OperationEntriesRate(v) => {
443 self.operation_entries_rate
444 .with_or_new(&labels, |hist| hist.observe(v));
445 }
446 observe::MetricValue::OperationDurationSeconds(v) => {
447 self.operation_duration_seconds
448 .with_or_new(&labels, |hist| hist.observe(v.as_secs_f64()));
449 }
450 observe::MetricValue::OperationErrorsTotal => {
451 self.operation_errors_total
452 .with_or_new(&labels, |counter| counter.inc());
453 }
454 observe::MetricValue::OperationExecuting(v) => {
455 self.operation_executing
456 .with_or_new(&labels, |gauge| gauge.inc_by(v as i64));
457 }
458 observe::MetricValue::OperationTtfbSeconds(v) => {
459 self.operation_ttfb_seconds
460 .with_or_new(&labels, |hist| hist.observe(v.as_secs_f64()));
461 }
462
463 observe::MetricValue::HttpExecuting(v) => {
464 self.http_executing
465 .with_or_new(&labels, |gauge| gauge.inc_by(v as i64));
466 }
467 observe::MetricValue::HttpRequestBytes(v) => {
468 self.http_request_bytes
469 .with_or_new(&labels, |hist| hist.observe(v as f64));
470 }
471 observe::MetricValue::HttpRequestBytesRate(v) => {
472 self.http_request_bytes_rate
473 .with_or_new(&labels, |hist| hist.observe(v));
474 }
475 observe::MetricValue::HttpRequestDurationSeconds(v) => {
476 self.http_request_duration_seconds
477 .with_or_new(&labels, |hist| hist.observe(v.as_secs_f64()));
478 }
479 observe::MetricValue::HttpResponseBytes(v) => {
480 self.http_response_bytes
481 .with_or_new(&labels, |hist| hist.observe(v as f64));
482 }
483 observe::MetricValue::HttpResponseBytesRate(v) => {
484 self.http_response_bytes_rate
485 .with_or_new(&labels, |hist| hist.observe(v));
486 }
487 observe::MetricValue::HttpResponseDurationSeconds(v) => {
488 self.http_response_duration_seconds
489 .with_or_new(&labels, |hist| hist.observe(v.as_secs_f64()));
490 }
491 observe::MetricValue::HttpConnectionErrorsTotal => {
492 self.http_connection_errors_total
493 .with_or_new(&labels, |counter| counter.inc());
494 }
495 observe::MetricValue::HttpStatusErrorsTotal => {
496 self.http_status_errors_total
497 .with_or_new(&labels, |counter| counter.inc());
498 }
499 };
500 }
501}
502
503#[derive(Clone, Debug, PartialEq, Eq, Hash)]
504struct OperationLabels {
505 labels: observe::MetricLabels,
506 disable_label_root: bool,
507}
508
509impl EncodeLabelSet for OperationLabels {
510 fn encode(&self, encoder: &mut dyn LabelSetEncoder) -> fmt::Result {
511 encoder.encode(&(observe::LABEL_SCHEME, self.labels.scheme.into_static()))?;
512 encoder.encode(&(observe::LABEL_NAMESPACE, self.labels.namespace.as_ref()))?;
513 if !self.disable_label_root {
514 encoder.encode(&(observe::LABEL_ROOT, self.labels.root.as_ref()))?;
515 }
516 encoder.encode(&(observe::LABEL_OPERATION, self.labels.operation))?;
517 if let Some(error) = &self.labels.error {
518 encoder.encode(&(observe::LABEL_ERROR, error.into_static()))?;
519 }
520 if let Some(code) = &self.labels.status_code {
521 encoder.encode(&(observe::LABEL_STATUS_CODE, code.as_str()))?;
522 }
523 Ok(())
524 }
525}