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, Span, Values,
7};
8
9/// A data item to which filters can be applied.
10pub trait Filterable {
11    /// The CSP report contained in the item. Only for CSP reports.
12    fn csp(&self) -> Option<&Csp>;
13
14    /// The exception values of the item. Only for error events.
15    fn exceptions(&self) -> Option<&Values<Exception>>;
16
17    /// The IP address of the client that sent the data.
18    fn ip_addr(&self) -> Option<&str>;
19
20    /// The logentry message. Only for error events.
21    fn logentry(&self) -> Option<&LogEntry>;
22
23    /// The release string of the data item.
24    fn release(&self) -> Option<&str>;
25
26    /// The transaction name. Only for transaction events.
27    fn transaction(&self) -> Option<&str>;
28
29    /// The URL from which the request originates. Used for localhost filtering.
30    fn url(&self) -> Option<Url>;
31
32    /// The user agent of the client that sent the data.
33    fn user_agent(&self) -> Option<&str>;
34
35    /// Retrieves a request headers from the item.
36    ///
37    /// For example this is used for localhost filtering by inspecting relevant headers that may
38    /// be included in the `request.headers` of an error.
39    ///
40    /// This **does not** return header information from the request that reached relay.
41    fn header(&self, header_name: &str) -> Option<&str>;
42}
43
44impl Filterable for Event {
45    fn csp(&self) -> Option<&Csp> {
46        if self.ty.value() != Some(&EventType::Csp) {
47            return None;
48        }
49        self.csp.value()
50    }
51
52    fn exceptions(&self) -> Option<&Values<Exception>> {
53        self.exceptions.value()
54    }
55
56    fn ip_addr(&self) -> Option<&str> {
57        let user = self.user.value()?;
58        Some(user.ip_address.value()?.as_ref())
59    }
60
61    fn logentry(&self) -> Option<&LogEntry> {
62        self.logentry.value()
63    }
64
65    fn release(&self) -> Option<&str> {
66        self.release.as_str()
67    }
68
69    fn transaction(&self) -> Option<&str> {
70        if self.ty.value() != Some(&EventType::Transaction) {
71            return None;
72        }
73        self.transaction.as_str()
74    }
75
76    fn url(&self) -> Option<Url> {
77        let url_str = self.request.value()?.url.value()?;
78        Url::parse(url_str).ok()
79    }
80
81    fn user_agent(&self) -> Option<&str> {
82        self.user_agent()
83    }
84
85    fn header(&self, header_name: &str) -> Option<&str> {
86        self.request
87            .value()?
88            .headers
89            .value()?
90            .get_header(header_name)
91    }
92}
93
94impl Filterable for Replay {
95    fn csp(&self) -> Option<&Csp> {
96        None
97    }
98
99    fn exceptions(&self) -> Option<&Values<Exception>> {
100        None
101    }
102
103    fn ip_addr(&self) -> Option<&str> {
104        let user = self.user.value()?;
105        Some(user.ip_address.value()?.as_ref())
106    }
107
108    fn logentry(&self) -> Option<&LogEntry> {
109        None
110    }
111
112    fn release(&self) -> Option<&str> {
113        self.release.as_str()
114    }
115
116    fn transaction(&self) -> Option<&str> {
117        None
118    }
119
120    fn url(&self) -> Option<Url> {
121        let url_str = self.request.value()?.url.value()?;
122        Url::parse(url_str).ok()
123    }
124
125    fn user_agent(&self) -> Option<&str> {
126        self.user_agent()
127    }
128
129    fn header(&self, header_name: &str) -> Option<&str> {
130        self.request
131            .value()?
132            .headers
133            .value()?
134            .get_header(header_name)
135    }
136}
137
138impl Filterable for Span {
139    fn csp(&self) -> Option<&Csp> {
140        // Only for events.
141        None
142    }
143
144    fn exceptions(&self) -> Option<&Values<Exception>> {
145        // Only for events.
146        None
147    }
148
149    fn ip_addr(&self) -> Option<&str> {
150        self.data.value()?.client_address.as_str()
151    }
152
153    fn logentry(&self) -> Option<&LogEntry> {
154        // Only for events.
155        None
156    }
157
158    fn release(&self) -> Option<&str> {
159        self.data.value()?.release.as_str()
160    }
161
162    fn transaction(&self) -> Option<&str> {
163        self.data.value()?.segment_name.as_str()
164    }
165
166    fn url(&self) -> Option<Url> {
167        let url_str = self.data.value()?.url_full.as_str()?;
168        Url::parse(url_str).ok()
169    }
170
171    fn user_agent(&self) -> Option<&str> {
172        self.data.value()?.user_agent_original.as_str()
173    }
174
175    fn header(&self, _: &str) -> Option<&str> {
176        None
177    }
178}