From d4dc09825618a5226b250d819df45baff34f7469 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 10:46:33 +0200 Subject: [PATCH 01/33] Add user attachments --- modules/sentry-native | 2 +- src/register_types.cpp | 6 ++++ src/sentry/disabled_attachment.h | 17 ++++++++++++ src/sentry/disabled_sdk.h | 3 ++ src/sentry/internal_sdk.h | 5 ++++ src/sentry/native/native_attachment.h | 23 +++++++++++++++ src/sentry/native/native_sdk.cpp | 40 +++++++++++++++++++++++++++ src/sentry/native/native_sdk.h | 3 ++ src/sentry_attachment.cpp | 29 +++++++++++++++++++ src/sentry_attachment.h | 32 +++++++++++++++++++++ src/sentry_sdk.cpp | 15 ++++++++++ src/sentry_sdk.h | 4 +++ 12 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/sentry/disabled_attachment.h create mode 100644 src/sentry/native/native_attachment.h create mode 100644 src/sentry_attachment.cpp create mode 100644 src/sentry_attachment.h diff --git a/modules/sentry-native b/modules/sentry-native index 6129d36d..99e59820 160000 --- a/modules/sentry-native +++ b/modules/sentry-native @@ -1 +1 @@ -Subproject commit 6129d36d717b77d53c8af8fe439ed0370fb63ea4 +Subproject commit 99e598206296b63301919b9bc20e36c39adb51a1 diff --git a/src/register_types.cpp b/src/register_types.cpp index 39e61289..e5eb3a7f 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -1,8 +1,10 @@ #include "editor/sentry_editor_export_plugin_unix.h" #include "editor/sentry_editor_plugin.h" #include "runtime_config.h" +#include "sentry/disabled_attachment.h" #include "sentry/disabled_event.h" #include "sentry/util/print.h" +#include "sentry_attachment.h" #include "sentry_configuration.h" #include "sentry_event.h" #include "sentry_logger.h" @@ -15,6 +17,7 @@ #include #ifdef NATIVE_SDK +#include "sentry/native/native_attachment.h" #include "sentry/native/native_event.h" #endif // NATIVE_SDK @@ -65,11 +68,14 @@ void initialize_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(SentryConfiguration); GDREGISTER_CLASS(SentryUser); GDREGISTER_CLASS(SentrySDK); + GDREGISTER_ABSTRACT_CLASS(SentryAttachment); GDREGISTER_ABSTRACT_CLASS(SentryEvent); + GDREGISTER_INTERNAL_CLASS(DisabledAttachment); GDREGISTER_INTERNAL_CLASS(DisabledEvent); GDREGISTER_INTERNAL_CLASS(SentryLogger); #ifdef NATIVE_SDK + GDREGISTER_INTERNAL_CLASS(NativeAttachment); GDREGISTER_INTERNAL_CLASS(NativeEvent); #endif diff --git a/src/sentry/disabled_attachment.h b/src/sentry/disabled_attachment.h new file mode 100644 index 00000000..cbd066ad --- /dev/null +++ b/src/sentry/disabled_attachment.h @@ -0,0 +1,17 @@ +#ifndef DISABLED_ATTACHMENT_H +#define DISABLED_ATTACHMENT_H + +#include "sentry_attachment.h" + +// Attachment class that does nothing (for unsupported platforms or disabled SDK). +class DisabledAttachment : public SentryAttachment { + GDCLASS(DisabledAttachment, SentryAttachment); + +protected: + static void _bind_methods() {} + +public: + virtual ~DisabledAttachment() override = default; +}; + +#endif // DISABLED_ATTACHMENT_H diff --git a/src/sentry/disabled_sdk.h b/src/sentry/disabled_sdk.h index 773c8d87..2a847bf9 100644 --- a/src/sentry/disabled_sdk.h +++ b/src/sentry/disabled_sdk.h @@ -26,6 +26,9 @@ class DisabledSDK : public InternalSDK { virtual Ref create_event() override { return memnew(DisabledEvent); } virtual String capture_event(const Ref &p_event) override { return ""; } + virtual void add_attachment(const Ref &p_attachment) override {} + virtual void remove_attachment(const Ref &p_attachment) override {} + virtual void initialize(const PackedStringArray &p_global_attachments) override {} }; diff --git a/src/sentry/internal_sdk.h b/src/sentry/internal_sdk.h index 35fca6c9..3b9ebad3 100644 --- a/src/sentry/internal_sdk.h +++ b/src/sentry/internal_sdk.h @@ -9,6 +9,8 @@ #include #include +class SentryAttachment; + using namespace godot; namespace sentry { @@ -34,6 +36,9 @@ class InternalSDK { virtual Ref create_event() = 0; virtual String capture_event(const Ref &p_event) = 0; + virtual void add_attachment(const Ref &p_attachment) = 0; + virtual void remove_attachment(const Ref &p_attachment) = 0; + virtual void initialize(const PackedStringArray &p_global_attachments) = 0; virtual ~InternalSDK() = default; diff --git a/src/sentry/native/native_attachment.h b/src/sentry/native/native_attachment.h new file mode 100644 index 00000000..9434c8f2 --- /dev/null +++ b/src/sentry/native/native_attachment.h @@ -0,0 +1,23 @@ +#ifndef NATIVE_ATTACHMENT_H +#define NATIVE_ATTACHMENT_H + +#include "sentry_attachment.h" + +#include + +// Attachment class that is used with the NativeSDK. +class NativeAttachment : public SentryAttachment { + GDCLASS(NativeAttachment, SentryAttachment); + +private: + sentry_attachment_t *native_attachment = nullptr; + +protected: + static void _bind_methods() {} + +public: + sentry_attachment_t *get_native_attachment() const { return native_attachment; } + void set_native_attachment(sentry_attachment_t *p_native_attachment) { native_attachment = p_native_attachment; } +}; + +#endif // NATIVE_ATTACHMENT_H diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index f7181e66..5c5225c8 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -4,6 +4,7 @@ #include "sentry/common_defs.h" #include "sentry/contexts.h" #include "sentry/level.h" +#include "sentry/native/native_attachment.h" #include "sentry/native/native_event.h" #include "sentry/native/native_util.h" #include "sentry/util/print.h" @@ -338,6 +339,45 @@ String NativeSDK::capture_event(const Ref &p_event) { return _uuid_as_string(uuid); } +void NativeSDK::add_attachment(const Ref &p_attachment) { + ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); + ERR_FAIL_COND_MSG(p_attachment->get_file_path().is_empty(), "Sentry: Can't add attachment with empty path."); + + NativeAttachment *native_attachment_wrapper = Object::cast_to(p_attachment.ptr()); + ERR_FAIL_NULL(native_attachment_wrapper); // Sanity check - this should never happen. + + ERR_FAIL_NULL(ProjectSettings::get_singleton()); + String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_file_path()); + sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8().get_data()); + if (!native_attachment) { + ERR_FAIL_MSG(vformat("Sentry: Failed to attach file: %s", absolute_path)); + } + + if (!p_attachment->get_content_type().is_empty()) { + sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8().get_data()); + } + + native_attachment_wrapper->set_native_attachment(native_attachment); + + sentry::util::print_debug(vformat("attached file: %s", absolute_path)); +} + +void NativeSDK::remove_attachment(const Ref &p_attachment) { + ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't remove null attachment."); + + NativeAttachment *native_attachment_wrapper = Object::cast_to(p_attachment.ptr()); + ERR_FAIL_NULL(native_attachment_wrapper); // Sanity check - this should never. + + sentry_attachment_t *native_attachment = native_attachment_wrapper->get_native_attachment(); + if (native_attachment) { + sentry_remove_attachment(native_attachment); + native_attachment_wrapper->set_native_attachment(nullptr); + sentry::util::print_debug(vformat("removed attachment: %s", p_attachment->get_file_path())); + } else { + sentry::util::print_warning(vformat("attempted to remove attachment that was not added: %s", p_attachment->get_file_path())); + } +} + void NativeSDK::initialize(const PackedStringArray &p_global_attachments) { ERR_FAIL_NULL(OS::get_singleton()); ERR_FAIL_NULL(ProjectSettings::get_singleton()); diff --git a/src/sentry/native/native_sdk.h b/src/sentry/native/native_sdk.h index 6af831d0..2411709d 100644 --- a/src/sentry/native/native_sdk.h +++ b/src/sentry/native/native_sdk.h @@ -33,6 +33,9 @@ class NativeSDK : public InternalSDK { virtual Ref create_event() override; virtual String capture_event(const Ref &p_event) override; + virtual void add_attachment(const Ref &p_attachment) override; + virtual void remove_attachment(const Ref &p_attachment) override; + virtual void initialize(const PackedStringArray &p_global_attachments) override; virtual ~NativeSDK() override; diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp new file mode 100644 index 00000000..d3d4c55f --- /dev/null +++ b/src/sentry_attachment.cpp @@ -0,0 +1,29 @@ +#include "sentry_attachment.h" + +#include "sentry/simple_bind.h" + +#include + +#ifdef NATIVE_SDK +#include "sentry/native/native_attachment.h" +#else +#include "sentry/disabled_attachment.h" +#endif + +void SentryAttachment::_bind_methods() { + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "content_type"), &SentryAttachment::create_with_path, DEFVAL("")); + + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), set_file_path, get_file_path); + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), set_content_type, get_content_type); +} + +Ref SentryAttachment::create_with_path(const String &p_path, const String &p_content_type) { +#ifdef NATIVE_SDK + Ref attachment = memnew(NativeAttachment); +#else + Ref attachment = memnew(DisabledAttachment); +#endif + attachment->set_file_path(p_path); + attachment->set_content_type(p_content_type); + return attachment; +} diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h new file mode 100644 index 00000000..70a9eec7 --- /dev/null +++ b/src/sentry_attachment.h @@ -0,0 +1,32 @@ +#ifndef SENTRY_ATTACHMENT_H +#define SENTRY_ATTACHMENT_H + +#include +#include + +using namespace godot; + +// Base class for attachment objects in the public API. +class SentryAttachment : public RefCounted { + GDCLASS(SentryAttachment, RefCounted); + +private: + String file_path; + String content_type; + +protected: + static void _bind_methods(); + +public: + void set_file_path(const String &p_path) { file_path = p_path; } + String get_file_path() const { return file_path; } + + void set_content_type(const String &p_content_type) { content_type = p_content_type; } + String get_content_type() const { return content_type; } + + static Ref create_with_path(const String &p_path, const String &p_content_type = ""); + + virtual ~SentryAttachment() = default; +}; + +#endif // SENTRY_ATTACHMENT_H diff --git a/src/sentry_sdk.cpp b/src/sentry_sdk.cpp index 908d69d3..3e7c0144 100644 --- a/src/sentry_sdk.cpp +++ b/src/sentry_sdk.cpp @@ -5,6 +5,7 @@ #include "sentry/contexts.h" #include "sentry/disabled_sdk.h" #include "sentry/util/print.h" +#include "sentry_attachment.h" #include #include @@ -77,6 +78,18 @@ String SentrySDK::capture_event(const Ref &p_event) { return internal_sdk->capture_event(p_event); } +void SentrySDK::add_attachment(const Ref &p_attachment) { + ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); + ERR_FAIL_COND_MSG(p_attachment->get_file_path().is_empty(), "Sentry: Can't add attachment with empty path."); + + internal_sdk->add_attachment(p_attachment); +} + +void SentrySDK::remove_attachment(const Ref &p_attachment) { + ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't remove null attachment."); + internal_sdk->remove_attachment(p_attachment); +} + void SentrySDK::set_tag(const String &p_key, const String &p_value) { ERR_FAIL_COND_MSG(p_key.is_empty(), "Sentry: Can't set tag with an empty key."); internal_sdk->set_tag(p_key, p_value); @@ -247,6 +260,8 @@ 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("add_attachment", "attachment"), &SentrySDK::add_attachment); + ClassDB::bind_method(D_METHOD("remove_attachment", "attachment"), &SentrySDK::remove_attachment); // Hidden API methods -- used in testing. ClassDB::bind_method(D_METHOD("_set_before_send", "callable"), &SentrySDK::set_before_send); diff --git a/src/sentry_sdk.h b/src/sentry_sdk.h index 5bc5fc0b..a8195383 100644 --- a/src/sentry_sdk.h +++ b/src/sentry_sdk.h @@ -4,6 +4,7 @@ #include "runtime_config.h" #include "sentry/internal_sdk.h" #include "sentry/level.h" +#include "sentry_attachment.h" #include "sentry_event.h" #include "sentry_options.h" @@ -70,6 +71,9 @@ class SentrySDK : public Object { Ref create_event() const; String capture_event(const Ref &p_event); + void add_attachment(const Ref &p_attachment); + void remove_attachment(const Ref &p_attachment); + // * Hidden API methods -- used in testing void set_before_send(const Callable &p_callable) { SentryOptions::get_singleton()->set_before_send(p_callable); } From 6ff3797a0182cbd26fc1cddb707388c6f6de8ba6 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 19 Jun 2025 21:53:45 +0200 Subject: [PATCH 02/33] Make attachment properties readonly --- src/sentry_attachment.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index d3d4c55f..872467b7 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -13,8 +13,8 @@ void SentryAttachment::_bind_methods() { ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "content_type"), &SentryAttachment::create_with_path, DEFVAL("")); - BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), set_file_path, get_file_path); - BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), set_content_type, get_content_type); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), get_file_path); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); } Ref SentryAttachment::create_with_path(const String &p_path, const String &p_content_type) { From 017cf876ebeecd8f45a69bb026ca0d4061961f73 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 19 Jun 2025 22:00:06 +0200 Subject: [PATCH 03/33] Return null for empty path --- src/sentry_attachment.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index 872467b7..1ea577e9 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -18,11 +18,14 @@ void SentryAttachment::_bind_methods() { } Ref SentryAttachment::create_with_path(const String &p_path, const String &p_content_type) { + ERR_FAIL_COND_V_MSG(p_path.is_empty(), Ref(), "Sentry: Can't create attachment with an empty file path."); + #ifdef NATIVE_SDK Ref attachment = memnew(NativeAttachment); #else Ref attachment = memnew(DisabledAttachment); #endif + attachment->set_file_path(p_path); attachment->set_content_type(p_content_type); return attachment; From 8929e9a8bba037f9f68395d6c12faab49290f79d Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 19 Jun 2025 22:14:11 +0200 Subject: [PATCH 04/33] Add class reference --- doc_classes/SentryAttachment.xml | 32 ++++++++++++++++++++++++++++++++ doc_classes/SentrySDK.xml | 15 +++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 doc_classes/SentryAttachment.xml diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml new file mode 100644 index 00000000..0e89546d --- /dev/null +++ b/doc_classes/SentryAttachment.xml @@ -0,0 +1,32 @@ + + + + Represents a file attachment that can be sent with Sentry events. + + + SentryAttachment represents a file that can be attached to Sentry events to provide additional context. Attachments are files that are uploaded alongside error reports and can include log files, screenshots, configuration files, or any other relevant data. + Attachments should be created using [method SentryAttachment.create_with_path], then added to Sentry using [method SentrySDK.add_attachment] and can be removed using [method SentrySDK.remove_attachment]. + To learn more about attachments, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url]. + + + + + + + + + + Creates a new [SentryAttachment] with the specified file [param path] and optional [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://" and "res://". The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + [b]Important:[/b] Attachments are read lazily at the time an event is sent to Sentry. + + + + + + The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. + + + The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://" or "res://". + + + diff --git a/doc_classes/SentrySDK.xml b/doc_classes/SentrySDK.xml index de4196c7..bdf4ea6b 100644 --- a/doc_classes/SentrySDK.xml +++ b/doc_classes/SentrySDK.xml @@ -13,6 +13,14 @@ + + + + + Attaches a file to future Sentry events. The [param attachment] should be a [SentryAttachment] object created with [method SentryAttachment.create_with_path]. Supports Godot's virtual file system paths like "user://" and "res://". + To learn more, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url]. + + @@ -64,6 +72,13 @@ Returns whether the SDK is enabled, i.e. whether it is initialized and active. + + + + + Removes a previously added attachment from future Sentry events. The [param attachment] should be a [SentryAttachment] object returned by [method SentrySDK.add_attachment]. + + From 70e4a13887918acc31a0248c5008ba97d8020faf Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Fri, 20 Jun 2025 08:45:53 +0200 Subject: [PATCH 05/33] Update SentryAttachment.xml --- doc_classes/SentryAttachment.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 0e89546d..2faedb1c 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -22,10 +22,10 @@ - + The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. - + The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://" or "res://". From 4508c997ff98acfd668ca3eed4ec75dbf5af89cb Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 11:08:50 +0200 Subject: [PATCH 06/33] Add remove attachments on Android --- .../godotplugin/SentryAndroidGodotPlugin.kt | 18 ++++++++++++++++-- src/sentry/android/android_sdk.cpp | 16 ++++++++++++++++ src/sentry/android/android_sdk.h | 3 +++ src/sentry/android/android_string_names.cpp | 2 ++ src/sentry/android/android_string_names.h | 2 ++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index 204ecf85..3f1a1623 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -19,6 +19,7 @@ import org.godotengine.godot.Godot import org.godotengine.godot.plugin.GodotPlugin import org.godotengine.godot.plugin.UsedByGodot import org.godotengine.godot.variant.Callable +import java.io.File import kotlin.random.Random @@ -123,11 +124,24 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { } @UsedByGodot - fun addGlobalAttachment(path: String) { - val attachment = Attachment(path) + fun addFileAttachment(path: String, filename: String, contentType: String, attachmentType: String) { + val attachment = Attachment( + path, + filename.ifEmpty { File(path).name }, + contentType.ifEmpty { null }, + attachmentType.ifEmpty { null }, + true + ) Sentry.getGlobalScope().addAttachment(attachment) } + @UsedByGodot + fun removeFileAttachment(path: String) { + val globalScope = Sentry.getGlobalScope() + val attachment = globalScope.attachments.find { att -> att.pathname == path } + globalScope.attachments.remove(attachment) + } + @UsedByGodot fun setContext(key: String, value: Dictionary) { Sentry.getGlobalScope().setContexts(key, value) diff --git a/src/sentry/android/android_sdk.cpp b/src/sentry/android/android_sdk.cpp index d36fec98..c2535466 100644 --- a/src/sentry/android/android_sdk.cpp +++ b/src/sentry/android/android_sdk.cpp @@ -3,6 +3,7 @@ #include "android_event.h" #include "android_string_names.h" #include "sentry/util/print.h" +#include "sentry_attachment.h" #include #include @@ -112,6 +113,21 @@ String AndroidSDK::capture_event(const Ref &p_event) { return android_event->get_id(); } +void AndroidSDK::add_attachment(const Ref &p_attachment) { + ERR_FAIL_COND(p_attachment.is_null()); + android_plugin->call(ANDROID_SN(addFileAttachment), + p_attachment->get_file_path(), + String(), + p_attachment->get_content_type(), + String()); +} + +void AndroidSDK::remove_attachment(const Ref &p_attachment) { + ERR_FAIL_COND(p_attachment.is_null()); + android_plugin->call(ANDROID_SN(removeFileAttachment), + p_attachment->get_file_path()); +} + void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) { ERR_FAIL_NULL(android_plugin); diff --git a/src/sentry/android/android_sdk.h b/src/sentry/android/android_sdk.h index 418f7737..ea481f02 100644 --- a/src/sentry/android/android_sdk.h +++ b/src/sentry/android/android_sdk.h @@ -47,6 +47,9 @@ class AndroidSDK : public InternalSDK { virtual Ref create_event() override; virtual String capture_event(const Ref &p_event) override; + virtual void add_attachment(const Ref &p_attachment) override; + virtual void remove_attachment(const Ref &p_attachment) override; + virtual void initialize(const PackedStringArray &p_global_attachments) override; bool has_android_plugin() const { return android_plugin != nullptr; } diff --git a/src/sentry/android/android_string_names.cpp b/src/sentry/android/android_string_names.cpp index 2402b31c..f7b20dad 100644 --- a/src/sentry/android/android_string_names.cpp +++ b/src/sentry/android/android_string_names.cpp @@ -29,6 +29,8 @@ AndroidStringNames::AndroidStringNames() { createEvent = StringName("createEvent"); releaseEvent = StringName("releaseEvent"); captureEvent = StringName("captureEvent"); + addFileAttachment = StringName("addFileAttachment"); + removeFileAttachment = StringName("removeFileAttachment"); // Event methods. eventGetId = StringName("eventGetId"); diff --git a/src/sentry/android/android_string_names.h b/src/sentry/android/android_string_names.h index d8d0f03d..7dabcc6e 100644 --- a/src/sentry/android/android_string_names.h +++ b/src/sentry/android/android_string_names.h @@ -41,6 +41,8 @@ class AndroidStringNames { StringName createEvent; StringName releaseEvent; StringName captureEvent; + StringName addFileAttachment; + StringName removeFileAttachment; // Event methods. StringName eventGetId; From 9568f2b6d9cfcc020c6126232c18681c3b261a9a Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 11:10:50 +0200 Subject: [PATCH 07/33] Update disabled_attachment.h --- src/sentry/disabled_attachment.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sentry/disabled_attachment.h b/src/sentry/disabled_attachment.h index cbd066ad..839eae93 100644 --- a/src/sentry/disabled_attachment.h +++ b/src/sentry/disabled_attachment.h @@ -9,9 +9,6 @@ class DisabledAttachment : public SentryAttachment { protected: static void _bind_methods() {} - -public: - virtual ~DisabledAttachment() override = default; }; #endif // DISABLED_ATTACHMENT_H From 39db26ccf590617f632dbfa519940735e120b8bf Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 11:25:48 +0200 Subject: [PATCH 08/33] Remove attachment specializations --- src/register_types.cpp | 4 ---- src/sentry/disabled_attachment.h | 14 -------------- src/sentry/native/native_attachment.h | 23 ----------------------- src/sentry/native/native_sdk.cpp | 16 +++++----------- src/sentry_attachment.cpp | 27 ++++++++------------------- src/sentry_attachment.h | 15 ++++++++++++++- 6 files changed, 27 insertions(+), 72 deletions(-) delete mode 100644 src/sentry/disabled_attachment.h delete mode 100644 src/sentry/native/native_attachment.h diff --git a/src/register_types.cpp b/src/register_types.cpp index e5eb3a7f..5223e9c0 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -1,7 +1,6 @@ #include "editor/sentry_editor_export_plugin_unix.h" #include "editor/sentry_editor_plugin.h" #include "runtime_config.h" -#include "sentry/disabled_attachment.h" #include "sentry/disabled_event.h" #include "sentry/util/print.h" #include "sentry_attachment.h" @@ -17,7 +16,6 @@ #include #ifdef NATIVE_SDK -#include "sentry/native/native_attachment.h" #include "sentry/native/native_event.h" #endif // NATIVE_SDK @@ -70,12 +68,10 @@ void initialize_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(SentrySDK); GDREGISTER_ABSTRACT_CLASS(SentryAttachment); GDREGISTER_ABSTRACT_CLASS(SentryEvent); - GDREGISTER_INTERNAL_CLASS(DisabledAttachment); GDREGISTER_INTERNAL_CLASS(DisabledEvent); GDREGISTER_INTERNAL_CLASS(SentryLogger); #ifdef NATIVE_SDK - GDREGISTER_INTERNAL_CLASS(NativeAttachment); GDREGISTER_INTERNAL_CLASS(NativeEvent); #endif diff --git a/src/sentry/disabled_attachment.h b/src/sentry/disabled_attachment.h deleted file mode 100644 index 839eae93..00000000 --- a/src/sentry/disabled_attachment.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DISABLED_ATTACHMENT_H -#define DISABLED_ATTACHMENT_H - -#include "sentry_attachment.h" - -// Attachment class that does nothing (for unsupported platforms or disabled SDK). -class DisabledAttachment : public SentryAttachment { - GDCLASS(DisabledAttachment, SentryAttachment); - -protected: - static void _bind_methods() {} -}; - -#endif // DISABLED_ATTACHMENT_H diff --git a/src/sentry/native/native_attachment.h b/src/sentry/native/native_attachment.h deleted file mode 100644 index 9434c8f2..00000000 --- a/src/sentry/native/native_attachment.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef NATIVE_ATTACHMENT_H -#define NATIVE_ATTACHMENT_H - -#include "sentry_attachment.h" - -#include - -// Attachment class that is used with the NativeSDK. -class NativeAttachment : public SentryAttachment { - GDCLASS(NativeAttachment, SentryAttachment); - -private: - sentry_attachment_t *native_attachment = nullptr; - -protected: - static void _bind_methods() {} - -public: - sentry_attachment_t *get_native_attachment() const { return native_attachment; } - void set_native_attachment(sentry_attachment_t *p_native_attachment) { native_attachment = p_native_attachment; } -}; - -#endif // NATIVE_ATTACHMENT_H diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index 5c5225c8..20c7d286 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -4,12 +4,12 @@ #include "sentry/common_defs.h" #include "sentry/contexts.h" #include "sentry/level.h" -#include "sentry/native/native_attachment.h" #include "sentry/native/native_event.h" #include "sentry/native/native_util.h" #include "sentry/util/print.h" #include "sentry/util/screenshot.h" #include "sentry/view_hierarchy.h" +#include "sentry_attachment.h" #include "sentry_options.h" #include @@ -342,11 +342,8 @@ String NativeSDK::capture_event(const Ref &p_event) { void NativeSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); ERR_FAIL_COND_MSG(p_attachment->get_file_path().is_empty(), "Sentry: Can't add attachment with empty path."); - - NativeAttachment *native_attachment_wrapper = Object::cast_to(p_attachment.ptr()); - ERR_FAIL_NULL(native_attachment_wrapper); // Sanity check - this should never happen. - ERR_FAIL_NULL(ProjectSettings::get_singleton()); + String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_file_path()); sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8().get_data()); if (!native_attachment) { @@ -357,7 +354,7 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8().get_data()); } - native_attachment_wrapper->set_native_attachment(native_attachment); + p_attachment->set_native_attachment(native_attachment); sentry::util::print_debug(vformat("attached file: %s", absolute_path)); } @@ -365,13 +362,10 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { void NativeSDK::remove_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't remove null attachment."); - NativeAttachment *native_attachment_wrapper = Object::cast_to(p_attachment.ptr()); - ERR_FAIL_NULL(native_attachment_wrapper); // Sanity check - this should never. - - sentry_attachment_t *native_attachment = native_attachment_wrapper->get_native_attachment(); + sentry_attachment_t *native_attachment = p_attachment->get_native_attachment(); if (native_attachment) { sentry_remove_attachment(native_attachment); - native_attachment_wrapper->set_native_attachment(nullptr); + p_attachment->set_native_attachment(nullptr); sentry::util::print_debug(vformat("removed attachment: %s", p_attachment->get_file_path())); } else { sentry::util::print_warning(vformat("attempted to remove attachment that was not added: %s", p_attachment->get_file_path())); diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index 1ea577e9..af1765f1 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -4,29 +4,18 @@ #include -#ifdef NATIVE_SDK -#include "sentry/native/native_attachment.h" -#else -#include "sentry/disabled_attachment.h" -#endif - -void SentryAttachment::_bind_methods() { - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "content_type"), &SentryAttachment::create_with_path, DEFVAL("")); - - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), get_file_path); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); -} - Ref SentryAttachment::create_with_path(const String &p_path, const String &p_content_type) { ERR_FAIL_COND_V_MSG(p_path.is_empty(), Ref(), "Sentry: Can't create attachment with an empty file path."); -#ifdef NATIVE_SDK - Ref attachment = memnew(NativeAttachment); -#else - Ref attachment = memnew(DisabledAttachment); -#endif - + Ref attachment = memnew(SentryAttachment); attachment->set_file_path(p_path); attachment->set_content_type(p_content_type); return attachment; } + +void SentryAttachment::_bind_methods() { + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "content_type"), &SentryAttachment::create_with_path, DEFVAL("")); + + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), get_file_path); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); +} diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index 70a9eec7..cbd7f812 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -4,6 +4,10 @@ #include #include +#ifdef NATIVE_SDK +#include +#endif + using namespace godot; // Base class for attachment objects in the public API. @@ -14,17 +18,26 @@ class SentryAttachment : public RefCounted { String file_path; String content_type; +#ifdef NATIVE_SDK + sentry_attachment_t *native_attachment = nullptr; +#endif + protected: static void _bind_methods(); public: + static Ref create_with_path(const String &p_path, const String &p_content_type = ""); + void set_file_path(const String &p_path) { file_path = p_path; } String get_file_path() const { return file_path; } void set_content_type(const String &p_content_type) { content_type = p_content_type; } String get_content_type() const { return content_type; } - static Ref create_with_path(const String &p_path, const String &p_content_type = ""); +#ifdef NATIVE_SDK + sentry_attachment_t *get_native_attachment() const { return native_attachment; } + void set_native_attachment(sentry_attachment_t *p_native_attachment) { native_attachment = p_native_attachment; } +#endif virtual ~SentryAttachment() = default; }; From 568cd503d6830ab74f4134e0640932d1af372c1f Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 11:44:36 +0200 Subject: [PATCH 09/33] Add attachment.filename and rename path property --- modules/sentry-native | 2 +- src/sentry/android/android_sdk.cpp | 6 +++--- src/sentry/native/native_sdk.cpp | 14 +++++++++----- src/sentry_attachment.cpp | 10 ++++++---- src/sentry_attachment.h | 12 ++++++++---- src/sentry_sdk.cpp | 2 +- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/modules/sentry-native b/modules/sentry-native index 99e59820..3f7bbd61 160000 --- a/modules/sentry-native +++ b/modules/sentry-native @@ -1 +1 @@ -Subproject commit 99e598206296b63301919b9bc20e36c39adb51a1 +Subproject commit 3f7bbd6193bda6814a7258da31971f21bf61da26 diff --git a/src/sentry/android/android_sdk.cpp b/src/sentry/android/android_sdk.cpp index c2535466..9d85a4dc 100644 --- a/src/sentry/android/android_sdk.cpp +++ b/src/sentry/android/android_sdk.cpp @@ -116,8 +116,8 @@ String AndroidSDK::capture_event(const Ref &p_event) { void AndroidSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND(p_attachment.is_null()); android_plugin->call(ANDROID_SN(addFileAttachment), - p_attachment->get_file_path(), - String(), + p_attachment->get_path(), + p_attachment->get_filename(), p_attachment->get_content_type(), String()); } @@ -125,7 +125,7 @@ void AndroidSDK::add_attachment(const Ref &p_attachment) { void AndroidSDK::remove_attachment(const Ref &p_attachment) { ERR_FAIL_COND(p_attachment.is_null()); android_plugin->call(ANDROID_SN(removeFileAttachment), - p_attachment->get_file_path()); + p_attachment->get_path()); } void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) { diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index 20c7d286..a68b5d23 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -341,17 +341,21 @@ String NativeSDK::capture_event(const Ref &p_event) { void NativeSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); - ERR_FAIL_COND_MSG(p_attachment->get_file_path().is_empty(), "Sentry: Can't add attachment with empty path."); + ERR_FAIL_COND_MSG(p_attachment->get_path().is_empty(), "Sentry: Can't add attachment with empty path."); ERR_FAIL_NULL(ProjectSettings::get_singleton()); - String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_file_path()); + String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8().get_data()); if (!native_attachment) { ERR_FAIL_MSG(vformat("Sentry: Failed to attach file: %s", absolute_path)); } if (!p_attachment->get_content_type().is_empty()) { - sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8().get_data()); + sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8()); + } + + if (!p_attachment->get_filename().is_empty()) { + sentry_attachment_set_filename(native_attachment, p_attachment->get_filename().utf8()); } p_attachment->set_native_attachment(native_attachment); @@ -366,9 +370,9 @@ void NativeSDK::remove_attachment(const Ref &p_attachment) { if (native_attachment) { sentry_remove_attachment(native_attachment); p_attachment->set_native_attachment(nullptr); - sentry::util::print_debug(vformat("removed attachment: %s", p_attachment->get_file_path())); + sentry::util::print_debug(vformat("removed attachment: %s", p_attachment->get_path())); } else { - sentry::util::print_warning(vformat("attempted to remove attachment that was not added: %s", p_attachment->get_file_path())); + sentry::util::print_warning(vformat("attempted to remove attachment that was not added: %s", p_attachment->get_path())); } } diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index af1765f1..7e2d99a7 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -4,18 +4,20 @@ #include -Ref SentryAttachment::create_with_path(const String &p_path, const String &p_content_type) { +Ref SentryAttachment::create_with_path(const String &p_path, const String &p_filename, const String &p_content_type) { ERR_FAIL_COND_V_MSG(p_path.is_empty(), Ref(), "Sentry: Can't create attachment with an empty file path."); Ref attachment = memnew(SentryAttachment); - attachment->set_file_path(p_path); + attachment->set_path(p_path); + attachment->set_filename(p_filename); attachment->set_content_type(p_content_type); return attachment; } void SentryAttachment::_bind_methods() { - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "content_type"), &SentryAttachment::create_with_path, DEFVAL("")); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "filename", "content_type"), &SentryAttachment::create_with_path, DEFVAL(""), DEFVAL("")); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "file_path"), get_file_path); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "path"), get_path); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "filename"), get_filename); BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); } diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index cbd7f812..f96957b9 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -15,7 +15,8 @@ class SentryAttachment : public RefCounted { GDCLASS(SentryAttachment, RefCounted); private: - String file_path; + String path; + String filename; String content_type; #ifdef NATIVE_SDK @@ -26,10 +27,13 @@ class SentryAttachment : public RefCounted { static void _bind_methods(); public: - static Ref create_with_path(const String &p_path, const String &p_content_type = ""); + static Ref create_with_path(const String &p_path, const String &p_filename = "", const String &p_content_type = ""); - void set_file_path(const String &p_path) { file_path = p_path; } - String get_file_path() const { return file_path; } + void set_path(const String &p_path) { path = p_path; } + String get_path() const { return path; } + + void set_filename(const String &p_filename) { filename = p_filename; } + String get_filename() const { return filename; } void set_content_type(const String &p_content_type) { content_type = p_content_type; } String get_content_type() const { return content_type; } diff --git a/src/sentry_sdk.cpp b/src/sentry_sdk.cpp index 3e7c0144..c8c2f429 100644 --- a/src/sentry_sdk.cpp +++ b/src/sentry_sdk.cpp @@ -80,7 +80,7 @@ String SentrySDK::capture_event(const Ref &p_event) { void SentrySDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); - ERR_FAIL_COND_MSG(p_attachment->get_file_path().is_empty(), "Sentry: Can't add attachment with empty path."); + ERR_FAIL_COND_MSG(p_attachment->get_path().is_empty(), "Sentry: Can't add attachment with empty path."); internal_sdk->add_attachment(p_attachment); } From 2207e0249bebef36072cb99b8b668d73634a94b7 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 11:59:45 +0200 Subject: [PATCH 10/33] Clarify comment --- src/sentry_attachment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index f96957b9..153e605e 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -10,7 +10,7 @@ using namespace godot; -// Base class for attachment objects in the public API. +// Represents attachments in the public API. class SentryAttachment : public RefCounted { GDCLASS(SentryAttachment, RefCounted); From ac340a438c8fb297f7fdaef68435e90d437101e3 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 12:12:48 +0200 Subject: [PATCH 11/33] Update SentryAttachment.xml --- doc_classes/SentryAttachment.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 2faedb1c..2ef51bd6 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -14,18 +14,22 @@ - + + - Creates a new [SentryAttachment] with the specified file [param path] and optional [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://" and "res://". The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://" and "res://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). [b]Important:[/b] Attachments are read lazily at the time an event is sent to Sentry. - + The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. - + + The filename of the attachment. This is the name that will be displayed in Sentry. If not provided, the filename will be extracted from the [member path]. + + The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://" or "res://". From c5172a5803f1297e85553e771857c45ff2294c61 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 12:57:26 +0200 Subject: [PATCH 12/33] Remove setters --- src/sentry_attachment.cpp | 6 +++--- src/sentry_attachment.h | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index 7e2d99a7..b22ebe78 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -8,9 +8,9 @@ Ref SentryAttachment::create_with_path(const String &p_path, c ERR_FAIL_COND_V_MSG(p_path.is_empty(), Ref(), "Sentry: Can't create attachment with an empty file path."); Ref attachment = memnew(SentryAttachment); - attachment->set_path(p_path); - attachment->set_filename(p_filename); - attachment->set_content_type(p_content_type); + attachment->path = p_path; + attachment->filename = p_filename; + attachment->content_type = p_content_type; return attachment; } diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index 153e605e..acd865b6 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -29,13 +29,8 @@ class SentryAttachment : public RefCounted { public: static Ref create_with_path(const String &p_path, const String &p_filename = "", const String &p_content_type = ""); - void set_path(const String &p_path) { path = p_path; } String get_path() const { return path; } - - void set_filename(const String &p_filename) { filename = p_filename; } String get_filename() const { return filename; } - - void set_content_type(const String &p_content_type) { content_type = p_content_type; } String get_content_type() const { return content_type; } #ifdef NATIVE_SDK From 6c4e679ba7a4e720cc9b26ffa4f4e464284bc919 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 13:34:41 +0200 Subject: [PATCH 13/33] Dont add attachments to transactions as per recommendation --- .../main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index 3f1a1623..f1f0a0ff 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -130,7 +130,7 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { filename.ifEmpty { File(path).name }, contentType.ifEmpty { null }, attachmentType.ifEmpty { null }, - true + false ) Sentry.getGlobalScope().addAttachment(attachment) } From fe5b491c219930c136c2bf51ed6ed6020f702ba8 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 13:52:06 +0200 Subject: [PATCH 14/33] Add simple test --- project/test/suites/test_attachment.gd | 13 +++++++++++++ project/test/suites/test_attachment.gd.uid | 1 + 2 files changed, 14 insertions(+) create mode 100644 project/test/suites/test_attachment.gd create mode 100644 project/test/suites/test_attachment.gd.uid diff --git a/project/test/suites/test_attachment.gd b/project/test/suites/test_attachment.gd new file mode 100644 index 00000000..9b3d0a1c --- /dev/null +++ b/project/test/suites/test_attachment.gd @@ -0,0 +1,13 @@ +extends GdUnitTestSuite +## Basic tests for the SentryAttachment class. + + +func test_create_with_path() -> void: + var attachment := SentryAttachment.create_with_path( + "res://example_configuration.gd", + "config.gd", + "text/x-gdscript" + ) + assert_str(attachment.path).is_equal("res://example_configuration.gd") + assert_str(attachment.filename).is_equal("config.gd") + assert_str(attachment.content_type).is_equal("text/x-gdscript") diff --git a/project/test/suites/test_attachment.gd.uid b/project/test/suites/test_attachment.gd.uid new file mode 100644 index 00000000..960d7b25 --- /dev/null +++ b/project/test/suites/test_attachment.gd.uid @@ -0,0 +1 @@ +uid://b10m6784fkgyb From b526f8d8fe46d6e1640bc5b901e63f8a7b905360 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 13:52:22 +0200 Subject: [PATCH 15/33] Redundant call --- src/sentry/native/native_sdk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index a68b5d23..a7494c7c 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -345,7 +345,7 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_NULL(ProjectSettings::get_singleton()); String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); - sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8().get_data()); + sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8()); if (!native_attachment) { ERR_FAIL_MSG(vformat("Sentry: Failed to attach file: %s", absolute_path)); } From d41169b5d4f2b2f5a95eb39eee3c687e6d69cbf3 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 16:21:14 +0200 Subject: [PATCH 16/33] Create/add attachments from bytes (native) --- src/sentry/native/native_sdk.cpp | 38 ++++++++++++++++++++++---------- src/sentry_attachment.cpp | 12 ++++++++++ src/sentry_attachment.h | 4 ++++ src/sentry_sdk.cpp | 2 -- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index a7494c7c..dacbae9a 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -341,26 +341,40 @@ String NativeSDK::capture_event(const Ref &p_event) { void NativeSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); - ERR_FAIL_COND_MSG(p_attachment->get_path().is_empty(), "Sentry: Can't add attachment with empty path."); ERR_FAIL_NULL(ProjectSettings::get_singleton()); - String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); - sentry_attachment_t *native_attachment = sentry_attach_file(absolute_path.utf8()); - if (!native_attachment) { - ERR_FAIL_MSG(vformat("Sentry: Failed to attach file: %s", absolute_path)); - } + sentry_attachment_t *native_attachment = nullptr; - if (!p_attachment->get_content_type().is_empty()) { - sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8()); - } + if (!p_attachment->get_path().is_empty()) { + String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); + native_attachment = sentry_attach_file(absolute_path.utf8()); + + ERR_FAIL_NULL_MSG(native_attachment, vformat("Sentry: Failed to attach file: %s", absolute_path)); + + if (!p_attachment->get_filename().is_empty()) { + sentry_attachment_set_filename(native_attachment, p_attachment->get_filename().utf8()); + } - if (!p_attachment->get_filename().is_empty()) { - sentry_attachment_set_filename(native_attachment, p_attachment->get_filename().utf8()); + sentry::util::print_debug(vformat("attached file: %s", absolute_path)); + } else { + PackedByteArray bytes = p_attachment->get_bytes(); + ERR_FAIL_COND_MSG(bytes.is_empty(), "Sentry: Can't add attachment with empty bytes and no file path."); + + native_attachment = sentry_attach_bytes( + reinterpret_cast(bytes.ptr()), + bytes.size(), + p_attachment->get_filename().utf8()); + + ERR_FAIL_NULL_MSG(native_attachment, vformat("Sentry: Failed to attach bytes with filename: %s", p_attachment->get_filename())); + + sentry::util::print_debug(vformat("attached bytes with filename: %s", p_attachment->get_filename())); } p_attachment->set_native_attachment(native_attachment); - sentry::util::print_debug(vformat("attached file: %s", absolute_path)); + if (!p_attachment->get_content_type().is_empty()) { + sentry_attachment_set_content_type(native_attachment, p_attachment->get_content_type().utf8()); + } } void NativeSDK::remove_attachment(const Ref &p_attachment) { diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index b22ebe78..caad102a 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -14,9 +14,21 @@ Ref SentryAttachment::create_with_path(const String &p_path, c return attachment; } +Ref SentryAttachment::create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename, const String &p_content_type) { + ERR_FAIL_COND_V_MSG(p_filename.is_empty(), Ref(), "Sentry: Can't create attachment with an empty filename."); + + Ref attachment = memnew(SentryAttachment); + attachment->bytes = p_bytes; + attachment->filename = p_filename; + attachment->content_type = p_content_type; + return attachment; +} + void SentryAttachment::_bind_methods() { ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "filename", "content_type"), &SentryAttachment::create_with_path, DEFVAL(""), DEFVAL("")); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_bytes", "bytes", "filename", "content_type"), &SentryAttachment::create_with_bytes, DEFVAL("")); + BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), get_bytes); BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "path"), get_path); BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "filename"), get_filename); BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index acd865b6..aa7b55e6 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -2,6 +2,7 @@ #define SENTRY_ATTACHMENT_H #include +#include #include #ifdef NATIVE_SDK @@ -15,6 +16,7 @@ class SentryAttachment : public RefCounted { GDCLASS(SentryAttachment, RefCounted); private: + PackedByteArray bytes; String path; String filename; String content_type; @@ -28,7 +30,9 @@ class SentryAttachment : public RefCounted { public: static Ref create_with_path(const String &p_path, const String &p_filename = "", const String &p_content_type = ""); + static Ref create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename, const String &p_content_type = ""); + PackedByteArray get_bytes() const { return bytes; } String get_path() const { return path; } String get_filename() const { return filename; } String get_content_type() const { return content_type; } diff --git a/src/sentry_sdk.cpp b/src/sentry_sdk.cpp index c8c2f429..38079837 100644 --- a/src/sentry_sdk.cpp +++ b/src/sentry_sdk.cpp @@ -80,8 +80,6 @@ String SentrySDK::capture_event(const Ref &p_event) { void SentrySDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't add null attachment."); - ERR_FAIL_COND_MSG(p_attachment->get_path().is_empty(), "Sentry: Can't add attachment with empty path."); - internal_sdk->add_attachment(p_attachment); } From a174012c966059fff3f8bb6acff1b394357d591e Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 16:21:31 +0200 Subject: [PATCH 17/33] Update test_attachment.gd --- project/test/suites/test_attachment.gd | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/project/test/suites/test_attachment.gd b/project/test/suites/test_attachment.gd index 9b3d0a1c..47ef56ab 100644 --- a/project/test/suites/test_attachment.gd +++ b/project/test/suites/test_attachment.gd @@ -8,6 +8,26 @@ func test_create_with_path() -> void: "config.gd", "text/x-gdscript" ) + assert_array(attachment.bytes).is_empty() assert_str(attachment.path).is_equal("res://example_configuration.gd") assert_str(attachment.filename).is_equal("config.gd") assert_str(attachment.content_type).is_equal("text/x-gdscript") + + +func test_create_with_bytes() -> void: + var contents := """ + Hello, world! + """ + var bytes: PackedByteArray = contents.to_utf8_buffer() + + var attachment := SentryAttachment.create_with_bytes( + bytes, "hello.txt", "text/plain") + + assert_array(attachment.bytes).is_not_empty() + assert_str(attachment.path).is_empty() + assert_str(attachment.filename).is_equal("hello.txt") + assert_str(attachment.content_type).is_equal("text/plain") + + assert_int(attachment.bytes.size()).is_equal(bytes.size()) + for i in attachment.bytes.size(): + assert_int(attachment.bytes[i]).is_equal(bytes[i]) From 7c8857c2f1da810876f6dd1513a1ef1fcbe3b606 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 17:00:32 +0200 Subject: [PATCH 18/33] Create/add attachments android --- .../godotplugin/SentryAndroidGodotPlugin.kt | 20 +++++++++++ src/sentry/android/android_sdk.cpp | 33 +++++++++++++++---- src/sentry/android/android_string_names.cpp | 2 ++ src/sentry/android/android_string_names.h | 2 ++ 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index f1f0a0ff..07dcca39 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -142,6 +142,26 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { globalScope.attachments.remove(attachment) } + @UsedByGodot + fun addBytesAttachment(bytes: ByteArray, filename: String, contentType: String, attachmentType: String) { + val globalScope = Sentry.getGlobalScope() + val attachment = Attachment( + bytes, + filename, + contentType.ifEmpty { null }, + attachmentType.ifEmpty { null }, + false + ) + Sentry.getGlobalScope().addAttachment(attachment) + } + + @UsedByGodot + fun removeBytesAttachment(filename: String) { + val globalScope = Sentry.getGlobalScope() + val attachment = globalScope.attachments.find { att -> att.filename == filename } + globalScope.attachments.remove(attachment) + } + @UsedByGodot fun setContext(key: String, value: Dictionary) { Sentry.getGlobalScope().setContexts(key, value) diff --git a/src/sentry/android/android_sdk.cpp b/src/sentry/android/android_sdk.cpp index 9d85a4dc..28024274 100644 --- a/src/sentry/android/android_sdk.cpp +++ b/src/sentry/android/android_sdk.cpp @@ -6,6 +6,7 @@ #include "sentry_attachment.h" #include +#include #include using namespace godot; @@ -115,17 +116,35 @@ String AndroidSDK::capture_event(const Ref &p_event) { void AndroidSDK::add_attachment(const Ref &p_attachment) { ERR_FAIL_COND(p_attachment.is_null()); - android_plugin->call(ANDROID_SN(addFileAttachment), - p_attachment->get_path(), - p_attachment->get_filename(), - p_attachment->get_content_type(), - String()); + + if (p_attachment->get_path().is_empty()) { + sentry::util::print_debug("attaching bytes with filename: ", p_attachment->get_filename()); + android_plugin->call(ANDROID_SN(addBytesAttachment), + p_attachment->get_bytes(), + p_attachment->get_filename(), + p_attachment->get_content_type(), + String()); + } else { + String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); + sentry::util::print_debug("attaching file: ", absolute_path); + android_plugin->call(ANDROID_SN(addFileAttachment), + absolute_path, + p_attachment->get_filename(), + p_attachment->get_content_type(), + String()); + } } void AndroidSDK::remove_attachment(const Ref &p_attachment) { ERR_FAIL_COND(p_attachment.is_null()); - android_plugin->call(ANDROID_SN(removeFileAttachment), - p_attachment->get_path()); + + if (p_attachment->get_path().is_empty()) { + android_plugin->call(ANDROID_SN(removeBytesAttachment), + p_attachment->get_filename()); + } else { + android_plugin->call(ANDROID_SN(removeFileAttachment), + p_attachment->get_path()); + } } void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) { diff --git a/src/sentry/android/android_string_names.cpp b/src/sentry/android/android_string_names.cpp index f7b20dad..389e4870 100644 --- a/src/sentry/android/android_string_names.cpp +++ b/src/sentry/android/android_string_names.cpp @@ -31,6 +31,8 @@ AndroidStringNames::AndroidStringNames() { captureEvent = StringName("captureEvent"); addFileAttachment = StringName("addFileAttachment"); removeFileAttachment = StringName("removeFileAttachment"); + addBytesAttachment = StringName("addBytesAttachment"); + removeBytesAttachment = StringName("removeBytesAttachment"); // Event methods. eventGetId = StringName("eventGetId"); diff --git a/src/sentry/android/android_string_names.h b/src/sentry/android/android_string_names.h index 7dabcc6e..9098afdb 100644 --- a/src/sentry/android/android_string_names.h +++ b/src/sentry/android/android_string_names.h @@ -43,6 +43,8 @@ class AndroidStringNames { StringName captureEvent; StringName addFileAttachment; StringName removeFileAttachment; + StringName addBytesAttachment; + StringName removeBytesAttachment; // Event methods. StringName eventGetId; From 09c11a68ac804021c883907677e2b5140ca91830 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 17:01:21 +0200 Subject: [PATCH 19/33] Update native_sdk.cpp --- src/sentry/native/native_sdk.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index dacbae9a..b6c4d203 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -347,6 +347,8 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { if (!p_attachment->get_path().is_empty()) { String absolute_path = ProjectSettings::get_singleton()->globalize_path(p_attachment->get_path()); + sentry::util::print_debug(vformat("attaching file: %s", absolute_path)); + native_attachment = sentry_attach_file(absolute_path.utf8()); ERR_FAIL_NULL_MSG(native_attachment, vformat("Sentry: Failed to attach file: %s", absolute_path)); @@ -355,19 +357,18 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { sentry_attachment_set_filename(native_attachment, p_attachment->get_filename().utf8()); } - sentry::util::print_debug(vformat("attached file: %s", absolute_path)); } else { PackedByteArray bytes = p_attachment->get_bytes(); ERR_FAIL_COND_MSG(bytes.is_empty(), "Sentry: Can't add attachment with empty bytes and no file path."); + sentry::util::print_debug(vformat("attaching bytes with filename: %s", p_attachment->get_filename())); + native_attachment = sentry_attach_bytes( reinterpret_cast(bytes.ptr()), bytes.size(), p_attachment->get_filename().utf8()); ERR_FAIL_NULL_MSG(native_attachment, vformat("Sentry: Failed to attach bytes with filename: %s", p_attachment->get_filename())); - - sentry::util::print_debug(vformat("attached bytes with filename: %s", p_attachment->get_filename())); } p_attachment->set_native_attachment(native_attachment); From 870714323d991b08e47bf36f6a107c5b5235244c Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 17:17:46 +0200 Subject: [PATCH 20/33] Add controls to create an attachment in the demo project --- project/views/enrich_events.gd | 9 +++++++++ project/views/enrich_events.tscn | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/project/views/enrich_events.gd b/project/views/enrich_events.gd index b08bcc2c..b93c469c 100644 --- a/project/views/enrich_events.gd +++ b/project/views/enrich_events.gd @@ -46,3 +46,12 @@ func _on_set_context_pressed() -> void: DemoOutput.print_err("Failed set context: Dictionary is expected, but found: " + type_string(typeof(result))) else: DemoOutput.print_err("Failed to parse expression: " + expr.get_error_text()) + + +func _on_attach_button_pressed() -> void: + var content: String = %AttachmentContent.text + var bytes: PackedByteArray = content.to_utf8_buffer() + var attachment := SentryAttachment.create_with_bytes( + bytes, "hello.txt", "text/plain") + SentrySDK.add_attachment(attachment) + DemoOutput.print_info("Attachment added.") diff --git a/project/views/enrich_events.tscn b/project/views/enrich_events.tscn index 9e6a542e..4ca7c8e3 100644 --- a/project/views/enrich_events.tscn +++ b/project/views/enrich_events.tscn @@ -63,6 +63,24 @@ unique_name_in_owner = true layout_mode = 2 text = "Add Tag" +[node name="Attachment" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="Attachment"] +layout_mode = 2 +text = "Attach:" + +[node name="AttachmentContent" type="LineEdit" parent="Attachment"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +text = "Hello, World!" +placeholder_text = "Content" + +[node name="AttachButton" type="Button" parent="Attachment"] +layout_mode = 2 +text = "Attach hello.txt" + [node name="Context" type="VBoxContainer" parent="."] layout_mode = 2 @@ -97,4 +115,5 @@ text = "Add context" [connection signal="pressed" from="Breadcrumb/AddBreadcrumbButton" to="." method="_on_add_breadcrumb_button_pressed"] [connection signal="pressed" from="Tags/AddTagButton" to="." method="_on_add_tag_button_pressed"] +[connection signal="pressed" from="Attachment/AttachButton" to="." method="_on_attach_button_pressed"] [connection signal="pressed" from="Context/SetContext" to="." method="_on_set_context_pressed"] From 9000027618973706ef12830d75f58b101a9b92dc Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 17:33:10 +0200 Subject: [PATCH 21/33] Update SentryAttachment.xml --- doc_classes/SentryAttachment.xml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 2ef51bd6..112fc793 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -5,12 +5,22 @@ SentryAttachment represents a file that can be attached to Sentry events to provide additional context. Attachments are files that are uploaded alongside error reports and can include log files, screenshots, configuration files, or any other relevant data. - Attachments should be created using [method SentryAttachment.create_with_path], then added to Sentry using [method SentrySDK.add_attachment] and can be removed using [method SentrySDK.remove_attachment]. + Attachments can be created using [method SentryAttachment.create_with_path] for existing files on disk or [method SentryAttachment.create_with_bytes] for data already in memory. Once created, they can be added to future events using [method SentrySDK.add_attachment] and removed using [method SentrySDK.remove_attachment]. To learn more about attachments, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url]. + + + + + + + Creates a new [SentryAttachment] with the specified [param bytes] data and [param filename]. The [param bytes] parameter contains the raw file data to be attached. The [param filename] parameter specifies the display name for the attachment in Sentry. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + This method is useful when you have file data already loaded in memory or when creating attachments from generated content rather than existing files on disk. + + @@ -23,6 +33,9 @@ + + Contains the raw byte data of the attachment. + The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. From 43f7b354dbbd1e810a4883266d8783d68834f5fb Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 20:24:40 +0200 Subject: [PATCH 22/33] Fix global attachments on Android --- src/sentry/android/android_sdk.cpp | 8 +++++++- src/sentry/android/android_string_names.cpp | 1 - src/sentry/android/android_string_names.h | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sentry/android/android_sdk.cpp b/src/sentry/android/android_sdk.cpp index 28024274..49141b4e 100644 --- a/src/sentry/android/android_sdk.cpp +++ b/src/sentry/android/android_sdk.cpp @@ -2,6 +2,7 @@ #include "android_event.h" #include "android_string_names.h" +#include "sentry/common_defs.h" #include "sentry/util/print.h" #include "sentry_attachment.h" @@ -153,7 +154,12 @@ void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) { sentry::util::print_debug("Initializing Sentry Android SDK"); for (const String &path : p_global_attachments) { - android_plugin->call(ANDROID_SN(addGlobalAttachment), path); + bool is_view_hierarchy = path.ends_with(SENTRY_VIEW_HIERARCHY_FN); + android_plugin->call(ANDROID_SN(addFileAttachment), + path, + String(), // filename + is_view_hierarchy ? "application/json" : String(), + is_view_hierarchy ? "event.view_hierarchy" : String()); } android_plugin->call("initialize", diff --git a/src/sentry/android/android_string_names.cpp b/src/sentry/android/android_string_names.cpp index 389e4870..9e712706 100644 --- a/src/sentry/android/android_string_names.cpp +++ b/src/sentry/android/android_string_names.cpp @@ -15,7 +15,6 @@ void AndroidStringNames::destroy_singleton() { AndroidStringNames::AndroidStringNames() { // API methods. - addGlobalAttachment = StringName("addGlobalAttachment"); setContext = StringName("setContext"); removeContext = StringName("removeContext"); setTag = StringName("setTag"); diff --git a/src/sentry/android/android_string_names.h b/src/sentry/android/android_string_names.h index 9098afdb..37f94c7d 100644 --- a/src/sentry/android/android_string_names.h +++ b/src/sentry/android/android_string_names.h @@ -27,7 +27,6 @@ class AndroidStringNames { _FORCE_INLINE_ static AndroidStringNames *get_singleton() { return singleton; } // API methods. - StringName addGlobalAttachment; StringName setContext; StringName removeContext; StringName setTag; From 5710a6e1e566f0c67a927a0accdb3ddb09a701f1 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 20:55:17 +0200 Subject: [PATCH 23/33] Update doc --- doc_classes/SentryAttachment.xml | 4 ++-- doc_classes/SentrySDK.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 112fc793..a25d7c96 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -27,7 +27,7 @@ - Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://" and "res://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). [b]Important:[/b] Attachments are read lazily at the time an event is sent to Sentry. @@ -43,7 +43,7 @@ The filename of the attachment. This is the name that will be displayed in Sentry. If not provided, the filename will be extracted from the [member path]. - The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://" or "res://". + The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://". diff --git a/doc_classes/SentrySDK.xml b/doc_classes/SentrySDK.xml index bdf4ea6b..cfa081a8 100644 --- a/doc_classes/SentrySDK.xml +++ b/doc_classes/SentrySDK.xml @@ -17,7 +17,7 @@ - Attaches a file to future Sentry events. The [param attachment] should be a [SentryAttachment] object created with [method SentryAttachment.create_with_path]. Supports Godot's virtual file system paths like "user://" and "res://". + Attaches a file to future Sentry events. The [param attachment] should be a [SentryAttachment] object created with [method SentryAttachment.create_with_path] or [method SentryAttachment.create_with_bytes]. Supports Godot's virtual file system paths like "user://". To learn more, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url]. From d5d40e5524a26762726cdb21364df6fab879ef0a Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 21:03:34 +0200 Subject: [PATCH 24/33] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f2b118a..a9f488be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Initial Android support ([#169](https://github.com/getsentry/sentry-godot/pull/169)) - Refine demo for mobile screens ([#196](https://github.com/getsentry/sentry-godot/pull/196)) +- Add user attachments support ([#205](https://github.com/getsentry/sentry-godot/pull/205)) ### Dependencies From fab96b6da0ed7239e7be974e10b231356068163c Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 22:17:43 +0200 Subject: [PATCH 25/33] Fix unused variable in bridge layer --- .../main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index 07dcca39..3f1ff01c 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -144,7 +144,6 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { @UsedByGodot fun addBytesAttachment(bytes: ByteArray, filename: String, contentType: String, attachmentType: String) { - val globalScope = Sentry.getGlobalScope() val attachment = Attachment( bytes, filename, From 3a0243116476b598b6fd9e53865105f194005bcc Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 22:22:37 +0200 Subject: [PATCH 26/33] Remove virtual destructor since SentryAttachment is no longer a base class --- src/sentry_attachment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index aa7b55e6..399947ac 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -42,7 +42,7 @@ class SentryAttachment : public RefCounted { void set_native_attachment(sentry_attachment_t *p_native_attachment) { native_attachment = p_native_attachment; } #endif - virtual ~SentryAttachment() = default; + ~SentryAttachment() = default; }; #endif // SENTRY_ATTACHMENT_H From 72843c5a35d1e97954fcee02ba7eaa837e206c40 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 25 Jun 2025 22:28:51 +0200 Subject: [PATCH 27/33] Improve null safety in the bridge layer while handling attachments --- .../java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index 3f1ff01c..c838ea0f 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -139,7 +139,7 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { fun removeFileAttachment(path: String) { val globalScope = Sentry.getGlobalScope() val attachment = globalScope.attachments.find { att -> att.pathname == path } - globalScope.attachments.remove(attachment) + attachment?.let { globalScope.attachments.remove(attachment) } } @UsedByGodot @@ -158,7 +158,7 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { fun removeBytesAttachment(filename: String) { val globalScope = Sentry.getGlobalScope() val attachment = globalScope.attachments.find { att -> att.filename == filename } - globalScope.attachments.remove(attachment) + attachment?.let { globalScope.attachments.remove(attachment) } } @UsedByGodot From 58da2f687676593316d5bc585021f2f80f50749e Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 26 Jun 2025 11:11:01 +0200 Subject: [PATCH 28/33] Add corrections to SentrySDK.xml --- doc_classes/SentrySDK.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc_classes/SentrySDK.xml b/doc_classes/SentrySDK.xml index cfa081a8..6a3c379c 100644 --- a/doc_classes/SentrySDK.xml +++ b/doc_classes/SentrySDK.xml @@ -76,7 +76,7 @@ - Removes a previously added attachment from future Sentry events. The [param attachment] should be a [SentryAttachment] object returned by [method SentrySDK.add_attachment]. + Removes a previously added attachment from future Sentry events. The [param attachment] should be a [SentryAttachment] object added with [method SentrySDK.add_attachment]. From eea30981c01db3c8948e7048b883500c0500fde2 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 26 Jun 2025 11:37:12 +0200 Subject: [PATCH 29/33] Add setters and simplify creator methods --- doc_classes/SentryAttachment.xml | 16 +++++++--------- project/test/suites/test_attachment.gd | 19 +++++++++---------- project/views/enrich_events.gd | 4 ++-- src/sentry_attachment.cpp | 19 ++++++++----------- src/sentry_attachment.h | 11 +++++++++-- 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index a25d7c96..bee9b4c6 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -14,8 +14,7 @@ - - + Creates a new [SentryAttachment] with the specified [param bytes] data and [param filename]. The [param bytes] parameter contains the raw file data to be attached. The [param filename] parameter specifies the display name for the attachment in Sentry. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). This method is useful when you have file data already loaded in memory or when creating attachments from generated content rather than existing files on disk. @@ -23,26 +22,25 @@ - - - + Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + [b]Note:[/b] Modifying attachment properties after the attachment has been added with [method SentrySDK.add_attachment] will have no effect. To apply property changes, you need to re-add the attachment. [b]Important:[/b] Attachments are read lazily at the time an event is sent to Sentry. - + Contains the raw byte data of the attachment. - + The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. - + The filename of the attachment. This is the name that will be displayed in Sentry. If not provided, the filename will be extracted from the [member path]. - + The file path of the attachment. This can be an absolute path or use Godot's virtual file system paths such as "user://". diff --git a/project/test/suites/test_attachment.gd b/project/test/suites/test_attachment.gd index 47ef56ab..7b5b773b 100644 --- a/project/test/suites/test_attachment.gd +++ b/project/test/suites/test_attachment.gd @@ -3,15 +3,14 @@ extends GdUnitTestSuite func test_create_with_path() -> void: - var attachment := SentryAttachment.create_with_path( - "res://example_configuration.gd", - "config.gd", - "text/x-gdscript" - ) + var attachment := SentryAttachment.create_with_path("user://logs/godot.log") + attachment.filename = "logfile.txt" + attachment.content_type = "text/plain" + assert_array(attachment.bytes).is_empty() - assert_str(attachment.path).is_equal("res://example_configuration.gd") - assert_str(attachment.filename).is_equal("config.gd") - assert_str(attachment.content_type).is_equal("text/x-gdscript") + assert_str(attachment.path).is_equal("user://logs/godot.log") + assert_str(attachment.filename).is_equal("logfile.txt") + assert_str(attachment.content_type).is_equal("text/plain") func test_create_with_bytes() -> void: @@ -20,8 +19,8 @@ func test_create_with_bytes() -> void: """ var bytes: PackedByteArray = contents.to_utf8_buffer() - var attachment := SentryAttachment.create_with_bytes( - bytes, "hello.txt", "text/plain") + var attachment := SentryAttachment.create_with_bytes(bytes, "hello.txt") + attachment.content_type = "text/plain" assert_array(attachment.bytes).is_not_empty() assert_str(attachment.path).is_empty() diff --git a/project/views/enrich_events.gd b/project/views/enrich_events.gd index b93c469c..ad7b4596 100644 --- a/project/views/enrich_events.gd +++ b/project/views/enrich_events.gd @@ -51,7 +51,7 @@ func _on_set_context_pressed() -> void: func _on_attach_button_pressed() -> void: var content: String = %AttachmentContent.text var bytes: PackedByteArray = content.to_utf8_buffer() - var attachment := SentryAttachment.create_with_bytes( - bytes, "hello.txt", "text/plain") + var attachment := SentryAttachment.create_with_bytes(bytes, "hello.txt") + attachment.content_type = "text/plain" SentrySDK.add_attachment(attachment) DemoOutput.print_info("Attachment added.") diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index caad102a..45d9cadc 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -4,32 +4,29 @@ #include -Ref SentryAttachment::create_with_path(const String &p_path, const String &p_filename, const String &p_content_type) { +Ref SentryAttachment::create_with_path(const String &p_path) { ERR_FAIL_COND_V_MSG(p_path.is_empty(), Ref(), "Sentry: Can't create attachment with an empty file path."); Ref attachment = memnew(SentryAttachment); attachment->path = p_path; - attachment->filename = p_filename; - attachment->content_type = p_content_type; return attachment; } -Ref SentryAttachment::create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename, const String &p_content_type) { +Ref SentryAttachment::create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename) { ERR_FAIL_COND_V_MSG(p_filename.is_empty(), Ref(), "Sentry: Can't create attachment with an empty filename."); Ref attachment = memnew(SentryAttachment); attachment->bytes = p_bytes; attachment->filename = p_filename; - attachment->content_type = p_content_type; return attachment; } void SentryAttachment::_bind_methods() { - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path", "filename", "content_type"), &SentryAttachment::create_with_path, DEFVAL(""), DEFVAL("")); - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_bytes", "bytes", "filename", "content_type"), &SentryAttachment::create_with_bytes, DEFVAL("")); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path"), &SentryAttachment::create_with_path, DEFVAL(""), DEFVAL("")); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_bytes", "bytes", "filename"), &SentryAttachment::create_with_bytes, DEFVAL("")); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), get_bytes); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "path"), get_path); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "filename"), get_filename); - BIND_PROPERTY_READONLY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), get_content_type); + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), set_bytes, get_bytes); + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "path"), set_path, get_path); + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "filename"), set_filename, get_filename); + BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "content_type"), set_content_type, get_content_type); } diff --git a/src/sentry_attachment.h b/src/sentry_attachment.h index 399947ac..d02355e1 100644 --- a/src/sentry_attachment.h +++ b/src/sentry_attachment.h @@ -29,13 +29,20 @@ class SentryAttachment : public RefCounted { static void _bind_methods(); public: - static Ref create_with_path(const String &p_path, const String &p_filename = "", const String &p_content_type = ""); - static Ref create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename, const String &p_content_type = ""); + static Ref create_with_path(const String &p_path); + static Ref create_with_bytes(const PackedByteArray &p_bytes, const String &p_filename); PackedByteArray get_bytes() const { return bytes; } + void set_bytes(const PackedByteArray &p_bytes) { bytes = p_bytes; } + String get_path() const { return path; } + void set_path(const String &p_path) { path = p_path; } + String get_filename() const { return filename; } + void set_filename(const String &p_filename) { filename = p_filename; } + String get_content_type() const { return content_type; } + void set_content_type(const String &p_content_type) { content_type = p_content_type; } #ifdef NATIVE_SDK sentry_attachment_t *get_native_attachment() const { return native_attachment; } From 31a7519322b9b974e7bc537e25e0303a33ad320d Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 26 Jun 2025 11:40:16 +0200 Subject: [PATCH 30/33] Remove default values from creator methods --- doc_classes/SentryAttachment.xml | 4 ++-- src/sentry_attachment.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index bee9b4c6..15e12945 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -14,7 +14,7 @@ - + Creates a new [SentryAttachment] with the specified [param bytes] data and [param filename]. The [param bytes] parameter contains the raw file data to be attached. The [param filename] parameter specifies the display name for the attachment in Sentry. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). This method is useful when you have file data already loaded in memory or when creating attachments from generated content rather than existing files on disk. @@ -22,7 +22,7 @@ - + Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). [b]Note:[/b] Modifying attachment properties after the attachment has been added with [method SentrySDK.add_attachment] will have no effect. To apply property changes, you need to re-add the attachment. diff --git a/src/sentry_attachment.cpp b/src/sentry_attachment.cpp index 45d9cadc..41b7bf83 100644 --- a/src/sentry_attachment.cpp +++ b/src/sentry_attachment.cpp @@ -22,8 +22,8 @@ Ref SentryAttachment::create_with_bytes(const PackedByteArray } void SentryAttachment::_bind_methods() { - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path"), &SentryAttachment::create_with_path, DEFVAL(""), DEFVAL("")); - ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_bytes", "bytes", "filename"), &SentryAttachment::create_with_bytes, DEFVAL("")); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_path", "path"), &SentryAttachment::create_with_path); + ClassDB::bind_static_method("SentryAttachment", D_METHOD("create_with_bytes", "bytes", "filename"), &SentryAttachment::create_with_bytes); BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), set_bytes, get_bytes); BIND_PROPERTY(SentryAttachment, PropertyInfo(Variant::STRING, "path"), set_path, get_path); From 81819774e435a657f4c11456d8e6e2e497832835 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 30 Jun 2025 19:54:39 +0200 Subject: [PATCH 31/33] Remove remove_attachment() method --- .../sentry/godotplugin/SentryAndroidGodotPlugin.kt | 14 -------------- doc_classes/SentryAttachment.xml | 2 +- doc_classes/SentrySDK.xml | 7 ------- src/sentry/android/android_sdk.cpp | 12 ------------ src/sentry/android/android_sdk.h | 1 - src/sentry/android/android_string_names.cpp | 2 -- src/sentry/android/android_string_names.h | 2 -- src/sentry/disabled_sdk.h | 1 - src/sentry/internal_sdk.h | 1 - src/sentry/native/native_sdk.cpp | 13 ------------- src/sentry/native/native_sdk.h | 1 - src/sentry_sdk.cpp | 6 ------ src/sentry_sdk.h | 1 - 13 files changed, 1 insertion(+), 62 deletions(-) diff --git a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt index c838ea0f..2c6ac1b3 100644 --- a/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt +++ b/android_lib/src/main/java/io/sentry/godotplugin/SentryAndroidGodotPlugin.kt @@ -135,13 +135,6 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { Sentry.getGlobalScope().addAttachment(attachment) } - @UsedByGodot - fun removeFileAttachment(path: String) { - val globalScope = Sentry.getGlobalScope() - val attachment = globalScope.attachments.find { att -> att.pathname == path } - attachment?.let { globalScope.attachments.remove(attachment) } - } - @UsedByGodot fun addBytesAttachment(bytes: ByteArray, filename: String, contentType: String, attachmentType: String) { val attachment = Attachment( @@ -154,13 +147,6 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) { Sentry.getGlobalScope().addAttachment(attachment) } - @UsedByGodot - fun removeBytesAttachment(filename: String) { - val globalScope = Sentry.getGlobalScope() - val attachment = globalScope.attachments.find { att -> att.filename == filename } - attachment?.let { globalScope.attachments.remove(attachment) } - } - @UsedByGodot fun setContext(key: String, value: Dictionary) { Sentry.getGlobalScope().setContexts(key, value) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 15e12945..143c55cb 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -5,7 +5,7 @@ SentryAttachment represents a file that can be attached to Sentry events to provide additional context. Attachments are files that are uploaded alongside error reports and can include log files, screenshots, configuration files, or any other relevant data. - Attachments can be created using [method SentryAttachment.create_with_path] for existing files on disk or [method SentryAttachment.create_with_bytes] for data already in memory. Once created, they can be added to future events using [method SentrySDK.add_attachment] and removed using [method SentrySDK.remove_attachment]. + Attachments can be created using [method SentryAttachment.create_with_path] for existing files on disk or [method SentryAttachment.create_with_bytes] for data already in memory. Once created, they can be added to future events using [method SentrySDK.add_attachment]. To learn more about attachments, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url]. diff --git a/doc_classes/SentrySDK.xml b/doc_classes/SentrySDK.xml index 6a3c379c..01737a14 100644 --- a/doc_classes/SentrySDK.xml +++ b/doc_classes/SentrySDK.xml @@ -72,13 +72,6 @@ Returns whether the SDK is enabled, i.e. whether it is initialized and active. - - - - - Removes a previously added attachment from future Sentry events. The [param attachment] should be a [SentryAttachment] object added with [method SentrySDK.add_attachment]. - - diff --git a/src/sentry/android/android_sdk.cpp b/src/sentry/android/android_sdk.cpp index 49141b4e..429f786c 100644 --- a/src/sentry/android/android_sdk.cpp +++ b/src/sentry/android/android_sdk.cpp @@ -136,18 +136,6 @@ void AndroidSDK::add_attachment(const Ref &p_attachment) { } } -void AndroidSDK::remove_attachment(const Ref &p_attachment) { - ERR_FAIL_COND(p_attachment.is_null()); - - if (p_attachment->get_path().is_empty()) { - android_plugin->call(ANDROID_SN(removeBytesAttachment), - p_attachment->get_filename()); - } else { - android_plugin->call(ANDROID_SN(removeFileAttachment), - p_attachment->get_path()); - } -} - void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) { ERR_FAIL_NULL(android_plugin); diff --git a/src/sentry/android/android_sdk.h b/src/sentry/android/android_sdk.h index ea481f02..ff71bc69 100644 --- a/src/sentry/android/android_sdk.h +++ b/src/sentry/android/android_sdk.h @@ -48,7 +48,6 @@ class AndroidSDK : public InternalSDK { virtual String capture_event(const Ref &p_event) override; virtual void add_attachment(const Ref &p_attachment) override; - virtual void remove_attachment(const Ref &p_attachment) override; virtual void initialize(const PackedStringArray &p_global_attachments) override; diff --git a/src/sentry/android/android_string_names.cpp b/src/sentry/android/android_string_names.cpp index 9e712706..fc1a132a 100644 --- a/src/sentry/android/android_string_names.cpp +++ b/src/sentry/android/android_string_names.cpp @@ -29,9 +29,7 @@ AndroidStringNames::AndroidStringNames() { releaseEvent = StringName("releaseEvent"); captureEvent = StringName("captureEvent"); addFileAttachment = StringName("addFileAttachment"); - removeFileAttachment = StringName("removeFileAttachment"); addBytesAttachment = StringName("addBytesAttachment"); - removeBytesAttachment = StringName("removeBytesAttachment"); // Event methods. eventGetId = StringName("eventGetId"); diff --git a/src/sentry/android/android_string_names.h b/src/sentry/android/android_string_names.h index 37f94c7d..9d6546a8 100644 --- a/src/sentry/android/android_string_names.h +++ b/src/sentry/android/android_string_names.h @@ -41,9 +41,7 @@ class AndroidStringNames { StringName releaseEvent; StringName captureEvent; StringName addFileAttachment; - StringName removeFileAttachment; StringName addBytesAttachment; - StringName removeBytesAttachment; // Event methods. StringName eventGetId; diff --git a/src/sentry/disabled_sdk.h b/src/sentry/disabled_sdk.h index 2a847bf9..1460ddd0 100644 --- a/src/sentry/disabled_sdk.h +++ b/src/sentry/disabled_sdk.h @@ -27,7 +27,6 @@ class DisabledSDK : public InternalSDK { virtual String capture_event(const Ref &p_event) override { return ""; } virtual void add_attachment(const Ref &p_attachment) override {} - virtual void remove_attachment(const Ref &p_attachment) override {} virtual void initialize(const PackedStringArray &p_global_attachments) override {} }; diff --git a/src/sentry/internal_sdk.h b/src/sentry/internal_sdk.h index 3b9ebad3..1e6e66ee 100644 --- a/src/sentry/internal_sdk.h +++ b/src/sentry/internal_sdk.h @@ -37,7 +37,6 @@ class InternalSDK { virtual String capture_event(const Ref &p_event) = 0; virtual void add_attachment(const Ref &p_attachment) = 0; - virtual void remove_attachment(const Ref &p_attachment) = 0; virtual void initialize(const PackedStringArray &p_global_attachments) = 0; diff --git a/src/sentry/native/native_sdk.cpp b/src/sentry/native/native_sdk.cpp index b6c4d203..470bf7a9 100644 --- a/src/sentry/native/native_sdk.cpp +++ b/src/sentry/native/native_sdk.cpp @@ -378,19 +378,6 @@ void NativeSDK::add_attachment(const Ref &p_attachment) { } } -void NativeSDK::remove_attachment(const Ref &p_attachment) { - ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't remove null attachment."); - - sentry_attachment_t *native_attachment = p_attachment->get_native_attachment(); - if (native_attachment) { - sentry_remove_attachment(native_attachment); - p_attachment->set_native_attachment(nullptr); - sentry::util::print_debug(vformat("removed attachment: %s", p_attachment->get_path())); - } else { - sentry::util::print_warning(vformat("attempted to remove attachment that was not added: %s", p_attachment->get_path())); - } -} - void NativeSDK::initialize(const PackedStringArray &p_global_attachments) { ERR_FAIL_NULL(OS::get_singleton()); ERR_FAIL_NULL(ProjectSettings::get_singleton()); diff --git a/src/sentry/native/native_sdk.h b/src/sentry/native/native_sdk.h index 2411709d..fa4e988e 100644 --- a/src/sentry/native/native_sdk.h +++ b/src/sentry/native/native_sdk.h @@ -34,7 +34,6 @@ class NativeSDK : public InternalSDK { virtual String capture_event(const Ref &p_event) override; virtual void add_attachment(const Ref &p_attachment) override; - virtual void remove_attachment(const Ref &p_attachment) override; virtual void initialize(const PackedStringArray &p_global_attachments) override; diff --git a/src/sentry_sdk.cpp b/src/sentry_sdk.cpp index 38079837..d7bd35fd 100644 --- a/src/sentry_sdk.cpp +++ b/src/sentry_sdk.cpp @@ -83,11 +83,6 @@ void SentrySDK::add_attachment(const Ref &p_attachment) { internal_sdk->add_attachment(p_attachment); } -void SentrySDK::remove_attachment(const Ref &p_attachment) { - ERR_FAIL_COND_MSG(p_attachment.is_null(), "Sentry: Can't remove null attachment."); - internal_sdk->remove_attachment(p_attachment); -} - void SentrySDK::set_tag(const String &p_key, const String &p_value) { ERR_FAIL_COND_MSG(p_key.is_empty(), "Sentry: Can't set tag with an empty key."); internal_sdk->set_tag(p_key, p_value); @@ -259,7 +254,6 @@ void SentrySDK::_bind_methods() { 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("add_attachment", "attachment"), &SentrySDK::add_attachment); - ClassDB::bind_method(D_METHOD("remove_attachment", "attachment"), &SentrySDK::remove_attachment); // Hidden API methods -- used in testing. ClassDB::bind_method(D_METHOD("_set_before_send", "callable"), &SentrySDK::set_before_send); diff --git a/src/sentry_sdk.h b/src/sentry_sdk.h index a8195383..a8d9f59a 100644 --- a/src/sentry_sdk.h +++ b/src/sentry_sdk.h @@ -72,7 +72,6 @@ class SentrySDK : public Object { String capture_event(const Ref &p_event); void add_attachment(const Ref &p_attachment); - void remove_attachment(const Ref &p_attachment); // * Hidden API methods -- used in testing From 624b1508e65f59d80b001d4d06f9bba816b46b58 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 30 Jun 2025 21:51:32 +0200 Subject: [PATCH 32/33] Add MIME type info to SentryAttachment content_type docs --- doc_classes/SentryAttachment.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index 143c55cb..da7e3f05 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -16,7 +16,7 @@ - Creates a new [SentryAttachment] with the specified [param bytes] data and [param filename]. The [param bytes] parameter contains the raw file data to be attached. The [param filename] parameter specifies the display name for the attachment in Sentry. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + Creates a new [SentryAttachment] with the specified [param bytes] data and [param filename]. The [param bytes] parameter contains the raw file data to be attached. The [param filename] parameter specifies the display name for the attachment in Sentry. This method is useful when you have file data already loaded in memory or when creating attachments from generated content rather than existing files on disk. @@ -24,7 +24,7 @@ - Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://". The optional [param filename] parameter specifies the display name for the attachment in Sentry - if not provided, the filename will be extracted from the path. The optional [param content_type] parameter specifies the MIME type of the file (e.g., "text/plain", "application/json"). + Creates a new [SentryAttachment] with the specified file [param path] and optional [param filename] and [param content_type]. The [param path] should point to an existing file and supports Godot's virtual file system paths like "user://". [b]Note:[/b] Modifying attachment properties after the attachment has been added with [method SentrySDK.add_attachment] will have no effect. To apply property changes, you need to re-add the attachment. [b]Important:[/b] Attachments are read lazily at the time an event is sent to Sentry. @@ -36,6 +36,7 @@ The MIME content type of the attachment file. This helps Sentry understand how to handle and display the attachment. + Sentry understands and renders the following MIME types: [code]text/plain[/code], [code]text/css[/code], [code]text/csv[/code], [code]text/html[/code], [code]text/javascript[/code], [code]text/json[/code] or [code]text/x-json[/code] or [code]application/json[/code] or [code]application/ld+json[/code], [code]image/jpeg[/code], [code]image/png[/code], [code]image/gif[/code]. The filename of the attachment. This is the name that will be displayed in Sentry. If not provided, the filename will be extracted from the [member path]. From 398a5b5c4e2cdf8d3f0cc62824fc349f55105973 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Mon, 30 Jun 2025 22:36:28 +0200 Subject: [PATCH 33/33] Add usage examples --- doc_classes/SentryAttachment.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc_classes/SentryAttachment.xml b/doc_classes/SentryAttachment.xml index da7e3f05..c13f2b26 100644 --- a/doc_classes/SentryAttachment.xml +++ b/doc_classes/SentryAttachment.xml @@ -5,7 +5,19 @@ SentryAttachment represents a file that can be attached to Sentry events to provide additional context. Attachments are files that are uploaded alongside error reports and can include log files, screenshots, configuration files, or any other relevant data. - Attachments can be created using [method SentryAttachment.create_with_path] for existing files on disk or [method SentryAttachment.create_with_bytes] for data already in memory. Once created, they can be added to future events using [method SentrySDK.add_attachment]. + Attachments can be created using [method SentryAttachment.create_with_path] for existing files on disk. Once created, they can be added to future events using [method SentrySDK.add_attachment]: + [codeblock] + var attachment := SentryAttachment.create_with_path("user://logs/godot.log") + attachment.content_type = "text/plain" + SentrySDK.add_attachment(attachment) + [/codeblock] + Attachments can also be created using [method SentryAttachment.create_with_bytes] for data already in memory: + [codeblock] + var bytes: PackedByteArray = "Hello, world!".to_ascii_buffer() + var attachment := SentryAttachment.create_with_bytes(bytes, "hello.txt") + attachment.content_type = "text/plain" + SentrySDK.add_attachment(attachment) + [/codeblock] To learn more about attachments, visit [url=https://docs.sentry.io/platforms/godot/enriching-events/attachments/]Attachments documentation[/url].