Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
d7f8249
Explicit singleton
limbonaut Aug 19, 2025
cdaa093
Refactor Sentry class registration
limbonaut Aug 19, 2025
0a91456
Auto-initialize in a separate step, ensure internal SDK is ready early
limbonaut Aug 19, 2025
044263a
Rename func => _auto_initialize()
limbonaut Aug 19, 2025
d809e8b
Move event processor initialization to prepare step
limbonaut Aug 19, 2025
62bb04f
Correct comment
limbonaut Aug 19, 2025
6e4835f
Fix Android compilation
limbonaut Aug 19, 2025
6cba510
Simplify Android enabling code
limbonaut Aug 19, 2025
a721f65
Rename initialize => init
limbonaut Aug 19, 2025
6cf9fd7
Update CHANGELOG.md
limbonaut Aug 20, 2025
c61ad72
Return plugin check on Android
limbonaut Aug 20, 2025
744d5a3
Update CHANGELOG.md
limbonaut Aug 20, 2025
5670b80
Merge branch 'main' into ref/impove-initialization-extracted
limbonaut Aug 20, 2025
847f49e
Add SentrySDK.init(), close(), is_enabled()
limbonaut Aug 19, 2025
1250511
Remove enabled flag and move logger registration into init()
limbonaut Aug 20, 2025
ee888c4
Add error handling for _configure
limbonaut Aug 20, 2025
8a8304f
Move contexts init logic into init()
limbonaut Aug 20, 2025
9310679
Whitespace fix
limbonaut Aug 20, 2025
0b5f933
Expose new methods, and add docs
limbonaut Aug 20, 2025
b25c545
Add tests for lifecycle methods
limbonaut Aug 21, 2025
dc71c41
Rename lifecycle test to test_sdk_lifecycle.gd
limbonaut Aug 21, 2025
3356bc2
Add tests for closing SDK
limbonaut Aug 21, 2025
9b31037
Fix issues with SentryLogger connecting to signal
limbonaut Aug 21, 2025
a21f3e9
Fix initialized flag should be set to false in NativeSDK on close(), and
limbonaut Aug 21, 2025
b8a9732
Merge branch 'main' into ref/improve-initialization
limbonaut Sep 9, 2025
11fcc68
Rename enabled/disabled options, remove them from exposed properties,
limbonaut Sep 10, 2025
bb1681d
Remove configuration script option
limbonaut Sep 10, 2025
b6c0a9c
Add configuration callback in init()
limbonaut Sep 10, 2025
6f07401
Remove SentryConfiguration class
limbonaut Sep 10, 2025
5c2a211
Merge branch 'main' into ref/improve-initialization
limbonaut Sep 10, 2025
1dbdbcb
Replace configuration script with init() & before_send example from
limbonaut Sep 10, 2025
320a903
Adjust isolation tests for new init
limbonaut Sep 10, 2025
bdb697e
Remove testing_configuration.gd
limbonaut Sep 10, 2025
38f016b
Adjust normal test suites for the new init
limbonaut Sep 10, 2025
f5a7da9
Update docs
limbonaut Sep 10, 2025
a26c9a5
Update SentrySDK.xml
limbonaut Sep 10, 2025
9baac57
Update docs with initialization & configuration examples
limbonaut Sep 10, 2025
1ee4106
Fix user not initialized if init() is not called
limbonaut Sep 10, 2025
cc00783
Restore SDK lifecycle isolated test
limbonaut Sep 10, 2025
a2c541b
Cosmetic fixes for docs
limbonaut Sep 10, 2025
3ee3da5
Auto doc fixes
limbonaut Sep 10, 2025
680d16f
Remove test_sdk_close as redundant
limbonaut Sep 10, 2025
d548380
Move contexts initialization into sentry::contexts
limbonaut Sep 10, 2025
e4b1ac3
Refactor context initialization to avoid Godot errors
limbonaut Sep 10, 2025
c99f787
Rename initialize => init on Android
limbonaut Sep 10, 2025
dd112bd
Revert "Move contexts initialization into sentry::contexts"
limbonaut Sep 10, 2025
2e15faf
Only close SDK if enabled in destructors
limbonaut Sep 10, 2025
888c017
Remove unused should_delay_contexts function
limbonaut Sep 10, 2025
c591cd9
Update CHANGELOG.md
limbonaut Sep 10, 2025
cd31f66
Update CHANGELOG.md
limbonaut Sep 10, 2025
89dbb9b
Fix link in CHANGELOG
limbonaut Sep 10, 2025
03dd1bb
Don't auto-initialize if DSN is empty
limbonaut Sep 11, 2025
973403f
Explain gui-only options in SentryOptions
limbonaut Sep 12, 2025
940df89
Fix unterminated bbcode
limbonaut Sep 12, 2025
521276e
Sync with docs
limbonaut Sep 12, 2025
7c34f6e
Update SentryOptions.xml
limbonaut Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Improvements

