Skip to content
28 changes: 28 additions & 0 deletions doc_classes/SentryFeedback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SentryFeedback" inherits="RefCounted" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
Represents user feedback in Sentry.
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<members>
<member name="associated_event_id" type="String" setter="set_associated_event_id" getter="get_associated_event_id" default="&quot;&quot;">
The identifier of an error event in the same project. [i]Optional[/i].
Use this to explicitly link a related error in the feedback UI.
</member>
<member name="contact_email" type="String" setter="set_contact_email" getter="get_contact_email" default="&quot;&quot;">
The email of the user who submitted the feedback. [i]Optional[/i].
If excluded, Sentry attempts to fill this in with user context. Anonymous feedbacks (no name or email) are still accepted.
</member>
<member name="message" type="String" setter="set_message" getter="get_message" default="&quot;&quot;">
Comments of the user, describing what happened and/or sharing feedback. [i]Required[/i].
The max length is 4096 characters.
</member>
<member name="name" type="String" setter="set_name" getter="get_name" default="&quot;&quot;">
The name of the user who submitted the feedback. [i]Optional[/i].
If excluded, Sentry attempts to fill this in with user context. Anonymous feedbacks (no name or email) are still accepted.
</member>
</members>
</class>
7 changes: 7 additions & 0 deletions doc_classes/SentrySDK.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
Captures [param event] and sends it to Sentry, returning the event ID. You can create an event with [method SentrySDK.create_event].
</description>
</method>
<method name="capture_feedback">
<return type="void" />
<param index="0" name="feedback" type="SentryFeedback" />
<description>
Captures user [param feedback] and sends it to Sentry. The feedback can optionally be associated with a specific error event if the [member SentryFeedback.associated_event_id] is set.
</description>
</method>
<method name="capture_message">
<return type="String" />
<param index="0" name="message" type="String" />
Expand Down
22 changes: 22 additions & 0 deletions project/test/suites/test_feedback.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
extends GdUnitTestSuite
## Test Feedback class.


func test_feedback_properties() -> void:
var feedback := SentryFeedback.new()

assert_str(feedback.associated_event_id).is_empty()
feedback.associated_event_id = "082ce03eface41dd94b8c6b005382d5e"
assert_str(feedback.associated_event_id).is_equal("082ce03eface41dd94b8c6b005382d5e")

assert_str(feedback.name).is_empty()
feedback.name = "Bob"
assert_str(feedback.name).is_equal(feedback.name)

assert_str(feedback.contact_email).is_empty()
feedback.contact_email = "[email protected]"
assert_str(feedback.contact_email).is_equal("[email protected]")

assert_str(feedback.message).is_empty()
feedback.message = "something happened"
assert_str(feedback.message).is_equal("something happened")
1 change: 1 addition & 0 deletions project/test/suites/test_feedback.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://m3p77wja6wk0
2 changes: 2 additions & 0 deletions src/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "sentry/sentry_attachment.h"
#include "sentry/sentry_breadcrumb.h"
#include "sentry/sentry_event.h"
#include "sentry/sentry_feedback.h"
#include "sentry/sentry_options.h"
#include "sentry/sentry_sdk.h"
#include "sentry/sentry_user.h"
Expand Down Expand Up @@ -48,6 +49,7 @@ void register_runtime_classes() {
GDREGISTER_INTERNAL_CLASS(RuntimeConfig);
GDREGISTER_CLASS(SentryUser);
GDREGISTER_CLASS(SentryTimestamp);
GDREGISTER_CLASS(SentryFeedback);
GDREGISTER_CLASS(SentrySDK);
GDREGISTER_ABSTRACT_CLASS(SentryAttachment);
GDREGISTER_ABSTRACT_CLASS(SentryEvent);
Expand Down
1 change: 1 addition & 0 deletions src/sentry/cocoa/cocoa_includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ using SentryException = ::SentryException;
using SentryStacktrace = ::SentryStacktrace;
using SentryFrame = ::SentryFrame;
using SentryThread = ::SentryThread;
using SentryFeedback = ::SentryFeedback;

} // namespace objc

Expand Down
2 changes: 2 additions & 0 deletions src/sentry/cocoa/cocoa_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class CocoaSDK : public InternalSDK {
virtual Ref<SentryEvent> create_event() override;
virtual String capture_event(const Ref<SentryEvent> &p_event) override;

virtual void capture_feedback(const Ref<SentryFeedback> &p_feedback) override;

virtual void add_attachment(const Ref<SentryAttachment> &p_attachment) override;

virtual void init(const PackedStringArray &p_global_attachments, const Callable &p_configuration_callback) override;
Expand Down
19 changes: 19 additions & 0 deletions src/sentry/cocoa/cocoa_sdk.mm
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@
return event_id ? string_from_objc(event_id.sentryIdString) : String();
}

void CocoaSDK::capture_feedback(const Ref<SentryFeedback> &p_feedback) {
ERR_FAIL_COND_MSG(p_feedback.is_null(), "Sentry: Can't capture feedback - feedback object is null.");
ERR_FAIL_COND_MSG(p_feedback->get_message().is_empty(), "Sentry: Can't capture feedback - feedback message is empty.");

objc::SentryId *id = nil;

if (!p_feedback->get_associated_event_id().is_empty()) {
id = [[objc::SentryId alloc] initWithUUIDString:string_to_objc(p_feedback->get_associated_event_id())];
}

objc::SentryFeedback *cocoa_feedback = [[objc::SentryFeedback alloc] initWithMessage:string_to_objc(p_feedback->get_message())
name:string_to_objc_or_nil_if_empty(p_feedback->get_name())
email:string_to_objc_or_nil_if_empty(p_feedback->get_contact_email())
source:SentryFeedbackSourceCustom
associatedEventId:id
attachments:nil];
[objc::SentrySDK captureFeedback:cocoa_feedback];
}

