relay_server/utils/
sizes.rs1use relay_config::Config;
2
3use crate::envelope::{AttachmentType, Envelope, ItemType};
4use crate::integrations::Integration;
5use crate::managed::{ItemAction, ManagedEnvelope};
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::Nel
52 | ItemType::UserReportV2
53 | ItemType::FormData => {
54 event_size += item.len();
55 NO_LIMIT
56 }
57 ItemType::Attachment | ItemType::UnrealReport | ItemType::UserReport => {
58 attachments_size += item.len();
59 config.max_attachment_size()
60 }
61 ItemType::ReplayRecording => config.max_replay_compressed_size(),
62 ItemType::ReplayVideo => config.max_replay_compressed_size(),
63 ItemType::Session | ItemType::Sessions => {
64 session_count += 1;
65 NO_LIMIT
66 }
67 ItemType::ClientReport => {
68 client_reports_size += item.len();
69 NO_LIMIT
70 }
71 ItemType::Profile => config.max_profile_size(),
72 ItemType::CheckIn => config.max_check_in_size(),
73 ItemType::Statsd => config.max_statsd_size(),
74 ItemType::MetricBuckets => config.max_metric_buckets_size(),
75 ItemType::Log => config.max_log_size(),
76 ItemType::TraceMetric => config.max_trace_metric_size(),
77 ItemType::Span => config.max_span_size(),
78 ItemType::Integration => match item.integration() {
79 Some(Integration::Logs(_)) => config.max_logs_integration_size(),
80 Some(Integration::Spans(_)) => config.max_spans_integration_size(),
81 None => NO_LIMIT,
82 },
83 ItemType::ProfileChunk => config.max_profile_size(),
84 ItemType::Unknown(_) => NO_LIMIT,
85 };
86
87 let avg_item_size = item.len() / (item.item_count().unwrap_or(1).max(1) as usize);
91 if avg_item_size > max_size {
92 return Err(item
93 .attachment_type()
94 .map(|t| t.into())
95 .unwrap_or_else(|| item.ty().into()));
96 }
97 }
98
99 if event_size > config.max_event_size() {
100 return Err(DiscardItemType::Event);
101 }
102 if attachments_size > config.max_attachments_size() {
103 return Err(DiscardItemType::Attachment(
104 DiscardAttachmentType::Attachment,
105 ));
106 }
107 if session_count > config.max_session_count() {
108 return Err(DiscardItemType::Session);
109 }
110 if client_reports_size > config.max_client_reports_size() {
111 return Err(DiscardItemType::ClientReport);
112 }
113
114 Ok(())
115}
116
117pub fn remove_unknown_items(config: &Config, envelope: &mut ManagedEnvelope) {
122 if !config.accept_unknown_items() {
123 envelope.retain_items(|item| match item.ty() {
124 ItemType::Unknown(ty) => {
125 relay_log::debug!("dropping unknown item of type '{ty}'");
126 ItemAction::DropSilently
127 }
128 _ => match item.attachment_type() {
129 Some(AttachmentType::Unknown(ty)) => {
130 relay_log::debug!("dropping unknown attachment of type '{ty}'");
131 ItemAction::DropSilently
132 }
133 _ => ItemAction::Keep,
134 },
135 });
136 }
137}