bothan_lib/metrics/server.rs
1//! Metrics collection for gRPC server operations.
2//!
3//! This module provides the [`Metrics`] struct and related types for tracking gRPC server statistics
4//! such as the number of requests and their processing durations. It leverages OpenTelemetry for metrics
5//! instrumentation, supporting monitoring and observability.
6
7use opentelemetry::metrics::{Counter, Histogram};
8use opentelemetry::{KeyValue, global};
9use strum_macros::Display;
10use tonic::Code;
11
12use crate::metrics::utils::code_to_str;
13
14/// Holds counters and histograms for gRPC server metrics.
15#[derive(Clone, Debug)]
16pub struct Metrics {
17 /// Counter tracking total server requests.
18 requests_total: Counter<u64>,
19
20 /// Histogram recording request durations in milliseconds.
21 request_duration: Histogram<f64>,
22}
23
24impl Default for Metrics {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl Metrics {
31 /// Creates a new [`Metrics`] instance configured for the gRPC server.
32 ///
33 /// # Examples
34 ///
35 /// ```rust
36 /// use bothan_lib::metrics::server::Metrics;
37 /// use bothan_lib::metrics::server::ServiceName;
38 /// use tonic::Code;
39 ///
40 /// let metrics = Metrics::new();
41 /// metrics.update_server_request(42.0, ServiceName::GetInfo, Code::Ok);
42 /// ```
43 pub fn new() -> Self {
44 let meter = global::meter("server");
45
46 let requests_total = meter
47 .u64_counter("server_requests")
48 .with_description("Total number of requests sent to the server")
49 .build();
50 let request_duration = meter
51 .f64_histogram("server_request_duration_milliseconds")
52 .with_description("Time taken to process each request sent to the server")
53 .with_unit("milliseconds")
54 .build();
55
56 Self {
57 requests_total,
58 request_duration,
59 }
60 }
61
62 /// Records a server request result and duration.
63 ///
64 /// # Arguments
65 ///
66 /// * `elapsed_time` - Duration of the request in milliseconds.
67 /// * `service_name` - The gRPC service being called.
68 /// * `grpc_code` - The gRPC status code returned.
69 pub fn update_server_request(
70 &self,
71 elapsed_time: f64,
72 service_name: ServiceName,
73 grpc_code: Code,
74 ) {
75 let labels = &[
76 KeyValue::new("service_name", service_name.to_string()),
77 KeyValue::new("status", code_to_str(grpc_code)),
78 ];
79 self.requests_total.add(1, labels);
80 self.request_duration.record(elapsed_time, labels);
81 }
82}
83
84/// Possible gRPC service endpoints for server requests.
85#[derive(Display)]
86#[strum(serialize_all = "snake_case")]
87pub enum ServiceName {
88 /// Get information from the server.
89 GetInfo,
90 /// Update the registry on the server.
91 UpdateRegistry,
92 /// Push monitoring records to the server.
93 PushMonitoringRecords,
94 /// Get price data from the server.
95 GetPrices,
96}