void CocoaSDK::add_attachment(const Ref<SentryAttachment> &p_attachment) {
ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment.");

Expand Down
2 changes: 2 additions & 0 deletions src/sentry/disabled/disabled_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class DisabledSDK : public InternalSDK {
virtual Ref<SentryEvent> create_event() override { return memnew(DisabledEvent); }
virtual String capture_event(const Ref<SentryEvent> &p_event) override { return ""; }

virtual void capture_feedback(const Ref<SentryFeedback> &p_feedback) override {}

virtual void add_attachment(const Ref<SentryAttachment> &p_attachment) override {}

virtual void init(const PackedStringArray &p_global_attachments, const Callable &p_configuration_callback) override {}
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/internal_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "sentry/sentry_attachment.h"
#include "sentry/sentry_breadcrumb.h"
#include "sentry/sentry_event.h"
#include "sentry/sentry_feedback.h"
#include "sentry/sentry_user.h"

#include <godot_cpp/variant/dictionary.hpp>
Expand Down Expand Up @@ -37,6 +38,8 @@ class InternalSDK {
virtual Ref<SentryEvent> create_event() = 0;
virtual String capture_event(const Ref<SentryEvent> &p_event) = 0;

virtual void capture_feedback(const Ref<SentryFeedback> &p_feedback) = 0;

virtual void add_attachment(const Ref<SentryAttachment> &p_attachment) = 0;

virtual void init(const PackedStringArray &p_global_attachments, const Callable &p_configuration_callback) = 0;
Expand Down
14 changes: 14 additions & 0 deletions src/sentry/sentry_feedback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "sentry_feedback.h"

#include "sentry/util/simple_bind.h"

namespace sentry {

void SentryFeedback::_bind_methods() {
BIND_PROPERTY(SentryFeedback, PropertyInfo(Variant::STRING, "name"), set_name, get_name);
BIND_PROPERTY(SentryFeedback, PropertyInfo(Variant::STRING, "contact_email"), set_contact_email, get_contact_email);
BIND_PROPERTY(SentryFeedback, PropertyInfo(Variant::STRING, "message"), set_message, get_message);
BIND_PROPERTY(SentryFeedback, PropertyInfo(Variant::STRING, "associated_event_id"), set_associated_event_id, get_associated_event_id);
}

} //namespace sentry
35 changes: 35 additions & 0 deletions src/sentry/sentry_feedback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <godot_cpp/classes/ref_counted.hpp>

using namespace godot;

namespace sentry {

class SentryFeedback : public RefCounted {
GDCLASS(SentryFeedback, RefCounted);

private:
String name;
String contact_email;
String message;
String associated_event_id;

protected:
static void _bind_methods();

public:
String get_name() const { return name; }
void set_name(const String &p_name) { name = p_name; }

String get_contact_email() const { return contact_email; }
void set_contact_email(const String &p_contact_email) { contact_email = p_contact_email; }

String get_message() const { return message; }
void set_message(const String &p_message) { message = p_message; }

String get_associated_event_id() const { return associated_event_id; }
void set_associated_event_id(const String &p_associated_event_id) { associated_event_id = p_associated_event_id; }
};

} //namespace sentry
10 changes: 10 additions & 0 deletions src/sentry/sentry_sdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ String SentrySDK::capture_event(const Ref<SentryEvent> &p_event) {
return internal_sdk->capture_event(p_event);
}

void SentrySDK::capture_feedback(const Ref<SentryFeedback> &p_feedback) {
ERR_FAIL_COND_MSG(p_feedback.is_null(), "Sentry: Can't capture feedback - feedback object is null.");
ERR_FAIL_COND_MSG(p_feedback->get_message().is_empty(), "Sentry: Can't capture feedback - feedback message is empty.");
if (p_feedback->get_message().length() > 4096) {
WARN_PRINT("Sentry: Feedback message is too long (max 4096 characters).");
}
return internal_sdk->capture_feedback(p_feedback);
}

void SentrySDK::add_attachment(const Ref<SentryAttachment> &p_attachment) {
ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment.");
internal_sdk->add_attachment(p_attachment);
Expand Down Expand Up @@ -362,6 +371,7 @@ void SentrySDK::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_user"), &SentrySDK::remove_user);
ClassDB::bind_method(D_METHOD("create_event"), &SentrySDK::create_event);
ClassDB::bind_method(D_METHOD("capture_event", "event"), &SentrySDK::capture_event);
ClassDB::bind_method(D_METHOD("capture_feedback", "feedback"), &SentrySDK::capture_feedback);
ClassDB::bind_method(D_METHOD("add_attachment", "attachment"), &SentrySDK::add_attachment);

// Hidden API methods -- used in testing.
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/sentry_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class SentrySDK : public Object {
Ref<SentryEvent> create_event() const;
String capture_event(const Ref<SentryEvent> &p_event);

void capture_feedback(const Ref<SentryFeedback> &p_feedback);

void add_attachment(const Ref<SentryAttachment> &p_attachment);

// * Hidden API methods -- used in testing
Expand Down
Loading