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 | ItemType::OtelLog => {
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::ProfileChunk => config.max_profile_size(),
87 ItemType::Unknown(_) => NO_LIMIT,
88 };
89
90 let avg_item_size = item.len() / (item.item_count().unwrap_or(1).max(1) as usize);
94 if avg_item_size > max_size {
95 return Err(item
96 .attachment_type()
97 .map(|t| t.into())
98 .unwrap_or_else(|| item.ty().into()));
99 }
100 }
101
102 if event_size > config.max_event_size() {
103 return Err(DiscardItemType::Event);
104 }
105 if attachments_size > config.max_attachments_size() {
106 return Err(DiscardItemType::Attachment(
107 DiscardAttachmentType::Attachment,
108 ));
109 }
110 if session_count > config.max_session_count() {
111 return Err(DiscardItemType::Session);
112 }
113 if span_count > config.max_span_count() {
114 return Err(DiscardItemType::Span);
115 }
116 if log_count > config.max_log_count() {
117 return Err(DiscardItemType::Log);
118 }
119 if client_reports_size > config.max_client_reports_size() {
120 return Err(DiscardItemType::ClientReport);
121 }
122
123 Ok(())
124}
125
126pub fn remove_unknown_items(config: &Config, envelope: &mut ManagedEnvelope) {
131 if !config.accept_unknown_items() {
132 envelope.retain_items(|item| match item.ty() {
133 ItemType::Unknown(ty) => {
134 relay_log::debug!("dropping unknown item of type '{ty}'");
135 ItemAction::DropSilently
136 }
137 _ => match item.attachment_type() {
138 Some(AttachmentType::Unknown(ty)) => {
139 relay_log::debug!("dropping unknown attachment of type '{ty}'");
140 ItemAction::DropSilently
141 }
142 _ => ItemAction::Keep,
143 },
144 });
145 }
146}