relay_server/utils/
sizes.rs1use relay_config::Config;
2
3use crate::envelope::{Envelope, ItemType};
4use crate::integrations::Integration;
5use crate::managed::Managed;
6use crate::services::outcome::{DiscardAttachmentType, DiscardItemType};
7
8pub fn check_envelope_size_limits(
30 config: &Config,
31 envelope: &Envelope,
32) -> Result<(), DiscardItemType> {
33 const NO_LIMIT: usize = usize::MAX;
34
35 let mut event_size = 0;
36 let mut attachments_size = 0;
37 let mut session_count = 0;
38 let mut client_reports_size = 0;
39
40 for item in envelope.items() {
41 if item.is_container() && item.len() > config.max_container_size() {
42 return Err(item.ty().into());
43 }
44
45 let max_size = match item.ty() {
46 ItemType::Event
47 | ItemType::Transaction
48 | ItemType::Security
49 | ItemType::ReplayEvent
50 | ItemType::RawSecurity
51 | ItemType::UserReportV2
52 | ItemType::FormData => {
53 event_size += item.len();
54 NO_LIMIT
55 }
56 ItemType::Attachment | ItemType::UnrealReport | ItemType::UserReport => {
57 attachments_size += item.len();
58 config.max_attachment_size()
59 }
60 ItemType::ReplayRecording => config.max_replay_compressed_size(),
61 ItemType::ReplayVideo => config.max_replay_compressed_size(),
62 ItemType::Session | ItemType::Sessions => {
63 session_count += 1;
64 NO_LIMIT
65 }
66 ItemType::ClientReport => {
67 client_reports_size += item.len();
68 NO_LIMIT
69 }
70 ItemType::Profile => config.max_profile_size(),
71 ItemType::CheckIn => config.max_check_in_size(),
72 ItemType::Statsd => config.max_statsd_size(),
73 ItemType::MetricBuckets => config.max_metric_buckets_size(),
74 ItemType::Log => config.max_log_size(),
75 ItemType::TraceMetric => config.max_trace_metric_size(),
76 ItemType::Span => config.max_span_size(),
77 ItemType::Integration => match item.integration() {
78 Some(Integration::Logs(_)) => config.max_logs_integration_size(),
79 Some(Integration::Spans(_)) => config.max_spans_integration_size(),
80 None => NO_LIMIT,
81 },
82 ItemType::ProfileChunk => config.max_profile_size(),
83 ItemType::Unknown(_) => NO_LIMIT,
84 };
85
86 let avg_item_size = item.len() / (item.item_count().unwrap_or(1).max(1) as usize);
90 if avg_item_size > max_size {
91 return Err(item
92 .attachment_type()
93 .map(|t| t.into())
94 .unwrap_or_else(|| item.ty().into()));
95 }
96 }
97
98 if event_size > config.max_event_size() {
99 return Err(DiscardItemType::Event);
100 }
101 if attachments_size > config.max_attachments_size() {
102 return Err(DiscardItemType::Attachment(
103 DiscardAttachmentType::Attachment,
104 ));
105 }
106 if session_count > config.max_session_count() {
107 return Err(DiscardItemType::Session);
108 }
109 if client_reports_size > config.max_client_reports_size() {
110 return Err(DiscardItemType::ClientReport);
111 }
112
113 Ok(())
114}
115
116pub fn remove_unknown_items(config: &Config, envelope: &mut Managed<Box<Envelope>>) {
121 if config.accept_unknown_items() {
122 return;
123 }
124
125 envelope.modify(|envelope, records| {
126 envelope.retain_items(|item| {
127 if item.is_unknown() {
128 relay_log::debug!("dropping unknown item");
129 records.reject_err(None, &*item);
131 false
132 } else {
133 true
134 }
135 });
136 });
137}