d291dcdc74
agent_api (HTTP server), agent_log (structured logging), agent_events (event bus), agent_console (GameConsole), agent_replay (snapshots), agent_vision (depth/segmentation), agent_fbx (bone remapping), agent_auth (multi-agent), agent_analytics (feature flags + tracking) All modules compile clean with mono. Binary uploaded to S3 v1.0.0. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
138 lines
4.4 KiB
C++
138 lines
4.4 KiB
C++
#pragma once
|
|
|
|
#include "core/object/class_db.h"
|
|
#include "core/object/object.h"
|
|
#include "core/os/mutex.h"
|
|
#include "core/string/ustring.h"
|
|
#include "core/variant/dictionary.h"
|
|
#include "core/variant/array.h"
|
|
|
|
// PostHog-like analytics + feature flags, built into the engine.
|
|
// Self-hosted: events stay local (JSONL) or are forwarded to a configured endpoint.
|
|
|
|
class AgentAnalytics : public Object {
|
|
GDCLASS(AgentAnalytics, Object);
|
|
|
|
static AgentAnalytics *singleton;
|
|
|
|
public:
|
|
static AgentAnalytics *get_singleton() { return singleton; }
|
|
|
|
struct AnalyticsEvent {
|
|
uint64_t id = 0;
|
|
uint64_t timestamp_msec = 0;
|
|
String event_name;
|
|
String distinct_id; // User/session/agent ID.
|
|
Dictionary properties;
|
|
};
|
|
|
|
struct FeatureFlag {
|
|
String key;
|
|
bool enabled = false;
|
|
Variant value; // Can be bool, string, int, etc.
|
|
Dictionary conditions; // Targeting rules.
|
|
float rollout_percentage = 100.0f;
|
|
String description;
|
|
};
|
|
|
|
struct Funnel {
|
|
String name;
|
|
Array steps; // Array of event names.
|
|
Dictionary step_counts; // step_name -> count.
|
|
};
|
|
|
|
private:
|
|
// Event storage.
|
|
static constexpr int EVENT_BUFFER_SIZE = 50000;
|
|
Vector<AnalyticsEvent> events;
|
|
uint64_t next_event_id = 1;
|
|
Mutex events_mutex;
|
|
|
|
// Feature flags.
|
|
HashMap<String, FeatureFlag> feature_flags;
|
|
Mutex flags_mutex;
|
|
|
|
// Session tracking.
|
|
String current_session_id;
|
|
String current_distinct_id;
|
|
uint64_t session_start = 0;
|
|
|
|
// Funnels.
|
|
HashMap<String, Funnel> funnels;
|
|
|
|
// File sink for event persistence.
|
|
bool file_sink_enabled = false;
|
|
String file_sink_path;
|
|
|
|
// Remote endpoint (optional — send events to external analytics).
|
|
String remote_endpoint;
|
|
String remote_api_key;
|
|
bool remote_enabled = false;
|
|
|
|
// A/B test groups.
|
|
HashMap<String, String> experiment_groups; // experiment_key -> group_name
|
|
|
|
void _write_event_to_file(const AnalyticsEvent &p_event);
|
|
void _send_event_to_remote(const AnalyticsEvent &p_event);
|
|
bool _evaluate_flag_conditions(const FeatureFlag &p_flag, const Dictionary &p_context);
|
|
String _generate_session_id();
|
|
|
|
protected:
|
|
static void _bind_methods();
|
|
|
|
public:
|
|
AgentAnalytics();
|
|
~AgentAnalytics();
|
|
|
|
// --- Event Tracking (PostHog capture equivalent) ---
|
|
void capture(const String &p_event, const Dictionary &p_properties = Dictionary());
|
|
void identify(const String &p_distinct_id, const Dictionary &p_properties = Dictionary());
|
|
void alias(const String &p_alias, const String &p_distinct_id);
|
|
|
|
// Session management.
|
|
void start_session(const String &p_distinct_id = "");
|
|
void end_session();
|
|
String get_session_id() const { return current_session_id; }
|
|
|
|
// Page/screen views (game equivalent: level/scene tracking).
|
|
void screen(const String &p_screen_name, const Dictionary &p_properties = Dictionary());
|
|
|
|
// --- Feature Flags ---
|
|
bool is_feature_enabled(const String &p_key, const Dictionary &p_context = Dictionary());
|
|
Variant get_feature_flag(const String &p_key, const Variant &p_default = Variant());
|
|
void set_feature_flag(const String &p_key, bool p_enabled, const Variant &p_value = Variant(), float p_rollout = 100.0f, const String &p_description = "");
|
|
void remove_feature_flag(const String &p_key);
|
|
Array get_all_flags() const;
|
|
bool load_flags_from_file(const String &p_path = "res://feature_flags.json");
|
|
bool save_flags_to_file(const String &p_path = "res://feature_flags.json");
|
|
|
|
// --- A/B Testing ---
|
|
String get_experiment_group(const String &p_experiment_key, const Array &p_groups);
|
|
Dictionary get_experiment_results(const String &p_experiment_key);
|
|
|
|
// --- Funnels ---
|
|
void define_funnel(const String &p_name, const Array &p_steps);
|
|
Dictionary get_funnel_stats(const String &p_name);
|
|
|
|
// --- Query ---
|
|
Array get_events(int p_count = 100, const String &p_event_name = "", uint64_t p_since_msec = 0);
|
|
int get_event_count(const String &p_event_name = "");
|
|
Dictionary get_event_counts_by_name(); // {event_name: count}
|
|
|
|
// --- Configuration ---
|
|
void enable_file_sink(const String &p_path = "user://analytics.jsonl");
|
|
void disable_file_sink();
|
|
void set_remote_endpoint(const String &p_endpoint, const String &p_api_key);
|
|
void disable_remote();
|
|
void set_distinct_id(const String &p_id) { current_distinct_id = p_id; }
|
|
String get_distinct_id() const { return current_distinct_id; }
|
|
|
|
// --- Super Properties (attached to every event) ---
|
|
Dictionary super_properties;
|
|
void set_super_property(const String &p_key, const Variant &p_value);
|
|
void remove_super_property(const String &p_key);
|
|
void clear_super_properties();
|
|
|
|
void clear();
|
|
};
|