fix: follow main's log folders in the dashboard and UGC server

Servers now log to logs/<Server>/ (worlds to logs/WorldServer/<zone>/<clone>/) with the start time in the file name.
The dashboard and UGC server log the same way, and the System Log page and log search read the whole folder tree
instead of only the top of logs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 09:39:53 -05:00
parent f7eee4a395
commit d835e18c92
4 changed files with 13 additions and 7 deletions

View File

@@ -350,7 +350,8 @@ int main(int argc, char** argv) {
Game::config = new dConfig("dashboardconfig.ini"); Game::config = new dConfig("dashboardconfig.ini");
// Setup logger // Setup logger
Server::SetupLogger("DashboardServer"); // Like the other servers: logs/DashboardServer/DashboardServer_<start time>.log
Server::SetupLogger("DashboardServer_" + std::to_string(time(nullptr)), "DashboardServer");
if (!Game::logger) return EXIT_FAILURE; if (!Game::logger) return EXIT_FAILURE;
Game::config->LogSettings(); Game::config->LogSettings();

View File

@@ -228,12 +228,14 @@ namespace {
uintmax_t size{}; uintmax_t size{};
}; };
// Every log file, by server (the name before the start time, e.g. "WorldServer_1200_3"), newest first // Every log file, by server (the name before the start time, e.g. "WorldServer_1200_0_3"), newest first. Servers
// write into their own folders (logs/WorldServer/<zone>/<clone>/, logs/AuthServer/, ...), so the whole tree is read.
std::map<std::string, std::vector<LogFile>> LogFilesByServer() { std::map<std::string, std::vector<LogFile>> LogFilesByServer() {
std::map<std::string, std::vector<LogFile>> byServer; std::map<std::string, std::vector<LogFile>> byServer;
const auto logDir = BinaryPathFinder::GetBinaryDir() / "logs"; const auto logDir = BinaryPathFinder::GetBinaryDir() / "logs";
std::error_code ec; std::error_code ec;
for (const auto& entry : std::filesystem::directory_iterator(logDir, ec)) { for (auto it = std::filesystem::recursive_directory_iterator(logDir, ec); !ec && it != std::filesystem::recursive_directory_iterator(); it.increment(ec)) {
const auto& entry = *it;
if (!entry.is_regular_file(ec) || entry.path().extension() != ".log") continue; if (!entry.is_regular_file(ec) || entry.path().extension() != ".log") continue;
const auto stem = entry.path().stem().string(); const auto stem = entry.path().stem().string();
const auto written = std::chrono::duration_cast<std::chrono::seconds>( const auto written = std::chrono::duration_cast<std::chrono::seconds>(

View File

@@ -135,7 +135,7 @@ void RegisterServerRoutes() {
Route(eHTTPMethod::GET, "/api/crash_dumps/:name", Perm("logs_system"), "Download a crash dump", Route(eHTTPMethod::GET, "/api/crash_dumps/:name", Perm("logs_system"), "Download a crash dump",
[](HTTPReply& reply, const HTTPContext& context) { [](HTTPReply& reply, const HTTPContext& context) {
const std::string name(PathSegment(context.originalPath, 2)); // crash_World_123.log: case matters const std::string name(PathSegment(context.originalPath, 2)); // Crash_WorldServer_..._123.log: case matters
const auto folder = DumpFolder(); const auto folder = DumpFolder();
if (folder.empty() || !PlainFileName(name)) return JsonError(reply, eHTTPStatusCode::NOT_FOUND, "Not found"); if (folder.empty() || !PlainFileName(name)) return JsonError(reply, eHTTPStatusCode::NOT_FOUND, "Not found");
std::error_code ec; std::error_code ec;
@@ -159,10 +159,12 @@ void RegisterServerRoutes() {
const auto folder = LogFolder(); const auto folder = LogFolder();
const auto requestId = PlayerActions::Begin(context.accountId, std::chrono::minutes(5)); const auto requestId = PlayerActions::Begin(context.accountId, std::chrono::minutes(5));
Background::Run("log_search:" + std::to_string(requestId), [folder, query, server, perServer](GameDatabase&) -> nlohmann::json { Background::Run("log_search:" + std::to_string(requestId), [folder, query, server, perServer](GameDatabase&) -> nlohmann::json {
// Newest files of each server (file names: <Server>_<time>.log) // Newest files of each server (file names: <Server>_..._<time>.log, in the server's own folder under logs/)
std::map<std::string, std::vector<fs::path>> byServer; std::map<std::string, std::vector<fs::path>> byServer;
std::error_code ec; std::error_code ec;
for (const auto& entry : fs::directory_iterator(folder, ec)) { for (auto it = fs::recursive_directory_iterator(folder, ec); !ec && it != fs::recursive_directory_iterator(); it.increment(ec)) {
const auto& entry = *it;
if (!entry.is_regular_file(ec)) continue;
const auto name = entry.path().filename().string(); const auto name = entry.path().filename().string();
if (!name.ends_with(".log")) continue; if (!name.ends_with(".log")) continue;
const auto serverName = name.substr(0, name.find('_')); const auto serverName = name.substr(0, name.find('_'));

View File

@@ -259,7 +259,8 @@ int main(int argc, char** argv) {
return MakeFromCommandLine(argv[1], argv[2], argv[3]); return MakeFromCommandLine(argv[1], argv[2], argv[3]);
} }
Server::SetupLogger("UgcServer"); // Like the other servers: logs/UgcServer/UgcServer_<start time>.log
Server::SetupLogger("UgcServer_" + std::to_string(time(nullptr)), "UgcServer");
if (!Game::logger) return EXIT_FAILURE; if (!Game::logger) return EXIT_FAILURE;
Game::config->LogSettings(); Game::config->LogSettings();
LOG("Starting UGC Server"); LOG("Starting UGC Server");