feat(dashboard): the UGC server on the Diagnostics page

When the UGC server is enabled, the Diagnostics page shows it: online or
unreachable, busy workers and queue, CPU against its limit, memory and
the jobs' estimated memory against its budget, stored files, what it
made and failed since it started, the last makes, and how many models
and cars/rockets are made, waiting, failed or empty. Refreshed every 10
seconds from /api/diagnostics/ugc (health_view).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 21:20:20 -05:00
parent e8fdf64186
commit 8b64bf08c6
2 changed files with 61 additions and 0 deletions

View File

@@ -7,6 +7,7 @@
#include <set>
#include "CDClientDatabase.h"
#include "ServerState.h"
#include "Database.h"
#include "UgcIconParams.h"
#include "NifFile.h"
@@ -433,6 +434,29 @@ namespace UgcRoutes {
}, WorkerPool::ePriority::URGENT);
});
Route(eHTTPMethod::GET, "/api/diagnostics/ugc", Perm("health_view"),
"The UGC server for the Diagnostics page: {enabled, online, status (its /status: queue, workers, CPU, memory, limits, "
"throttling, recent makes) or error, counts: {model, modular} per state}",
[](HTTPReply& reply, const HTTPContext& context) {
bool enabled = false, online = false;
{
std::lock_guard lock(ServerState::g_StatusMutex);
enabled = ServerState::g_UgcEnabled;
online = ServerState::g_UgcStatus.online;
}
const auto base = InternalUrl();
Workers::Reply(reply, context, false, [base, enabled, online](HTTPReply& out) {
nlohmann::json body = { { "success", true }, { "enabled", enabled }, { "online", online },
{ "counts", { { "model", Counts(Database::Get()->GetUgcProcessCounts()) }, { "modular", Counts(Database::Get()->GetModularBuildProcessCounts()) } } } };
if (enabled) {
const auto fetched = CachedGet(base + "/status", eCache::STATUS);
if (fetched->status == 200) body["status"] = nlohmann::json::parse(fetched->body, nullptr, false);
else body["error"] = fetched->status == 0 ? fetched->error : "answered " + std::to_string(fetched->status);
}
JsonReply(out, eHTTPStatusCode::OK, body);
}, WorkerPool::ePriority::URGENT);
});
Route(eHTTPMethod::GET, "/api/ugc/files/:kind/:id/:file", Perm("properties_view"),
"A file the UGC server made (fetched from ugc_internal_url): icon.png, model.nif, model.noao.nif (before the lighting bake), "
"stats.json, or previous.<one of those> (the version before it was made again). 408 while it's being made",