sc_observability_types/
projection.rs1use std::sync::Arc;
2
3use crate::{
4 LogEvent, MetricRecord, Observable, Observation, ProjectionError, SpanSignal, SubscriberError,
5};
6
7type SubscriberRegistrationParts<T> = (
8 Arc<dyn ObservationSubscriber<T>>,
9 Option<Arc<dyn ObservationFilter<T>>>,
10);
11
12type ProjectionRegistrationParts<T> = (
13 Option<Arc<dyn LogProjector<T>>>,
14 Option<Arc<dyn SpanProjector<T>>>,
15 Option<Arc<dyn MetricProjector<T>>>,
16 Option<Arc<dyn ObservationFilter<T>>>,
17);
18
19pub trait ObservationSubscriber<T>: Send + Sync
21where
22 T: Observable,
23{
24 fn observe(&self, observation: &Observation<T>) -> Result<(), SubscriberError>;
31}
32
33pub trait ObservationFilter<T>: Send + Sync
35where
36 T: Observable,
37{
38 fn accepts(&self, observation: &Observation<T>) -> bool;
40}
41
42pub trait LogProjector<T>: Send + Sync
44where
45 T: Observable,
46{
47 fn project_logs(&self, observation: &Observation<T>) -> Result<Vec<LogEvent>, ProjectionError>;
54}
55
56pub trait SpanProjector<T>: Send + Sync
58where
59 T: Observable,
60{
61 fn project_spans(
68 &self,
69 observation: &Observation<T>,
70 ) -> Result<Vec<SpanSignal>, ProjectionError>;
71}
72
73pub trait MetricProjector<T>: Send + Sync
75where
76 T: Observable,
77{
78 fn project_metrics(
85 &self,
86 observation: &Observation<T>,
87 ) -> Result<Vec<MetricRecord>, ProjectionError>;
88}
89
90#[derive(Clone)]
92#[expect(
93 missing_debug_implementations,
94 reason = "public registration wrappers intentionally store trait objects that do not have a stable or useful Debug surface"
95)]
96pub struct SubscriberRegistration<T>
97where
98 T: Observable,
99{
100 subscriber: Arc<dyn ObservationSubscriber<T>>,
102 filter: Option<Arc<dyn ObservationFilter<T>>>,
104}
105
106impl<T> SubscriberRegistration<T>
107where
108 T: Observable,
109{
110 #[must_use]
112 pub fn new(subscriber: Arc<dyn ObservationSubscriber<T>>) -> Self {
113 Self {
114 subscriber,
115 filter: None,
116 }
117 }
118
119 #[must_use]
121 pub fn with_filter(mut self, filter: Arc<dyn ObservationFilter<T>>) -> Self {
122 self.filter = Some(filter);
123 self
124 }
125
126 #[must_use]
128 pub fn into_parts(self) -> SubscriberRegistrationParts<T> {
129 (self.subscriber, self.filter)
130 }
131}
132
133#[derive(Clone)]
135#[expect(
136 missing_debug_implementations,
137 reason = "public registration wrappers intentionally store trait objects that do not have a stable or useful Debug surface"
138)]
139pub struct ProjectionRegistration<T>
140where
141 T: Observable,
142{
143 log_projector: Option<Arc<dyn LogProjector<T>>>,
145 span_projector: Option<Arc<dyn SpanProjector<T>>>,
147 metric_projector: Option<Arc<dyn MetricProjector<T>>>,
149 filter: Option<Arc<dyn ObservationFilter<T>>>,
151}
152
153impl<T> ProjectionRegistration<T>
154where
155 T: Observable,
156{
157 #[must_use]
159 pub fn new() -> Self {
160 Self {
161 log_projector: None,
162 span_projector: None,
163 metric_projector: None,
164 filter: None,
165 }
166 }
167
168 #[must_use]
170 pub fn with_log_projector(mut self, projector: Arc<dyn LogProjector<T>>) -> Self {
171 self.log_projector = Some(projector);
172 self
173 }
174
175 #[must_use]
177 pub fn with_span_projector(mut self, projector: Arc<dyn SpanProjector<T>>) -> Self {
178 self.span_projector = Some(projector);
179 self
180 }
181
182 #[must_use]
184 pub fn with_metric_projector(mut self, projector: Arc<dyn MetricProjector<T>>) -> Self {
185 self.metric_projector = Some(projector);
186 self
187 }
188
189 #[must_use]
191 pub fn with_filter(mut self, filter: Arc<dyn ObservationFilter<T>>) -> Self {
192 self.filter = Some(filter);
193 self
194 }
195
196 #[must_use]
198 pub fn into_parts(self) -> ProjectionRegistrationParts<T> {
199 (
200 self.log_projector,
201 self.span_projector,
202 self.metric_projector,
203 self.filter,
204 )
205 }
206}
207
208impl<T> Default for ProjectionRegistration<T>
209where
210 T: Observable,
211{
212 fn default() -> Self {
213 Self::new()
214 }
215}