ash_rpc/observability/
macros.rs1#[macro_export]
35macro_rules! observable_setup {
36 (
38 service_name: $service_name:expr,
39 metrics_prefix: $metrics_prefix:expr,
40 otlp_endpoint: $otlp_endpoint:expr
41 $(, log_level: $log_level:expr)?
42 $(,)?
43 ) => {{
44 #[allow(unused_imports)]
45 use $crate::logger::{Logger, TracingLogger};
46
47 let logger: ::std::sync::Arc<dyn Logger> = ::std::sync::Arc::new(TracingLogger::new());
49 logger.info(
50 "Initializing observability stack",
51 &[
52 ("service", &$service_name),
53 ("metrics_prefix", &$metrics_prefix),
54 ],
55 );
56
57 #[cfg(feature = "opentelemetry")]
59 {
60 use ::opentelemetry::global;
61 use ::opentelemetry_otlp::{SpanExporter, WithExportConfig};
62 use ::opentelemetry_sdk::Resource;
63 use ::opentelemetry_sdk::trace::TracerProvider;
64
65 logger.info(
66 "Initializing OpenTelemetry tracer",
67 &[("endpoint", &$otlp_endpoint)],
68 );
69
70 let exporter = SpanExporter::builder()
71 .with_tonic()
72 .with_endpoint($otlp_endpoint)
73 .build()
74 .expect("Failed to create OTLP exporter");
75
76 let tracer_provider = TracerProvider::builder()
77 .with_batch_exporter(exporter, ::opentelemetry_sdk::runtime::Tokio)
78 .with_resource(Resource::new(vec![::opentelemetry::KeyValue::new(
79 "service.name",
80 $service_name,
81 )]))
82 .build();
83
84 global::set_tracer_provider(tracer_provider);
85 logger.info("OpenTelemetry tracer initialized", &[]);
86 }
87
88 #[cfg(feature = "prometheus")]
90 let metrics = {
91 let m = ::std::sync::Arc::new(
92 $crate::observability::prometheus::PrometheusMetrics::with_prefix($metrics_prefix)
93 .expect("Failed to create Prometheus metrics"),
94 );
95
96 #[cfg(all(target_os = "linux", feature = "prometheus"))]
98 {
99 let process_collector =
100 $crate::prometheus::process_collector::ProcessCollector::for_self();
101 m.registry()
102 .register(Box::new(process_collector))
103 .expect("Failed to register process collector");
104 logger.info("Prometheus metrics initialized with process collector", &[]);
105 }
106
107 #[cfg(not(target_os = "linux"))]
108 logger.info("Prometheus metrics initialized", &[]);
109
110 m
111 };
112
113 #[cfg(not(feature = "prometheus"))]
114 let metrics = ();
115
116 $crate::observability::macros::ObservabilityStack {
117 #[cfg(feature = "prometheus")]
118 metrics,
119 logger,
120 }
121 }};
122
123 (
125 metrics_prefix: $metrics_prefix:expr
126 $(,)?
127 ) => {{
128 #[allow(unused_imports)]
129 use $crate::logger::{Logger, TracingLogger};
130
131 let logger: ::std::sync::Arc<dyn Logger> = ::std::sync::Arc::new(TracingLogger::new());
132 logger.info(
133 "Initializing observability stack",
134 &[("metrics_prefix", &$metrics_prefix)],
135 );
136
137 #[cfg(feature = "prometheus")]
138 let metrics = {
139 let m = ::std::sync::Arc::new(
140 $crate::observability::prometheus::PrometheusMetrics::with_prefix($metrics_prefix)
141 .expect("Failed to create Prometheus metrics"),
142 );
143
144 #[cfg(all(target_os = "linux", feature = "prometheus"))]
145 {
146 let process_collector =
147 $crate::prometheus::process_collector::ProcessCollector::for_self();
148 m.registry()
149 .register(Box::new(process_collector))
150 .expect("Failed to register process collector");
151 logger.info("Prometheus metrics initialized with process collector", &[]);
152 }
153
154 #[cfg(not(target_os = "linux"))]
155 logger.info("Prometheus metrics initialized", &[]);
156
157 m
158 };
159
160 #[cfg(not(feature = "prometheus"))]
161 let metrics = ();
162
163 $crate::observability::macros::ObservabilityStack {
164 #[cfg(feature = "prometheus")]
165 metrics,
166 logger,
167 }
168 }};
169
170 (
172 service_name: $service_name:expr,
173 metrics_prefix: $metrics_prefix:expr
174 $(,)?
175 ) => {{
176 #[allow(unused_imports)]
177 use $crate::logger::{Logger, TracingLogger};
178
179 let logger: ::std::sync::Arc<dyn Logger> = ::std::sync::Arc::new(TracingLogger::new());
180 logger.info(
181 "Initializing observability stack",
182 &[
183 ("service", &$service_name),
184 ("metrics_prefix", &$metrics_prefix),
185 ],
186 );
187
188 #[cfg(feature = "prometheus")]
189 let metrics = {
190 let m = ::std::sync::Arc::new(
191 $crate::observability::prometheus::PrometheusMetrics::with_prefix($metrics_prefix)
192 .expect("Failed to create Prometheus metrics"),
193 );
194
195 #[cfg(all(target_os = "linux", feature = "prometheus"))]
196 {
197 let process_collector =
198 $crate::prometheus::process_collector::ProcessCollector::for_self();
199 m.registry()
200 .register(Box::new(process_collector))
201 .expect("Failed to register process collector");
202 logger.info("Prometheus metrics initialized with process collector", &[]);
203 }
204
205 #[cfg(not(target_os = "linux"))]
206 logger.info("Prometheus metrics initialized", &[]);
207
208 m
209 };
210
211 #[cfg(not(feature = "prometheus"))]
212 let metrics = ();
213
214 $crate::observability::macros::ObservabilityStack {
215 #[cfg(feature = "prometheus")]
216 metrics,
217 logger,
218 }
219 }};
220}
221
222pub struct ObservabilityStack {
224 #[cfg(feature = "prometheus")]
225 pub metrics: ::std::sync::Arc<super::prometheus::PrometheusMetrics>,
226 pub logger: ::std::sync::Arc<dyn crate::logger::Logger>,
227}
228
229impl ObservabilityStack {
230 #[cfg(feature = "prometheus")]
232 #[must_use]
233 pub fn metrics(&self) -> ::std::sync::Arc<super::prometheus::PrometheusMetrics> {
234 ::std::sync::Arc::clone(&self.metrics)
235 }
236
237 #[must_use]
239 pub fn logger(&self) -> ::std::sync::Arc<dyn crate::logger::Logger> {
240 ::std::sync::Arc::clone(&self.logger)
241 }
242}