ferron_common/
observability.rs1use std::collections::HashSet;
2use std::error::Error;
3use std::sync::Arc;
4
5use async_channel::{Receiver, Sender};
6
7use crate::config::ServerConfiguration;
8use crate::logging::LogMessage;
9
10pub trait ObservabilityBackendLoader {
12 fn load_observability_backend(
14 &mut self,
15 config: &ServerConfiguration,
16 global_config: Option<&ServerConfiguration>,
17 secondary_runtime: &tokio::runtime::Runtime,
18 ) -> Result<Arc<dyn ObservabilityBackend + Send + Sync>, Box<dyn Error + Send + Sync>>;
19
20 fn get_requirements(&self) -> Vec<&'static str> {
22 vec![]
23 }
24
25 #[allow(unused_variables)]
27 fn validate_configuration(
28 &self,
29 config: &ServerConfiguration,
30 used_properties: &mut HashSet<String>,
31 ) -> Result<(), Box<dyn Error + Send + Sync>> {
32 Ok(())
33 }
34}
35
36pub trait ObservabilityBackend {
38 fn get_log_channel(&self) -> Option<Sender<LogMessage>> {
40 None
41 }
42
43 fn get_metric_channel(&self) -> Option<Sender<Metric>> {
45 None
46 }
47
48 fn get_trace_channel(&self) -> Option<(Sender<()>, Receiver<Sender<TraceSignal>>)> {
50 None
51 }
52}
53
54#[derive(Clone)]
56pub struct ObservabilityBackendChannels {
57 pub log_channels: Vec<Sender<LogMessage>>,
59 pub metric_channels: Vec<Sender<Metric>>,
61 pub trace_channels: Vec<(Sender<()>, Receiver<Sender<TraceSignal>>)>,
63}
64
65impl Default for ObservabilityBackendChannels {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl ObservabilityBackendChannels {
72 pub fn new() -> Self {
74 Self {
75 log_channels: Vec::new(),
76 metric_channels: Vec::new(),
77 trace_channels: Vec::new(),
78 }
79 }
80
81 pub fn add_log_channel(&mut self, channel: Sender<LogMessage>) {
83 self.log_channels.push(channel);
84 }
85
86 pub fn add_metric_channel(&mut self, channel: Sender<Metric>) {
88 self.metric_channels.push(channel);
89 }
90
91 pub fn add_trace_channel(&mut self, channel: (Sender<()>, Receiver<Sender<TraceSignal>>)) {
93 self.trace_channels.push(channel);
94 }
95}
96
97#[derive(Clone)]
99pub struct Metric {
100 pub name: &'static str,
102 pub attributes: Vec<(&'static str, MetricAttributeValue)>,
104 pub ty: MetricType,
106 pub value: MetricValue,
108 pub unit: Option<&'static str>,
110 pub description: Option<&'static str>,
112}
113
114impl Metric {
115 pub fn new(
117 name: &'static str,
118 attributes: Vec<(&'static str, MetricAttributeValue)>,
119 ty: MetricType,
120 value: MetricValue,
121 unit: Option<&'static str>,
122 description: Option<&'static str>,
123 ) -> Self {
124 Self {
125 name,
126 attributes,
127 ty,
128 value,
129 unit,
130 description,
131 }
132 }
133}
134
135#[derive(Clone, Debug, PartialEq)]
137pub enum MetricType {
138 Counter,
140
141 Gauge,
143
144 UpDownCounter,
146
147 Histogram(Option<Vec<f64>>),
149}
150
151#[derive(Clone, Copy, Debug, PartialEq)]
153#[non_exhaustive]
154pub enum MetricValue {
155 F64(f64),
156 U64(u64),
157 I64(i64),
158}
159
160#[derive(Clone, Debug, PartialEq)]
162pub enum MetricAttributeValue {
163 String(String),
165
166 Bool(bool),
168
169 I64(i64),
171
172 F64(f64),
174}
175
176pub struct MetricsMultiSender {
178 senders: Vec<Sender<Metric>>,
179}
180
181impl MetricsMultiSender {
182 pub fn new(sender: Sender<Metric>) -> Self {
192 Self { senders: vec![sender] }
193 }
194
195 pub fn new_multiple(senders: Vec<Sender<Metric>>) -> Self {
205 Self { senders }
206 }
207
208 pub fn without_sender() -> Self {
214 Self { senders: vec![] }
215 }
216
217 pub async fn send(&self, metric_data: Metric) {
224 for sender in &self.senders {
225 sender.send(metric_data.clone()).await.unwrap_or_default();
226 }
227 }
228}
229
230impl Clone for MetricsMultiSender {
231 fn clone(&self) -> Self {
237 Self {
238 senders: self.senders.clone(),
239 }
240 }
241}
242
243#[derive(Clone)]
245#[non_exhaustive]
246pub enum TraceSignal {
247 StartSpan(String),
249 EndSpan(String, Option<String>),
251}