feat(dashboard): track the UGC server like auth and chat

Online state with the time it came up, down/up alerts, a UGC column in the
health history, /api/servers (every server with its process memory and CPU)
and /api/servers/ugc, and UGC gauges for Prometheus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 09:23:16 -05:00
parent 63496f52ab
commit fe67b5635d
18 changed files with 349 additions and 64 deletions

View File

@@ -97,16 +97,20 @@ namespace {
// What the dashboard knows without asking the database: master's server list, its own connections, /proc
void AddLive(MetricsFormat::Writer& w) {
std::vector<WorldInstanceInfo> worlds;
bool authUp = false, chatUp = false;
bool authUp = false, chatUp = false, ugcEnabled = false, ugcUp = false;
{
std::lock_guard lock(ServerState::g_StatusMutex);
worlds = ServerState::g_WorldInstances;
authUp = ServerState::g_AuthStatus.online;
chatUp = ServerState::g_ChatStatus.online;
ugcEnabled = ServerState::g_UgcEnabled;
ugcUp = ServerState::g_UgcStatus.online;
}
w.Add("darkflame_master_connected", "Whether the dashboard is connected to the master server", "gauge", Game::server && Game::server->GetIsConnectedToMaster() ? 1 : 0);
w.Add("darkflame_auth_up", "Whether the auth server is up, as master last reported", "gauge", authUp ? 1 : 0);
w.Add("darkflame_chat_up", "Whether the chat server is up, as master last reported", "gauge", chatUp ? 1 : 0);
w.Add("darkflame_ugc_enabled", "Whether master starts the UGC server (enable_ugc_server)", "gauge", ugcEnabled ? 1 : 0);
w.Add("darkflame_ugc_up", "Whether the UGC server is up, as master last reported", "gauge", ugcUp ? 1 : 0);
uint32_t players = 0;
std::map<uint32_t, std::pair<std::string, std::pair<uint32_t, uint32_t>>> zones; // id -> name, {instances, players}
@@ -215,6 +219,20 @@ namespace {
w.Add("darkflame_moderation_queue", "", "gauge", { {"queue", "player_reports"} }, db->CountPlayerReports(q));
});
// The UGC server's work list: models and modular builds by processing state
ok &= Timed(w, "ugc", [&] {
w.Declare("darkflame_ugc_items", "Player models (model) and cars and rockets (modular) by UGC processing state", "gauge");
const auto add = [&](const char* kind, const std::vector<std::pair<IUgc::eProcessState, uint64_t>>& rows) {
std::map<std::string, uint64_t> states{ {"pending", 0}, {"done", 0}, {"failed", 0} };
for (const auto& [state, count] : rows) {
states[state == IUgc::eProcessState::PENDING ? "pending" : state == IUgc::eProcessState::DONE ? "done" : "failed"] += count;
}
for (const auto& [state, count] : states) w.Add("darkflame_ugc_items", "", "gauge", { {"kind", kind}, {"state", state} }, static_cast<double>(count));
};
add("model", db->GetUgcProcessCounts());
add("modular", db->GetModularBuildProcessCounts());
});
ok &= Timed(w, "strikes", [&] {
w.Add("darkflame_active_strikes", "Strikes that still count, all accounts together", "gauge", db->CountActiveStrikes(0, Strikes::CountsSince()));
});