Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Event objects #51

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions project/test/test_event.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
class_name TestEvent
extends GdUnitTestSuite


## SentryEvent.id should not be empty on event creation.
func test_event_id() -> void:
var event := SentrySDK.create_event()
assert_str(event.id).is_not_empty()


## SentryEvent.message should be set to the specified value, and should be empty on event creation.
func test_event_message() -> void:
var event := SentrySDK.create_event()
assert_str(event.message).is_empty()
event.message = "Hello, World!"
assert_str(event.message).is_equal("Hello, World!")


## SentryEvent.level should be set to the specified value.
func test_event_level() -> void:
var event := SentrySDK.create_event()
for l in [SentrySDK.LEVEL_DEBUG, SentrySDK.LEVEL_INFO, SentrySDK.LEVEL_WARNING, SentrySDK.LEVEL_ERROR, SentrySDK.LEVEL_FATAL]:
event.level = l
assert_int(event.level).is_equal(l)


## SentryEvent.timestamp should not be empty on event creation, and setter should update it.
func test_event_timestamp() -> void:
var event := SentrySDK.create_event()
assert_str(event.timestamp).is_not_empty()
var ts = Time.get_datetime_string_from_system()
event.timestamp = ts
assert_str(event.timestamp).is_equal(ts)


## SentryEvent.platform should not be empty.
func test_event_platform() -> void:
var event := SentrySDK.create_event()
assert_str(event.platform).is_not_empty()


## SentryEvent.logger should be set to the specified value, and empty on event creation.
func test_event_logger() -> void:
var event := SentrySDK.create_event()
assert_str(event.logger).is_empty()
event.logger = "custom-logger"
assert_str(event.logger).is_equal("custom-logger")


## SentryEvent.release should be set to the specified value, and empty on event creation.
func test_event_release() -> void:
var event := SentrySDK.create_event()
assert_str(event.release).is_empty()
event.release = "custom-release"
assert_str(event.release).is_equal("custom-release")


## SentryEvent.dist should be set to the specified value, and empty on event creation.
func test_event_dist() -> void:
var event := SentrySDK.create_event()
assert_str(event.dist).is_empty()
event.dist = "custom-dist"
assert_str(event.dist).is_equal("custom-dist")


## SentryEvent.environment should be set to the specified value, and empty on event creation.
func test_event_environment() -> void:
var event := SentrySDK.create_event()
assert_str(event.environment).is_empty()
event.environment = "custom-environment"
assert_str(event.environment).is_equal("custom-environment")


## SentrySDK.capture_event() should return a non-empty event ID, which must match the ID returned by the get_last_event_id() call.
func test_capture_event() -> void:
var event := SentrySDK.create_event()
var event_id := SentrySDK.capture_event(event)
assert_str(event_id).is_not_empty()
assert_str(event_id).is_equal(event.id)
assert_str(SentrySDK.get_last_event_id()).is_not_empty()
assert_str(event_id).is_equal(SentrySDK.get_last_event_id())


