Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Features

- Add message category attribute to structured logs for better filtering ([#1199](https://github.com/getsentry/sentry-unreal/pull/1199))
- Add attachments support for user feedback ([#1121](https://github.com/getsentry/sentry-unreal/pull/1121))

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

#include "AndroidSentryFeedback.h"

#include "AndroidSentryHint.h"
#include "AndroidSentryId.h"

#include "Infrastructure/AndroidSentryJavaClasses.h"

FAndroidSentryFeedback::FAndroidSentryFeedback(const FString& message)
: FSentryJavaObjectWrapper(SentryJavaClasses::Feedback, "(Ljava/lang/String;)V",
*GetJString(message))
, Hint(nullptr)
{
SetupClassMethods();
}
Expand Down Expand Up @@ -69,3 +71,18 @@ FString FAndroidSentryFeedback::GetAssociatedEvent() const
TSharedPtr<FAndroidSentryId> eventId = MakeShareable(new FAndroidSentryId(*idAndroid));
return eventId->ToString();
}

void FAndroidSentryFeedback::AddAttachment(TSharedPtr<ISentryAttachment> attachment)
{
if (!Hint)
{
Hint = MakeShareable(new FAndroidSentryHint());
}

Hint->AddAttachment(attachment);
}

TSharedPtr<FAndroidSentryHint> FAndroidSentryFeedback::GetHint()
{
return Hint;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Infrastructure/AndroidSentryJavaObjectWrapper.h"

class ISentryId;
class FAndroidSentryHint;

class FAndroidSentryFeedback : public ISentryFeedback, public FSentryJavaObjectWrapper
{
Expand All @@ -22,6 +23,9 @@ class FAndroidSentryFeedback : public ISentryFeedback, public FSentryJavaObjectW
virtual FString GetContactEmail() const override;
virtual void SetAssociatedEvent(const FString& eventId) override;
virtual FString GetAssociatedEvent() const override;
virtual void AddAttachment(TSharedPtr<ISentryAttachment> attachment) override;

TSharedPtr<FAndroidSentryHint> GetHint();

private:
FSentryJavaMethod GetMessageMethod;
Expand All @@ -31,6 +35,8 @@ class FAndroidSentryFeedback : public ISentryFeedback, public FSentryJavaObjectW
FSentryJavaMethod GetContactEmailMethod;
FSentryJavaMethod SetAssociatedEventMethod;
FSentryJavaMethod GetAssociatedEventMethod;

TSharedPtr<FAndroidSentryHint> Hint;
};

typedef FAndroidSentryFeedback FPlatformSentryFeedback;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "AndroidSentryBreadcrumb.h"
#include "AndroidSentryEvent.h"
#include "AndroidSentryFeedback.h"
#include "AndroidSentryHint.h"
#include "AndroidSentryId.h"
#include "AndroidSentryTransaction.h"
#include "AndroidSentryTransactionContext.h"
Expand Down Expand Up @@ -292,8 +293,10 @@ void FAndroidSentrySubsystem::CaptureFeedback(TSharedPtr<ISentryFeedback> feedba
{
TSharedPtr<FAndroidSentryFeedback> feedbackAndroid = StaticCastSharedPtr<FAndroidSentryFeedback>(feedback);

FSentryJavaObjectWrapper::CallStaticObjectMethod<jobject>(SentryJavaClasses::Sentry, "captureFeedback", "(Lio/sentry/protocol/Feedback;)Lio/sentry/protocol/SentryId;",
feedbackAndroid->GetJObject());
TSharedPtr<FAndroidSentryHint> hintAndroid = feedbackAndroid->GetHint();

FSentryJavaObjectWrapper::CallStaticObjectMethod<jobject>(SentryJavaClasses::Sentry, "captureFeedback", "(Lio/sentry/protocol/Feedback;Lio/sentry/Hint;)Lio/sentry/protocol/SentryId;",
feedbackAndroid->GetJObject(), hintAndroid ? hintAndroid->GetJObject() : nullptr);
}

void FAndroidSentrySubsystem::SetUser(TSharedPtr<ISentryUser> user)
Expand Down
29 changes: 28 additions & 1 deletion plugin-dev/Source/Sentry/Private/Apple/AppleSentryFeedback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

#include "AppleSentryFeedback.h"

#include "AppleSentryAttachment.h"
#include "AppleSentryId.h"

#include "Convenience/AppleSentryInclude.h"
#include "Convenience/AppleSentryMacro.h"

#include "Misc/FileHelper.h"

FAppleSentryFeedback::FAppleSentryFeedback(const FString& message)
: Message(message)
{
Expand Down Expand Up @@ -52,6 +55,11 @@ FString FAppleSentryFeedback::GetAssociatedEvent() const
return EventId;
}

void FAppleSentryFeedback::AddAttachment(TSharedPtr<ISentryAttachment> attachment)
{
Attachments.Add(attachment);
}

SentryFeedback* FAppleSentryFeedback::CreateSentryFeedback(TSharedPtr<FAppleSentryFeedback> feedback)
{
SentryId* id = nil;
Expand All @@ -61,10 +69,29 @@ SentryFeedback* FAppleSentryFeedback::CreateSentryFeedback(TSharedPtr<FAppleSent
id = idIOS->GetNativeObject();
}

NSMutableArray<SentryAttachment*>* attachments = nil;
if (feedback->Attachments.Num() > 0)
{
attachments = [NSMutableArray arrayWithCapacity:feedback->Attachments.Num()];

for (const TSharedPtr<ISentryAttachment>& attachment : feedback->Attachments)
{
TSharedPtr<FAppleSentryAttachment> attachmentApple = StaticCastSharedPtr<FAppleSentryAttachment>(attachment);
if (attachmentApple)
{
SentryAttachment* nativeAttachment = attachmentApple->GetNativeObject();
if (nativeAttachment != nil)
{
[attachments addObject:nativeAttachment];
}
}
}
}

return [[SENTRY_APPLE_CLASS(SentryFeedback) alloc] initWithMessage:feedback->Message.GetNSString()
name:feedback->Name.GetNSString()
email:feedback->Email.GetNSString()
source:SentryFeedbackSourceCustom
associatedEventId:id
attachments:nil];
attachments:attachments];
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class FAppleSentryFeedback : public ISentryFeedback
virtual FString GetContactEmail() const override;
virtual void SetAssociatedEvent(const FString& eventId) override;
virtual FString GetAssociatedEvent() const override;
virtual void AddAttachment(TSharedPtr<ISentryAttachment> attachment) override;

static SentryFeedback* CreateSentryFeedback(TSharedPtr<FAppleSentryFeedback> feedback);

Expand All @@ -27,6 +28,8 @@ class FAppleSentryFeedback : public ISentryFeedback
FString Name;
FString Email;
FString EventId;

TArray<TSharedPtr<ISentryAttachment>> Attachments;
};

typedef FAppleSentryFeedback FPlatformSentryFeedback;
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
// Copyright (c) 2025 Sentry. All Rights Reserved.

#include "GenericPlatformSentryFeedback.h"
#include "GenericPlatformSentryAttachment.h"

#include "Infrastructure/GenericPlatformSentryConverters.h"

#if USE_SENTRY_NATIVE

FGenericPlatformSentryFeedback::FGenericPlatformSentryFeedback()
: Hint(nullptr)
{
Feedback = sentry_value_new_object();
}

FGenericPlatformSentryFeedback::FGenericPlatformSentryFeedback(const FString& message)
: Hint(nullptr)
Comment thread
tustanivsky marked this conversation as resolved.
{
Feedback = sentry_value_new_object();
sentry_value_set_by_key(Feedback, "message", sentry_value_new_string(TCHAR_TO_UTF8(*message)));
Expand Down Expand Up @@ -69,4 +72,55 @@ FString FGenericPlatformSentryFeedback::GetAssociatedEvent() const
return FString(UTF8_TO_TCHAR(sentry_value_as_string(comment)));
}

void FGenericPlatformSentryFeedback::AddAttachment(TSharedPtr<ISentryAttachment> attachment)
{
if (!Hint)
{
Hint = sentry_hint_new();
Comment thread
tustanivsky marked this conversation as resolved.
}

TSharedPtr<FGenericPlatformSentryAttachment> platformAttachment = StaticCastSharedPtr<FGenericPlatformSentryAttachment>(attachment);

if (!platformAttachment->GetPath().IsEmpty())
{
AddFileAttachment(platformAttachment);
}
else
{
AddByteAttachment(platformAttachment);
}
Comment thread
cursor[bot] marked this conversation as resolved.
}

sentry_hint_t* FGenericPlatformSentryFeedback::GetHintNativeObject()
{
return Hint;
}

void FGenericPlatformSentryFeedback::AddFileAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment)
{
sentry_attachment_t* nativeAttachment =
sentry_hint_attach_file(Hint, TCHAR_TO_UTF8(*attachment->GetPath()));

if (!attachment->GetFilename().IsEmpty())
sentry_attachment_set_filename(nativeAttachment, TCHAR_TO_UTF8(*attachment->GetFilename()));

if (!attachment->GetContentType().IsEmpty())
sentry_attachment_set_content_type(nativeAttachment, TCHAR_TO_UTF8(*attachment->GetContentType()));

attachment->SetNativeObject(nativeAttachment);
Comment thread
tustanivsky marked this conversation as resolved.
}

void FGenericPlatformSentryFeedback::AddByteAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment)
{
const TArray<uint8>& byteBuf = attachment->GetDataByRef();

sentry_attachment_t* nativeAttachment =
sentry_hint_attach_bytes(Hint, reinterpret_cast<const char*>(byteBuf.GetData()), byteBuf.Num(), TCHAR_TO_UTF8(*attachment->GetFilename()));

if (!attachment->GetContentType().IsEmpty())
sentry_attachment_set_content_type(nativeAttachment, TCHAR_TO_UTF8(*attachment->GetContentType()));

attachment->SetNativeObject(nativeAttachment);
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#if USE_SENTRY_NATIVE

class FGenericPlatformSentryAttachment;

class FGenericPlatformSentryFeedback : public ISentryFeedback
{
public:
Expand All @@ -24,11 +26,22 @@ class FGenericPlatformSentryFeedback : public ISentryFeedback
virtual FString GetContactEmail() const override;
virtual void SetAssociatedEvent(const FString& eventId) override;
virtual FString GetAssociatedEvent() const override;
virtual void AddAttachment(TSharedPtr<ISentryAttachment> attachment) override;

sentry_hint_t* GetHintNativeObject();

protected:
virtual void AddFileAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment);
virtual void AddByteAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment);

sentry_hint_t* Hint;

private:
sentry_value_t Feedback;
};

#if !PLATFORM_MICROSOFT
typedef FGenericPlatformSentryFeedback FPlatformSentryFeedback;
#endif

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,8 @@ TSharedPtr<ISentryId> FGenericPlatformSentrySubsystem::CaptureEnsure(const FStri
void FGenericPlatformSentrySubsystem::CaptureFeedback(TSharedPtr<ISentryFeedback> feedback)
{
TSharedPtr<FGenericPlatformSentryFeedback> Feedback = StaticCastSharedPtr<FGenericPlatformSentryFeedback>(feedback);
sentry_capture_feedback(Feedback->GetNativeObject());

sentry_capture_feedback_with_hint(Feedback->GetNativeObject(), Feedback->GetHintNativeObject());
}

void FGenericPlatformSentrySubsystem::SetUser(TSharedPtr<ISentryUser> InUser)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "Android/AndroidSentryFeedback.h"
#elif PLATFORM_APPLE
#include "Apple/AppleSentryFeedback.h"
#elif USE_SENTRY_NATIVE && PLATFORM_MICROSOFT
#include "Microsoft/MicrosoftSentryFeedback.h"
#elif USE_SENTRY_NATIVE
#include "GenericPlatform/GenericPlatformSentryFeedback.h"
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "CoreMinimal.h"

class ISentryAttachment;

class ISentryFeedback
{
public:
Expand All @@ -16,4 +18,5 @@ class ISentryFeedback
virtual FString GetContactEmail() const = 0;
virtual void SetAssociatedEvent(const FString& eventId) = 0;
virtual FString GetAssociatedEvent() const = 0;
virtual void AddAttachment(TSharedPtr<ISentryAttachment> attachment) = 0;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2025 Sentry. All Rights Reserved.

#include "MicrosoftSentryFeedback.h"

#include "GenericPlatform/GenericPlatformSentryAttachment.h"

#if USE_SENTRY_NATIVE

FMicrosoftSentryFeedback::FMicrosoftSentryFeedback()
: FGenericPlatformSentryFeedback()
{
}

FMicrosoftSentryFeedback::FMicrosoftSentryFeedback(const FString& message)
: FGenericPlatformSentryFeedback(message)
{
}

void FMicrosoftSentryFeedback::AddFileAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment)
{
sentry_attachment_t* nativeAttachment =
sentry_hint_attach_filew(Hint, *attachment->GetPath());

if (!attachment->GetFilename().IsEmpty())
sentry_attachment_set_filenamew(nativeAttachment, *attachment->GetFilename());

if (!attachment->GetContentType().IsEmpty())
sentry_attachment_set_content_type(nativeAttachment, TCHAR_TO_UTF8(*attachment->GetContentType()));

attachment->SetNativeObject(nativeAttachment);
}

void FMicrosoftSentryFeedback::AddByteAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment)
{
const TArray<uint8>& byteBuf = attachment->GetDataByRef();

sentry_attachment_t* nativeAttachment =
sentry_hint_attach_bytesw(Hint, reinterpret_cast<const char*>(byteBuf.GetData()), byteBuf.Num(), *attachment->GetFilename());

if (!attachment->GetContentType().IsEmpty())
sentry_attachment_set_content_type(nativeAttachment, TCHAR_TO_UTF8(*attachment->GetContentType()));

attachment->SetNativeObject(nativeAttachment);
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2025 Sentry. All Rights Reserved.

#pragma once

#if USE_SENTRY_NATIVE

#include "GenericPlatform/GenericPlatformSentryFeedback.h"

class FMicrosoftSentryFeedback : public FGenericPlatformSentryFeedback
{
public:
FMicrosoftSentryFeedback();
FMicrosoftSentryFeedback(const FString& message);
virtual ~FMicrosoftSentryFeedback() override = default;

protected:
virtual void AddFileAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment) override;
virtual void AddByteAttachment(TSharedPtr<FGenericPlatformSentryAttachment> attachment) override;
};

typedef FMicrosoftSentryFeedback FPlatformSentryFeedback;

#endif
Comment thread
cursor[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class FNullSentryFeedback final : public ISentryFeedback
virtual FString GetContactEmail() const override { return TEXT(""); }
virtual void SetAssociatedEvent(const FString& eventId) override {}
virtual FString GetAssociatedEvent() const override { return TEXT(""); }
virtual void AddAttachment(TSharedPtr<ISentryAttachment> attachment) override {}
};

typedef FNullSentryFeedback FPlatformSentryFeedback;
Loading
Loading