Skip to content
Merged
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
2 changes: 1 addition & 1 deletion relay-server/src/processing/errors/errors/unreal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl SentryError for Unreal {
//
// This is currently still split to avoid too many changes and code duplication at once.
if let Some(result) =
crate::utils::process_unreal(event_id, &mut event, &attachments, user_header)
crate::utils::process_unreal(expansion.context, event_id, &mut event, &attachments, user_header)
.map_err(ProcessingError::InvalidUnrealReport)?
{
user_reports.extend(result.user_reports);
Expand Down
63 changes: 30 additions & 33 deletions relay-server/src/utils/unreal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,6 @@ const MAX_NUM_UNREAL_LOGS: usize = 40;
/// Client SDK name used for the event payload to identify the UE4 crash reporter.
const CLIENT_SDK_NAME: &str = "unreal.crashreporter";

fn get_event_item(data: &[u8]) -> Result<Option<Item>, Unreal4Error> {
let mut context = Unreal4Context::parse(data)?;
let json = match context
.game_data
.remove(crate::constants::SENTRY_CRASH_PAYLOAD_KEY)
{
Some(json) if !json.is_empty() => json,
_ => return Ok(None),
};

relay_log::trace!("adding event payload from unreal context");
let mut item = Item::new(ItemType::Event);
item.set_payload(ContentType::Json, json);
Ok(Some(item))
}

/// Extracts the items from an Unreal 4 crash report payload.
pub fn extract_items(payload: Bytes, config: &Config) -> Result<Items, ProcessingError> {
let mut items = Items::new();
Expand All @@ -63,9 +47,6 @@ pub fn extract_items(payload: Bytes, config: &Config) -> Result<Items, Processin

let mut item = Item::new(ItemType::Attachment);
item.set_filename(file.name());
// TODO: This clones data. Update symbolic to allow moving the bytes out.
//
// See: <https://github.com/getsentry/symbolic/issues/959>.
item.set_payload(content_type, file.into_bytes());
item.set_attachment_type(attachment_type);
items.push(item);
Expand All @@ -76,15 +57,17 @@ pub fn extract_items(payload: Bytes, config: &Config) -> Result<Items, Processin

/// Expands items previously extracted from a report in to the [`UnrealExpansion`] representation.
pub fn expand_unreal_items(items: Items) -> Result<UnrealExpansion, ProcessingError> {
let event = items
let mut context = items
.iter()
.find(|&item| matches!(item.attachment_type(), Some(AttachmentType::UnrealContext)))
.map(|item| get_event_item(&item.payload()))
.transpose()?
.flatten();
.map(|item| Unreal4Context::parse(&item.payload()))
.transpose()?;

let event = context.as_mut().and_then(take_event_item);

Ok(UnrealExpansion {
event,
context,
attachments: items,
})
}
Expand All @@ -101,11 +84,31 @@ pub struct UnrealExpansion {
/// The error event if the crash contained one.
#[cfg_attr(not(feature = "processing"), expect(unused))]
pub event: Option<Item>,
/// The parsed unreal context.
///
/// Note: the raw unreal context may still be in [`Self::attachments`].
#[cfg_attr(not(feature = "processing"), expect(unused))]
pub context: Option<Unreal4Context>,
/// Files of the report as attachments.
#[cfg_attr(not(feature = "processing"), expect(unused))]
pub attachments: Items,
}

fn take_event_item(context: &mut Unreal4Context) -> Option<Item> {
let json = context
.game_data
.remove(crate::constants::SENTRY_CRASH_PAYLOAD_KEY)?;

if json.is_empty() {
return None;
}

relay_log::trace!("adding event payload from unreal context");
let mut item = Item::new(ItemType::Event);
item.set_payload(ContentType::Json, json);
Some(item)
}

fn merge_unreal_user_info(event: &mut Event, user_info: &str) {
let mut parts = user_info.split('|');

Expand Down Expand Up @@ -351,24 +354,20 @@ fn merge_unreal_context(event: &mut Event, context: Unreal4Context) {
/// The `user_header` should be extracted from the [`crate::constants::UNREAL_USER_HEADER`] envelope header.
#[cfg_attr(not(feature = "processing"), expect(unused))]
pub fn process_unreal<'a>(
context: Option<Unreal4Context>,
event_id: EventId,
event: &mut Annotated<Event>,
attachments: impl IntoIterator<Item = &'a Item> + Clone,
attachments: impl IntoIterator<Item = &'a Item>,
user_header: Option<&str>,
) -> Result<Option<ProcessedUnrealReport>, Unreal4Error> {
let context_item = attachments
.clone()
Comment thread
cursor[bot] marked this conversation as resolved.
.into_iter()
.find(|item| item.attachment_type() == Some(AttachmentType::UnrealContext));

let mut logs_items = attachments
.into_iter()
.filter(|item| item.attachment_type() == Some(AttachmentType::UnrealLogs))
.map(|item| item.payload())
.peekable();

// Early exit if there is no information.
if user_header.is_none() && context_item.is_none() && logs_items.peek().is_none() {
if context.is_none() && user_header.is_none() && logs_items.peek().is_none() {
return Ok(None);
}

Expand All @@ -383,9 +382,7 @@ pub fn process_unreal<'a>(
merge_unreal_logs(event, logs_items)?;

let mut user_reports = Items::new();
if let Some(context_item) = context_item {
let mut context = Unreal4Context::parse(&context_item.payload())?;

if let Some(mut context) = context {
if let Some(report) = get_unreal_user_report(event_id, &mut context) {
user_reports.push(report);
}
Expand Down
Loading