- Improve initialization flow ([#322](https://github.com/getsentry/sentry-godot/pull/322))

### Dependencies

- Bump Cocoa SDK from v8.54.0 to v8.55.0 ([#318](https://github.com/getsentry/sentry-godot/pull/318))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ class SentryAndroidGodotPlugin(godot: Godot) : GodotPlugin(godot) {
}
}

@UsedByGodot
fun close() {
Sentry.close()
}

@UsedByGodot
fun isEnabled(): Boolean {
return Sentry.isEnabled()
}

@UsedByGodot
fun addFileAttachment(path: String, filename: String, contentType: String, attachmentType: String) {
val attachment = Attachment(
Expand Down
12 changes: 12 additions & 0 deletions doc_classes/SentrySDK.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
Captures an event with [param message] and sends it to Sentry, returning the event ID.
</description>
</method>
<method name="close">
<return type="void" />
<description>
Closes the SDK and flushes any pending events to ensure all queued data is sent to Sentry before shutdown. Called automatically when the application exits.
</description>
</method>
<method name="create_event" qualifiers="const">
<return type="SentryEvent" />
<description>
Expand All @@ -66,6 +72,12 @@
Returns the currently set user. See [SentryUser].
</description>
</method>
<method name="init">
<return type="void" />
<description>
Initializes the SDK. Called automatically during startup if [member SentryOptions.enabled] is set to [code]true[/code]. Manual initialization is only needed when you want to control the exact timing of SDK startup or when automatic initialization is disabled.
</description>
</method>
<method name="is_enabled" qualifiers="const">
<return type="bool" />
<description>
Expand Down
35 changes: 35 additions & 0 deletions project/test/isolated/test_sdk_close.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extends GdUnitTestSuite
## Test SDK should stop capture if closed via code.


signal callback_processed


static func configure_options(options: SentryOptions) -> void:
# Ensure SDK auto-intialization.
options.enabled = true


func before_test() -> void:
SentrySDK._set_before_send(_before_send)


func _before_send(_ev: SentryEvent) -> SentryEvent:
callback_processed.emit()
return null


func test_capture_when_sdk_closed() -> void:
var monitor := monitor_signals(self, false)

# SDK should auto initialize when enabled.
assert_bool(SentrySDK.is_enabled()).is_true()

SentrySDK.capture_message("message captured when SDK is initialiazed")
await assert_signal(monitor).is_emitted("callback_processed")

SentrySDK.close()
assert_bool(SentrySDK.is_enabled()).is_false()

SentrySDK.capture_message("message not captured when SDK is closed")
await assert_signal(monitor).is_not_emitted("callback_processed")
1 change: 1 addition & 0 deletions project/test/isolated/test_sdk_close.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://bitdh4j15m2tl
42 changes: 42 additions & 0 deletions project/test/isolated/test_sdk_lifecycle.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
extends GdUnitTestSuite
## Test SDK lifecycle methods.


signal callback_processed


static func configure_options(options: SentryOptions) -> void:
# Disable SDK auto-intialization.
options.enabled = false


func before_test() -> void:
SentrySDK._set_before_send(_before_send)


func _before_send(_ev: SentryEvent) -> SentryEvent:
callback_processed.emit()
return null


## Test manual initialization and shutdown of SDK.
func test_lifecycle() -> void:
var monitor := monitor_signals(self, false)

# SDK should be disabled when `options.enabled = false`
assert_bool(SentrySDK.is_enabled()).is_false()

SentrySDK.capture_message("message not captured before SDK is initialized")
await assert_signal(monitor).is_not_emitted("callback_processed")

SentrySDK.init()
assert_bool(SentrySDK.is_enabled()).is_true()

SentrySDK.capture_message("message captured when SDK is initialiazed")
await assert_signal(monitor).is_emitted("callback_processed")

SentrySDK.close()
assert_bool(SentrySDK.is_enabled()).is_false()

SentrySDK.capture_message("message not captured when SDK is closed")
await assert_signal(monitor).is_not_emitted("callback_processed")
1 change: 1 addition & 0 deletions project/test/isolated/test_sdk_lifecycle.gd.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://lrv0g3lj2pds
74 changes: 41 additions & 33 deletions src/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,59 +39,67 @@
using namespace godot;
using namespace sentry;

void initialize_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_CORE) {
} else if (p_level == godot::MODULE_INITIALIZATION_LEVEL_SERVERS) {
} else if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
GDREGISTER_CLASS(SentryLoggerLimits);
GDREGISTER_CLASS(SentryOptions);
GDREGISTER_INTERNAL_CLASS(RuntimeConfig);
GDREGISTER_CLASS(SentryConfiguration);
GDREGISTER_CLASS(SentryUser);
GDREGISTER_CLASS(SentryTimestamp);
GDREGISTER_CLASS(SentrySDK);
GDREGISTER_ABSTRACT_CLASS(SentryAttachment);
GDREGISTER_ABSTRACT_CLASS(SentryEvent);
GDREGISTER_INTERNAL_CLASS(DisabledEvent);
GDREGISTER_INTERNAL_CLASS(SentryEventProcessor);
GDREGISTER_INTERNAL_CLASS(ScreenshotProcessor);
GDREGISTER_INTERNAL_CLASS(ViewHierarchyProcessor);
GDREGISTER_INTERNAL_CLASS(SentryLogger);
void register_runtime_classes() {
GDREGISTER_CLASS(SentryLoggerLimits);
GDREGISTER_CLASS(SentryOptions);
GDREGISTER_INTERNAL_CLASS(RuntimeConfig);
GDREGISTER_CLASS(SentryConfiguration);
GDREGISTER_CLASS(SentryUser);
GDREGISTER_CLASS(SentryTimestamp);
GDREGISTER_CLASS(SentrySDK);
GDREGISTER_ABSTRACT_CLASS(SentryAttachment);
GDREGISTER_ABSTRACT_CLASS(SentryEvent);
GDREGISTER_INTERNAL_CLASS(DisabledEvent);
GDREGISTER_INTERNAL_CLASS(SentryEventProcessor);
GDREGISTER_INTERNAL_CLASS(ScreenshotProcessor);
GDREGISTER_INTERNAL_CLASS(ViewHierarchyProcessor);
GDREGISTER_INTERNAL_CLASS(SentryLogger);

#ifdef SDK_NATIVE
GDREGISTER_INTERNAL_CLASS(NativeEvent);
GDREGISTER_INTERNAL_CLASS(NativeEvent);
#endif

#ifdef SDK_ANDROID
GDREGISTER_INTERNAL_CLASS(AndroidEvent);
GDREGISTER_INTERNAL_CLASS(SentryAndroidBeforeSendHandler);
GDREGISTER_INTERNAL_CLASS(AndroidEvent);
GDREGISTER_INTERNAL_CLASS(SentryAndroidBeforeSendHandler);
#endif

#ifdef SDK_COCOA
GDREGISTER_INTERNAL_CLASS(cocoa::CocoaEvent);
GDREGISTER_INTERNAL_CLASS(cocoa::CocoaEvent);
#endif
}

SentryOptions::create_singleton();

SentrySDK *sentry_singleton = memnew(SentrySDK);
Engine::get_singleton()->register_singleton("SentrySDK", SentrySDK::get_singleton());
} else if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
void register_editor_classes() {
#ifdef TOOLS_ENABLED
GDREGISTER_INTERNAL_CLASS(SentryEditorExportPluginAndroid);
GDREGISTER_INTERNAL_CLASS(SentryEditorPlugin);

#ifndef WINDOWS_ENABLED
GDREGISTER_INTERNAL_CLASS(SentryEditorExportPluginUnix);
GDREGISTER_INTERNAL_CLASS(SentryEditorExportPluginUnix);
#endif // !WINDOWS_ENABLED
GDREGISTER_INTERNAL_CLASS(SentryEditorExportPluginAndroid);
GDREGISTER_INTERNAL_CLASS(SentryEditorPlugin);

#endif // TOOLS_ENABLED
}

void initialize_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_CORE) {
} else if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) {
} else if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
register_runtime_classes();
SentryOptions::create_singleton();
SentrySDK::create_singleton();
SentrySDK::get_singleton()->prepare_and_auto_initialize();
} else if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
#ifdef TOOLS_ENABLED
register_editor_classes();
EditorPlugins::add_by_type<SentryEditorPlugin>();
#endif // TOOLS_ENABLED
}
}