## SentrySDK.create_message_event() should return a SentryEvent instance with the specified message and level, and should be able to be captured.
func test_create_message_event_and_capture() -> void:
var event := SentrySDK.create_message_event("Test message", SentrySDK.LEVEL_DEBUG, "custom-logger")
assert_str(event.message).is_equal("Test message")
assert_str(event.id).is_not_empty()
assert_int(event.level).is_equal(SentrySDK.LEVEL_DEBUG)
assert_str(event.logger).is_equal("custom-logger")
var event_id := SentrySDK.capture_event(event)
assert_str(event_id).is_not_empty()
assert_str(event_id).is_equal(event.id)
assert_str(event_id).is_equal(SentrySDK.get_last_event_id())
6 changes: 6 additions & 0 deletions src/register_types.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "runtime_config.h"
#include "sentry/disabled_event.h"
#include "sentry/native/native_event.h"
#include "sentry_event.h"
#include "sentry_logger.h"
#include "sentry_options.h"
#include "sentry_sdk.h"
Expand Down Expand Up @@ -38,6 +41,9 @@ void initialize_module(ModuleInitializationLevel p_level) {
GDREGISTER_INTERNAL_CLASS(RuntimeConfig);
GDREGISTER_CLASS(SentryUser);
GDREGISTER_CLASS(SentrySDK);
GDREGISTER_ABSTRACT_CLASS(SentryEvent);
GDREGISTER_INTERNAL_CLASS(NativeEvent);
GDREGISTER_INTERNAL_CLASS(DisabledEvent);
SentrySDK *sentry_singleton = memnew(SentrySDK);
Engine::get_singleton()->register_singleton("SentrySDK", SentrySDK::get_singleton());

Expand Down
49 changes: 49 additions & 0 deletions src/sentry/disabled_event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef DISABLED_EVENT_H
#define DISABLED_EVENT_H

#include "sentry_event.h"

// Event class that is used when the SDK is disabled.
class DisabledEvent : public SentryEvent {
GDCLASS(DisabledEvent, SentryEvent);

private:
String message;
String timestamp;
String logger;
sentry::Level level = sentry::Level::LEVEL_INFO;
String release;
String dist;
String environment;

protected:
static void _bind_methods() {}

public:
virtual String get_id() const override { return ""; }

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

virtual void set_timestamp(const String &p_timestamp) override { timestamp = p_timestamp; }
virtual String get_timestamp() const override { return timestamp; }

virtual String get_platform() const override { return ""; }

virtual void set_level(sentry::Level p_level) override { level = p_level; }
virtual sentry::Level get_level() const override { return level; }

virtual void set_logger(const String &p_logger) override { logger = p_logger; }
virtual String get_logger() const override { return logger; }

virtual void set_release(const String &p_release) override { release = p_release; }
virtual String get_release() const override { return release; }

virtual void set_dist(const String &p_dist) override { dist = p_dist; }
virtual String get_dist() const override { return dist; }

virtual void set_environment(const String &p_environment) override { environment = p_environment; }
virtual String get_environment() const override { return environment; }
};

#endif // DISABLED_EVENT_H
9 changes: 6 additions & 3 deletions src/sentry/disabled_sdk.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef DISABLED_SDK_H
#define DISABLED_SDK_H

#include "sentry/disabled_event.h"
#include "sentry/internal_sdk.h"

namespace sentry {
Expand All @@ -18,13 +19,15 @@ class DisabledSDK : public InternalSDK {

virtual void add_breadcrumb(const String &p_message, const String &p_category, Level p_level,
const String &p_type = "default", const Dictionary &p_data = Dictionary()) override {}
// TODO: Consider adding the following function.
// virtual void clear_breadcrumbs() = 0;

virtual String capture_message(const String &p_message, Level p_level, const String &p_logger = "") override { return ""; }
virtual String capture_message(const String &p_message, Level p_level = sentry::LEVEL_INFO, const String &p_logger = "") override { return ""; }
virtual String get_last_event_id() override { return ""; }
virtual String capture_error(const String &p_type, const String &p_value, Level p_level, const Vector<StackFrame> &p_frames) override { return ""; }

virtual Ref<SentryEvent> create_event() override { return memnew(DisabledEvent); }
virtual Ref<SentryEvent> create_message_event(const String &p_message, Level p_level = sentry::LEVEL_INFO, const String &p_logger = "") override { return memnew(DisabledEvent); };
virtual String capture_event(const Ref<SentryEvent> &p_event) override { return ""; }

virtual void initialize() override {}
};

Expand Down
5 changes: 5 additions & 0 deletions src/sentry/internal_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define INTERNAL_SDK_H

#include "sentry/level.h"
#include "sentry_event.h"
#include "sentry_user.h"

#include <godot_cpp/variant/dictionary.hpp>
Expand Down Expand Up @@ -44,6 +45,10 @@ class InternalSDK {
virtual String get_last_event_id() = 0;
virtual String capture_error(const String &p_type, const String &p_value, Level p_level, const Vector<StackFrame> &p_frames) = 0;

virtual Ref<SentryEvent> create_event() = 0;
virtual Ref<SentryEvent> create_message_event(const String &p_message, sentry::Level p_level, const String &p_logger = "") = 0;
virtual String capture_event(const Ref<SentryEvent> &p_event) = 0;

virtual void initialize() = 0;
virtual ~InternalSDK() = default;
};
Expand Down
6 changes: 5 additions & 1 deletion src/sentry/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace sentry {

CharString level_as_cstring(Level level) {
godot::CharString level_as_cstring(Level level) {
switch (level) {
case Level::LEVEL_DEBUG:
return "debug";
Expand All @@ -19,4 +19,8 @@ CharString level_as_cstring(Level level) {
}
}

godot::PropertyInfo make_level_enum_property(const godot::String &p_name) {
return godot::PropertyInfo(godot::Variant::INT, p_name, godot::PROPERTY_HINT_ENUM, "Debug,Info,Warning,Error,Fatal");
}

} // namespace sentry
11 changes: 7 additions & 4 deletions src/sentry/level.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#ifndef SENTRY_LEVEL_H
#define SENTRY_LEVEL_H

#include <godot_cpp/variant/char_string.hpp>

using namespace godot;
#include <godot_cpp/core/property_info.hpp>
#include <godot_cpp/variant/string.hpp>

namespace sentry {

// Represents the severity of events or breadcrumbs.
// In the public API, it is exposed as SentrySDK.Level enum.
// And as such, VariantCaster<SentrySDK::Level> is defined in sentry_sdk.h.
enum Level {
LEVEL_DEBUG = 0,
LEVEL_INFO = 1,
Expand All @@ -15,7 +17,8 @@ enum Level {
LEVEL_FATAL = 4
};

CharString level_as_cstring(Level level);
godot::CharString level_as_cstring(Level level);
godot::PropertyInfo make_level_enum_property(const godot::String &p_name);

} // namespace sentry

Expand Down
114 changes: 114 additions & 0 deletions src/sentry/native/native_event.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "native_event.h"

#include "sentry/level.h"
#include "sentry/native/native_util.h"

#include <sentry.h>

namespace {

inline void _sentry_value_set_or_remove_string_by_key(sentry_value_t value, const char *k, const String &v) {
if (v.is_empty()) {
sentry_value_remove_by_key(value, k);
} else {
sentry_value_set_by_key(value, k, sentry_value_new_string(v.utf8()));
}
}

} // unnamed namespace

String NativeEvent::get_id() const {
sentry_value_t id = sentry_value_get_by_key(native_event, "event_id");
return sentry_value_as_string(id);
}

void NativeEvent::set_message(const String &p_message) {
if (p_message.is_empty()) {
sentry_value_remove_by_key(native_event, "message");
} else {
sentry_value_t message = sentry_value_get_by_key(native_event, "message");
if (sentry_value_is_null(message)) {
message = sentry_value_new_object();
sentry_value_set_by_key(native_event, "message", message);
}
sentry_value_set_by_key(message, "formatted", sentry_value_new_string(p_message.utf8()));
}
}

String NativeEvent::get_message() const {
sentry_value_t message = sentry_value_get_by_key(native_event, "message");
sentry_value_t formatted = sentry_value_get_by_key(message, "formatted");
return sentry_value_as_string(formatted);
}

void NativeEvent::set_timestamp(const String &p_timestamp) {
_sentry_value_set_or_remove_string_by_key(native_event, "timestamp", p_timestamp);
}

String NativeEvent::get_timestamp() const {
sentry_value_t timestamp = sentry_value_get_by_key(native_event, "timestamp");
return sentry_value_as_string(timestamp);
}

String NativeEvent::get_platform() const {
sentry_value_t platform = sentry_value_get_by_key(native_event, "platform");
return sentry_value_as_string(platform);
}

void NativeEvent::set_level(sentry::Level p_level) {
sentry_value_set_by_key(native_event, "level",
sentry_value_new_string(sentry::native::level_to_cstring(p_level)));
}

sentry::Level NativeEvent::get_level() const {
sentry_value_t value = sentry_value_get_by_key(native_event, "level");
return sentry::native::cstring_to_level(sentry_value_as_string(value));
}

void NativeEvent::set_logger(const String &p_logger) {
_sentry_value_set_or_remove_string_by_key(native_event, "logger", p_logger);
}

String NativeEvent::get_logger() const {
sentry_value_t logger = sentry_value_get_by_key(native_event, "logger");
return sentry_value_as_string(logger);
}

void NativeEvent::set_release(const String &p_release) {
_sentry_value_set_or_remove_string_by_key(native_event, "release", p_release);
}

String NativeEvent::get_release() const {
sentry_value_t release = sentry_value_get_by_key(native_event, "release");
return sentry_value_as_string(release);
}

void NativeEvent::set_dist(const String &p_dist) {
_sentry_value_set_or_remove_string_by_key(native_event, "dist", p_dist);
}

String NativeEvent::get_dist() const {
sentry_value_t dist = sentry_value_get_by_key(native_event, "dist");
return sentry_value_as_string(dist);
}

void NativeEvent::set_environment(const String &p_environment) {
_sentry_value_set_or_remove_string_by_key(native_event, "environment", p_environment);
}

String NativeEvent::get_environment() const {
sentry_value_t environment = sentry_value_get_by_key(native_event, "environment");
return sentry_value_as_string(environment);
}

NativeEvent::NativeEvent(sentry_value_t p_native_event) {
native_event = p_native_event;
}

NativeEvent::NativeEvent() :
NativeEvent(sentry_value_new_event()) {
}

NativeEvent::~NativeEvent() {
sentry_value_decref(native_event);
}
Loading
Loading