fast_telemetry/
runtime.rs1use crate::{CompletedSpan, ExportMetrics, MetricVisitor, Span, SpanCollector, SpanKind};
9use parking_lot::RwLock;
10use std::borrow::Cow;
11use std::ops::Deref;
12use std::sync::Arc;
13
14#[derive(Clone, Debug, Default)]
19#[non_exhaustive]
20pub struct RuntimeConfig {}
21
22#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
30pub struct MetricScope {
31 name: Arc<str>,
32}
33
34impl MetricScope {
35 pub fn new(name: impl Into<Arc<str>>) -> Self {
37 Self { name: name.into() }
38 }
39
40 pub fn name(&self) -> &str {
42 &self.name
43 }
44}
45
46impl From<&'static str> for MetricScope {
47 fn from(name: &'static str) -> Self {
48 Self::new(name)
49 }
50}
51
52impl From<String> for MetricScope {
53 fn from(name: String) -> Self {
54 Self::new(Arc::<str>::from(name))
55 }
56}
57
58pub struct Runtime {
65 config: RuntimeConfig,
66 registry: RwLock<Vec<RegisteredMetricGroup>>,
67 span_collector: Arc<SpanCollector>,
68}
69
70impl Runtime {
71 pub fn new(config: RuntimeConfig) -> Arc<Self> {
73 Arc::new(Self {
74 config,
75 registry: RwLock::new(Vec::new()),
76 span_collector: Arc::new(SpanCollector::new(8, 4096)),
77 })
78 }
79
80 pub fn config(&self) -> &RuntimeConfig {
82 &self.config
83 }
84
85 pub fn span_collector(&self) -> &Arc<SpanCollector> {
91 &self.span_collector
92 }
93
94 pub fn start_span(&self, name: impl Into<Cow<'static, str>>, kind: SpanKind) -> Span {
99 self.span_collector.start_span(name, kind)
100 }
101
102 pub fn start_span_from_traceparent(
106 &self,
107 traceparent: Option<&str>,
108 name: impl Into<Cow<'static, str>>,
109 kind: SpanKind,
110 ) -> Span {
111 self.span_collector
112 .start_span_from_traceparent(traceparent, name, kind)
113 }
114
115 pub fn flush_local_spans(&self) {
117 self.span_collector.flush_local();
118 }
119
120 pub fn drain_spans_into(&self, buf: &mut Vec<CompletedSpan>) {
122 self.span_collector.drain_into(buf);
123 }
124
125 pub fn register_metrics<M>(&self, scope: MetricScope, metrics: M) -> RegisteredMetrics<M>
130 where
131 M: ExportMetrics + Send + Sync + 'static,
132 {
133 let metrics = Arc::new(metrics);
134 let erased_metrics: Arc<dyn ErasedExportMetrics> = metrics.clone();
135 self.registry.write().push(RegisteredMetricGroup {
136 scope: scope.clone(),
137 metrics: erased_metrics,
138 });
139
140 RegisteredMetrics { scope, metrics }
141 }
142
143 pub fn visit_metrics<V>(&self, visitor: &mut V)
145 where
146 V: MetricVisitor,
147 {
148 for group in self.registry.read().iter() {
149 group.metrics.visit_metrics(visitor);
150 }
151 }
152
153 pub fn visit_metrics_for_scope<V>(&self, scope: &MetricScope, visitor: &mut V)
155 where
156 V: MetricVisitor,
157 {
158 for group in self.registry.read().iter() {
159 if &group.scope == scope {
160 group.metrics.visit_metrics(visitor);
161 }
162 }
163 }
164
165 pub fn registered_metrics_len(&self) -> usize {
167 self.registry.read().len()
168 }
169
170 pub fn scopes(&self) -> Vec<MetricScope> {
172 self.registry
173 .read()
174 .iter()
175 .map(|group| group.scope.clone())
176 .collect()
177 }
178}
179
180#[must_use = "keep RegisteredMetrics so hot paths can update direct metric handles"]
182pub struct RegisteredMetrics<M> {
183 scope: MetricScope,
184 metrics: Arc<M>,
185}
186
187impl<M> RegisteredMetrics<M> {
188 pub fn scope(&self) -> &MetricScope {
190 &self.scope
191 }
192
193 pub fn metrics(&self) -> &Arc<M> {
195 &self.metrics
196 }
197
198 pub fn into_metrics(self) -> Arc<M> {
200 self.metrics
201 }
202}
203
204impl<M> Clone for RegisteredMetrics<M> {
205 fn clone(&self) -> Self {
206 Self {
207 scope: self.scope.clone(),
208 metrics: Arc::clone(&self.metrics),
209 }
210 }
211}
212
213impl<M> Deref for RegisteredMetrics<M> {
214 type Target = M;
215
216 fn deref(&self) -> &Self::Target {
217 &self.metrics
218 }
219}
220
221struct RegisteredMetricGroup {
222 scope: MetricScope,
223 metrics: Arc<dyn ErasedExportMetrics>,
224}
225
226trait ErasedExportMetrics: Send + Sync {
227 fn visit_metrics(&self, visitor: &mut dyn MetricVisitor);
228}
229
230impl<M> ErasedExportMetrics for M
231where
232 M: ExportMetrics + Send + Sync + 'static,
233{
234 fn visit_metrics(&self, visitor: &mut dyn MetricVisitor) {
235 ExportMetrics::visit_metrics(self, visitor);
236 }
237}