relay_server/utils/
sizes.rs1use relay_config::Config;
2
3use crate::envelope::{AttachmentType, Envelope, ItemType};
4use crate::managed::{ItemAction, ManagedEnvelope};
5use crate::services::outcome::{DiscardAttachmentType, DiscardItemType};
6
7pub 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 span_count = 0;
39 let mut log_count = 0;
40 let mut client_reports_size = 0;
41
42 for item in envelope.items() {
43 if item.is_container() && item.len() > config.max_container_size() {
44 return Err(item.ty().into());
45 }
46
47 let max_size = match item.ty() {
48 ItemType::Event
49 | ItemType::Transaction
50 | ItemType::Security
51 | ItemType::ReplayEvent
52 | ItemType::RawSecurity
53 | ItemType::Nel
54 | ItemType::UserReportV2
55 | ItemType::FormData => {
56 event_size += item.len();
57 NO_LIMIT
58 }
59 ItemType::Attachment | ItemType::UnrealReport | ItemType::UserReport => {
60 attachments_size += item.len();
61 config.max_attachment_size()
62 }
63 ItemType::ReplayRecording => config.max_replay_compressed_size(),
64 ItemType::ReplayVideo => config.max_replay_compressed_size(),
65 ItemType::Session | ItemType::Sessions => {
66 session_count += 1;
67 NO_LIMIT
68 }
69 ItemType::ClientReport => {
70 client_reports_size += item.len();
71 NO_LIMIT
72 }
73 ItemType::Profile => config.max_profile_size(),
74 ItemType::CheckIn => config.max_check_in_size(),
75 ItemType::Statsd => config.max_statsd_size(),
76 ItemType::MetricBuckets => config.max_metric_buckets_size(),
77 ItemType::Log => {
78 log_count += item.item_count().unwrap_or(1) as usize;
79 config.max_log_size()
80 }
81 ItemType::Span | ItemType::OtelSpan => {
82 span_count += item.item_count().unwrap_or(1) as usize;
83 config.max_span_size()
84 }
85 ItemType::OtelTracesData => config.max_event_size(), ItemType::OtelLogsData => config.max_event_size(), ItemType::ProfileChunk => config.max_profile_size(),
88 ItemType::Unknown(_) => NO_LIMIT,
89 };
90
91 let avg_item_size = item.len() / (item.item_count().unwrap_or(1).max(1) as usize);
95 if avg_item_size > max_size {
96 return Err(item
97 .attachment_type()
98 .map(|t| t.into())
99 .unwrap_or_else(|| item.ty().into()));
100 }
101 }
102
103 if event_size > config.max_event_size() {
104 return Err(DiscardItemType::Event);
105 }
106 if attachments_size > config.max_attachments_size() {
107 return Err(DiscardItemType::Attachment(
108 DiscardAttachmentType::Attachment,
109 ));
110 }
111 if session_count > config.max_session_count() {
112 return Err(DiscardItemType::Session);
113 }
114 if span_count > config.max_span_count() {
115 return Err(DiscardItemType::Span);
116 }
117 if log_count > config.max_log_count() {
118 return Err(DiscardItemType::Log);
119 }
120 if client_reports_size > config.max_client_reports_size() {
121 return Err(DiscardItemType::ClientReport);
122 }
123
124 Ok(())
125}
126
127pub fn remove_unknown_items(config: &Config, envelope: &mut ManagedEnvelope) {
132 if !config.accept_unknown_items() {
133 envelope.retain_items(|item| match item.ty() {
134 ItemType::Unknown(ty) => {
135 relay_log::debug!("dropping unknown item of type '{ty}'");
136 ItemAction::DropSilently
137 }
138 _ => match item.attachment_type() {
139 Some(AttachmentType::Unknown(ty)) => {
140 relay_log::debug!("dropping unknown attachment of type '{ty}'");
141 ItemAction::DropSilently
142 }
143 _ => ItemAction::Keep,
144 },
145 });
146 }
147}