void uninitialize_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
if (SentrySDK::get_singleton()) {
memdelete(SentrySDK::get_singleton());
}
SentrySDK::destroy_singleton();
SentryOptions::destroy_singleton();
}
}
Expand Down
16 changes: 12 additions & 4 deletions src/sentry/android/android_sdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,9 @@ void AndroidSDK::add_attachment(const Ref<SentryAttachment> &p_attachment) {
}
}

void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) {
void AndroidSDK::init(const PackedStringArray &p_global_attachments) {
ERR_FAIL_NULL(android_plugin);

sentry::util::print_debug("Initializing Sentry Android SDK");

for (const String &path : p_global_attachments) {
bool is_view_hierarchy = path.ends_with(SENTRY_VIEW_HIERARCHY_FN);
android_plugin->call(ANDROID_SN(addFileAttachment),
Expand All @@ -139,7 +137,7 @@ void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) {
is_view_hierarchy ? "event.view_hierarchy" : String());
}

android_plugin->call("initialize",
android_plugin->call(ANDROID_SN(init),
before_send_handler->get_instance_id(),
SentryOptions::get_singleton()->get_dsn(),
SentryOptions::get_singleton()->is_debug_enabled(),
Expand All @@ -150,6 +148,16 @@ void AndroidSDK::initialize(const PackedStringArray &p_global_attachments) {
SentryOptions::get_singleton()->get_max_breadcrumbs());
}

void AndroidSDK::close() {
if (android_plugin != nullptr) {
android_plugin->call(ANDROID_SN(close));
}
}

bool AndroidSDK::is_enabled() const {
return android_plugin && android_plugin->call(ANDROID_SN(isEnabled));
}

AndroidSDK::AndroidSDK() {
AndroidStringNames::create_singleton();

Expand Down
4 changes: 3 additions & 1 deletion src/sentry/android/android_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ class AndroidSDK : public InternalSDK {

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

virtual void initialize(const PackedStringArray &p_global_attachments) override;
virtual void init(const PackedStringArray &p_global_attachments) override;
virtual void close() override;
virtual bool is_enabled() const override;

bool has_android_plugin() const { return android_plugin != nullptr; }

Expand Down
3 changes: 3 additions & 0 deletions src/sentry/android/android_string_names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ void AndroidStringNames::destroy_singleton() {

AndroidStringNames::AndroidStringNames() {
// API methods.
init = StringName("init");
close = StringName("close");
isEnabled = StringName("isEnabled");
setContext = StringName("setContext");
removeContext = StringName("removeContext");
setTag = StringName("setTag");
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/android/android_string_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class AndroidStringNames {
_FORCE_INLINE_ static AndroidStringNames *get_singleton() { return singleton; }

// API methods.
StringName init;
StringName close;
StringName isEnabled;
StringName setContext;
StringName removeContext;
StringName setTag;
Expand Down
6 changes: 3 additions & 3 deletions src/sentry/cocoa/cocoa_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class CocoaSDK : public InternalSDK {

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

virtual void initialize(const PackedStringArray &p_global_attachments) override;

bool is_enabled() const;
virtual void init(const PackedStringArray &p_global_attachments) override;
virtual void close() override;
virtual bool is_enabled() const override;

CocoaSDK();
virtual ~CocoaSDK() override;
Expand Down
10 changes: 6 additions & 4 deletions src/sentry/cocoa/cocoa_sdk.mm
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
}];
}

void CocoaSDK::initialize(const PackedStringArray &p_global_attachments) {
void CocoaSDK::init(const PackedStringArray &p_global_attachments) {
[PrivateSentrySDKOnly setSdkName:@"sentry.cocoa.godot"];

[objc::SentrySDK startWithConfigureOptions:^(objc::SentryOptions *options) {
Expand Down Expand Up @@ -200,6 +200,10 @@
}];
}

void CocoaSDK::close() {
[objc::SentrySDK close];
}

bool CocoaSDK::is_enabled() const {
return [objc::SentrySDK isEnabled];
}
Expand All @@ -209,9 +213,7 @@
}

CocoaSDK::~CocoaSDK() {
if (is_enabled()) {
[objc::SentrySDK close];
}
close();
}

} //namespace sentry::cocoa
9 changes: 8 additions & 1 deletion src/sentry/contexts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "gen/sdk_version.gen.h"
#include "sentry/environment.h"
#include "sentry/sentry_options.h"
#include "sentry/uuid.h"

#include <godot_cpp/classes/dir_access.hpp>
#include <godot_cpp/classes/display_server.hpp>
Expand Down Expand Up @@ -50,6 +49,14 @@ String _screen_orientation_as_string(int32_t p_screen) {

namespace sentry::contexts {

bool should_delay_contexts() {
// Delay contexts if engine singletons are not ready.
return !OS::get_singleton() || !Engine::get_singleton() ||
!DisplayServer::get_singleton() || !Time::get_singleton() ||
!ProjectSettings::get_singleton() || !Performance::get_singleton() ||
!RenderingServer::get_singleton();
}

Dictionary make_device_context(const Ref<RuntimeConfig> &p_runtime_config) {
Dictionary device_context = Dictionary();
ERR_FAIL_NULL_V(OS::get_singleton(), device_context);
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ using namespace godot;

namespace sentry::contexts {

bool should_delay_contexts();

Dictionary make_device_context(const Ref<RuntimeConfig> &p_runtime_config);

// Returns smaller device context dictionary that only includes values that are
Expand Down
4 changes: 3 additions & 1 deletion src/sentry/disabled/disabled_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ class DisabledSDK : public InternalSDK {

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

virtual void initialize(const PackedStringArray &p_global_attachments) override {}
virtual void init(const PackedStringArray &p_global_attachments) override {}
virtual void close() override {}
virtual bool is_enabled() const override { return false; }
};

} // namespace sentry
Expand Down
Loading
Loading