AeThex-Engine-Core/engine/modules/aethex_cloud/aethex_telemetry.cpp

125 lines
4 KiB
C++

/**************************************************************************/
/* aethex_telemetry.cpp */
/**************************************************************************/
/* AeThex Engine */
/* https://aethex.dev */
/**************************************************************************/
#include "aethex_telemetry.h"
#include "aethex_cloud.h"
#include "core/io/http_client.h"
#include "core/os/os.h"
#include "core/version.h"
void AethexTelemetry::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &AethexTelemetry::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &AethexTelemetry::is_enabled);
ClassDB::bind_method(D_METHOD("track_event", "event_name", "properties"), &AethexTelemetry::track_event, DEFVAL(Dictionary()));
ClassDB::bind_method(D_METHOD("track_screen", "screen_name"), &AethexTelemetry::track_screen);
ClassDB::bind_method(D_METHOD("track_error", "error", "stack_trace"), &AethexTelemetry::track_error, DEFVAL(""));
ClassDB::bind_method(D_METHOD("report_crash", "message", "stack_trace", "context"), &AethexTelemetry::report_crash, DEFVAL(Dictionary()));
ClassDB::bind_method(D_METHOD("flush"), &AethexTelemetry::flush);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
}
AethexTelemetry::AethexTelemetry() {
}
AethexTelemetry::~AethexTelemetry() {
// Flush remaining events on shutdown
if (!event_buffer.is_empty()) {
flush();
}
}
void AethexTelemetry::set_cloud(AethexCloud *p_cloud) {
cloud = p_cloud;
}
void AethexTelemetry::set_enabled(bool p_enabled) {
enabled = p_enabled;
}
bool AethexTelemetry::is_enabled() const {
return enabled;
}
void AethexTelemetry::track_event(const String &p_event_name, const Dictionary &p_properties) {
if (!enabled || !cloud) {
return;
}
Dictionary event;
event["name"] = p_event_name;
event["properties"] = p_properties;
event["timestamp"] = Time::get_singleton()->get_datetime_string_from_system(true);
event["platform"] = OS::get_singleton()->get_name();
event["engineVersion"] = VERSION_FULL_CONFIG;
event_buffer.push_back(event);
// Auto-flush if buffer is full
if (event_buffer.size() >= buffer_size) {
flush();
}
}
void AethexTelemetry::track_screen(const String &p_screen_name) {
Dictionary props;
props["screen"] = p_screen_name;
track_event("screen_view", props);
}
void AethexTelemetry::track_error(const String &p_error, const String &p_stack_trace) {
Dictionary props;
props["error"] = p_error;
props["stack_trace"] = p_stack_trace;
track_event("error", props);
}
void AethexTelemetry::report_crash(const String &p_message, const String &p_stack_trace, const Dictionary &p_context) {
if (!cloud) {
return;
}
Dictionary data;
data["message"] = p_message;
data["stackTrace"] = p_stack_trace;
data["context"] = p_context;
data["platform"] = OS::get_singleton()->get_name();
data["engineVersion"] = VERSION_FULL_CONFIG;
data["timestamp"] = Time::get_singleton()->get_datetime_string_from_system(true);
// Crash reports are sent immediately, not buffered
cloud->make_request("/api/telemetry/crash", HTTPClient::METHOD_POST, data);
}
void AethexTelemetry::flush() {
if (!cloud || event_buffer.is_empty()) {
return;
}
// Send all buffered events
for (int i = 0; i < event_buffer.size(); i++) {
cloud->make_request("/api/telemetry/event", HTTPClient::METHOD_POST, event_buffer[i]);
}
event_buffer.clear();
time_since_flush = 0.0;
}
void AethexTelemetry::process(double p_delta) {
if (!enabled) {
return;
}
time_since_flush += p_delta;
// Auto-flush periodically
if (time_since_flush >= flush_interval && !event_buffer.is_empty()) {
flush();
}
}