Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom switch attachment expansion #4566

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ backoff = "0.4.0"
bindgen = "0.70.1"
brotli = "6.0.0"
bytecount = "0.6.8"
bytes = "1.9.0"
bytes = "1.10.1"
bzip2 = "0.4.4"
cadence = "1.5.0"
chrono = { version = "0.4.38", default-features = false, features = [
Expand Down Expand Up @@ -202,4 +202,4 @@ url = "2.5.4"
utf16string = "0.2.0"
uuid = { version = "1.11.0", features = ["serde", "v4"] }
walkdir = "2.5.0"
zstd = "0.13.2"
zstd = { version = "0.13.2", features = ["experimental"] }
36 changes: 33 additions & 3 deletions relay-server/src/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1154,14 +1154,19 @@ impl Envelope {
}

/// Parses an envelope from bytes.
#[allow(dead_code)]
pub fn parse_bytes(bytes: Bytes) -> Result<Box<Self>, EnvelopeError> {
let (headers, offset) = Self::parse_headers(&bytes)?;
let items = Self::parse_items(&bytes, offset)?;

Ok(Box::new(Envelope { headers, items }))
}

/// Parse envelope items from bytes buffer that doesn't contain a complete envelope.
/// Note: the envelope header must not be present in the data. Use `parse_bytes()` instead.
pub fn parse_items_bytes(bytes: Bytes) -> Result<Items, EnvelopeError> {
Self::parse_items(&bytes, 0)
}

/// Parses an envelope taking into account a request.
///
/// This method is intended to be used when parsing an envelope that was sent as part of a web
Expand Down Expand Up @@ -1199,13 +1204,11 @@ impl Envelope {
}

/// Returns the number of items in this envelope.
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.items.len()
}

/// Returns `true` if this envelope does not contain any items.
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
Expand Down Expand Up @@ -1966,6 +1969,33 @@ mod tests {
);
}

#[test]
fn test_parse_empty_items() {
// Without terminating newline after header
let items = Envelope::parse_items_bytes(Bytes::from("")).unwrap();
assert_eq!(items.len(), 0);
}

#[test]
fn test_parse_multiple_items() {
let bytes = Bytes::from(
"\
{\"type\":\"attachment\"}\n\
helloworld\n\
{\"type\":\"replay_recording\"}\n\
helloworld\
",
);

// Without terminating newline after header
let items = Envelope::parse_items_bytes(bytes).unwrap();
assert_eq!(items.len(), 2);
assert_eq!(items[0].len(), 10);
assert_eq!(items[0].ty(), &ItemType::Attachment);
assert_eq!(items[1].len(), 10);
assert_eq!(items[1].ty(), &ItemType::ReplayRecording);
}

#[test]
fn test_parse_request_envelope() {
let bytes = Bytes::from("{\"event_id\":\"9ec79c33ec9942ab8353589fcb2e04dc\"}");
Expand Down
10 changes: 10 additions & 0 deletions relay-server/src/services/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ use crate::services::global_config::GlobalConfigHandle;
use crate::services::metrics::{Aggregator, FlushBuckets, MergeBuckets, ProjectBuckets};
use crate::services::outcome::{DiscardReason, Outcome, TrackOutcome};
use crate::services::processor::event::FiltersStatus;
use crate::services::processor::nnswitch::SwitchProcessingError;
use crate::services::projects::cache::ProjectCacheHandle;
use crate::services::projects::project::{ProjectInfo, ProjectState};
use crate::services::test_store::{Capture, TestStore};
Expand Down Expand Up @@ -102,6 +103,9 @@ mod standalone;
#[cfg(feature = "processing")]
mod unreal;

#[cfg(feature = "processing")]
mod nnswitch;

/// Creates the block only if used with `processing` feature.
///
/// Provided code block will be executed only if the provided config has `processing_enabled` set.
Expand Down Expand Up @@ -527,6 +531,10 @@ pub enum ProcessingError {

#[error("replay filtered with reason: {0:?}")]
ReplayFiltered(FilterStatKey),

#[cfg(feature = "processing")]
#[error("nintendo switch dying message processing failed")]
InvalidNintendoDyingMessage(#[source] SwitchProcessingError),
}

impl ProcessingError {
Expand All @@ -546,6 +554,7 @@ impl ProcessingError {
Self::InvalidTimestamp => Some(Outcome::Invalid(DiscardReason::Timestamp)),
Self::DuplicateItem(_) => Some(Outcome::Invalid(DiscardReason::DuplicateItem)),
Self::NoEventPayload => Some(Outcome::Invalid(DiscardReason::NoEventPayload)),
Self::InvalidNintendoDyingMessage(_) => Some(Outcome::Invalid(DiscardReason::Payload)),

// Processing-only outcomes (Sentry-internal Relays)
#[cfg(feature = "processing")]
Expand Down Expand Up @@ -1552,6 +1561,7 @@ impl EnvelopeProcessorService {

if_processing!(self.inner.config, {
unreal::expand(managed_envelope, &self.inner.config)?;
nnswitch::expand(managed_envelope)?;
});

let extraction_result = event::extract(
Expand Down
Loading