relay_filter/
interface.rs

1//! This module contains the trait for items that can be filtered by Inbound Filters, plus
2//! the implementation for [`Event`].
3use url::Url;
4
5use relay_event_schema::protocol::{
6    Csp, Event, EventType, Exception, LogEntry, Replay, SessionAggregates, SessionUpdate, Span,
7    Values,
8};
9
10/// A data item to which filters can be applied.
11pub trait Filterable {
12    /// The CSP report contained in the item. Only for CSP reports.
13    fn csp(&self) -> Option<&Csp>;
14
15    /// The exception values of the item. Only for error events.
16    fn exceptions(&self) -> Option<&Values<Exception>>;
17
18    /// The IP address of the client that sent the data.
19    fn ip_addr(&self) -> Option<&str>;
20
21    /// The logentry message. Only for error events.
22    fn logentry(&self) -> Option<&LogEntry>;
23
24    /// The release string of the data item.
25    fn release(&self) -> Option<&str>;
26
27    /// The transaction name. Only for transaction events.
28    fn transaction(&self) -> Option<&str>;
29
30    /// The URL from which the request originates. Used for localhost filtering.
31    fn url(&self) -> Option<Url>;
32
33    /// The user agent of the client that sent the data.
34    fn user_agent(&self) -> Option<&str>;
35
36    /// Retrieves a request headers from the item.
37    ///
38    /// For example this is used for localhost filtering by inspecting relevant headers that may
39    /// be included in the `request.headers` of an error.
40    ///
41    /// This **does not** return header information from the request that reached relay.
42    fn header(&self, header_name: &str) -> Option<&str>;
43}
44
45impl Filterable for Event {
46    fn csp(&self) -> Option<&Csp> {
47        if self.ty.value() != Some(&EventType::Csp) {
48            return None;
49        }
50        self.csp.value()
51    }
52
53    fn exceptions(&self) -> Option<&Values<Exception>> {
54        self.exceptions.value()
55    }
56
57    fn ip_addr(&self) -> Option<&str> {
58        let user = self.user.value()?;
59        Some(user.ip_address.value()?.as_ref())
60    }
61
62    fn logentry(&self) -> Option<&LogEntry> {
63        self.logentry.value()
64    }
65
66    fn release(&self) -> Option<&str> {
67        self.release.as_str()
68    }
69
70    fn transaction(&self) -> Option<&str> {
71        if self.ty.value() != Some(&EventType::Transaction) {
72            return None;
73        }
74        self.transaction.as_str()
75    }
76
77    fn url(&self) -> Option<Url> {
78        let url_str = self.request.value()?.url.value()?;
79        Url::parse(url_str).ok()
80    }
81
82    fn user_agent(&self) -> Option<&str> {
83        self.user_agent()
84    }
85
86    fn header(&self, header_name: &str) -> Option<&str> {
87        self.request
88            .value()?
89            .headers
90            .value()?
91            .get_header(header_name)
92    }
93}
94
95impl Filterable for Replay {
96    fn csp(&self) -> Option<&Csp> {
97        None
98    }
99
100    fn exceptions(&self) -> Option<&Values<Exception>> {
101        None
102    }
103
104    fn ip_addr(&self) -> Option<&str> {
105        let user = self.user.value()?;
106        Some(user.ip_address.value()?.as_ref())
107    }
108
109    fn logentry(&self) -> Option<&LogEntry> {
110        None
111    }
112
113    fn release(&self) -> Option<&str> {
114        self.release.as_str()
115    }
116
117    fn transaction(&self) -> Option<&str> {
118        None
119    }
120
121    fn url(&self) -> Option<Url> {
122        let url_str = self.request.value()?.url.value()?;
123        Url::parse(url_str).ok()
124    }
125
126    fn user_agent(&self) -> Option<&str> {
127        self.user_agent()
128    }
129
130    fn header(&self, header_name: &str) -> Option<&str> {
131        self.request
132            .value()?
133            .headers
134            .value()?
135            .get_header(header_name)
136    }
137}
138
139impl Filterable for Span {
140    fn csp(&self) -> Option<&Csp> {
141        // Only for events.
142        None
143    }
144
145    fn exceptions(&self) -> Option<&Values<Exception>> {
146        // Only for events.
147        None
148    }
149
150    fn ip_addr(&self) -> Option<&str> {
151        self.data.value()?.client_address.as_str()
152    }
153
154    fn logentry(&self) -> Option<&LogEntry> {
155        // Only for events.
156        None
157    }
158
159    fn release(&self) -> Option<&str> {
160        self.data.value()?.release.as_str()
161    }
162
163    fn transaction(&self) -> Option<&str> {
164        self.data.value()?.segment_name.as_str()
165    }
166
167    fn url(&self) -> Option<Url> {
168        let url_str = self.data.value()?.url_full.as_str()?;
169        Url::parse(url_str).ok()
170    }
171
172    fn user_agent(&self) -> Option<&str> {
173        self.data.value()?.user_agent_original.as_str()
174    }
175
176    fn header(&self, _: &str) -> Option<&str> {
177        None
178    }
179}
180
181impl Filterable for SessionUpdate {
182    fn csp(&self) -> Option<&Csp> {
183        None
184    }
185
186    fn exceptions(&self) -> Option<&Values<Exception>> {
187        None
188    }
189
190    fn ip_addr(&self) -> Option<&str> {
191        self.attributes
192            .ip_address
193            .as_ref()
194            .map(|addr| addr.as_str())
195    }
196
197    fn logentry(&self) -> Option<&LogEntry> {
198        None
199    }
200
201    fn release(&self) -> Option<&str> {
202        Some(&self.attributes.release)
203    }
204
205    fn transaction(&self) -> Option<&str> {
206        None
207    }
208
209    fn url(&self) -> Option<Url> {
210        None
211    }
212
213    fn user_agent(&self) -> Option<&str> {
214        self.attributes.user_agent.as_deref()
215    }
216
217    fn header(&self, _header_name: &str) -> Option<&str> {
218        None
219    }
220}
221
222impl Filterable for SessionAggregates {
223    fn csp(&self) -> Option<&Csp> {
224        None
225    }
226
227    fn exceptions(&self) -> Option<&Values<Exception>> {
228        None
229    }
230
231    fn ip_addr(&self) -> Option<&str> {
232        self.attributes
233            .ip_address
234            .as_ref()
235            .map(|addr| addr.as_str())
236    }
237
238    fn logentry(&self) -> Option<&LogEntry> {
239        None
240    }
241
242    fn release(&self) -> Option<&str> {
243        Some(&self.attributes.release)
244    }
245
246    fn transaction(&self) -> Option<&str> {
247        None
248    }
249
250    fn url(&self) -> Option<Url> {
251        None
252    }
253
254    fn user_agent(&self) -> Option<&str> {
255        self.attributes.user_agent.as_deref()
256    }
257
258    fn header(&self, _header_name: &str) -> Option<&str> {
259        None
260    }
261}