Add statuses, status messages

This commit is contained in:
Lion Kortlepel 2021-12-06 13:17:54 +01:00
parent 0f74eca2ee
commit a1335e8c7d
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
13 changed files with 126 additions and 24 deletions

View File

@ -97,15 +97,15 @@ public:
using SystemStatusMap = std::unordered_map<std::string /* system name */, Status /* status */>;
static const SystemStatusMap& GetSubsystemStatuses() {
std::unique_lock Lock(mSystemStatusMapMutex);
return mSystemStatusMap;
}
static void SetSubsystemStatus(const std::string& Subsystem, Status status) {
mSystemStatusMap[Subsystem] = status;
}
static void SetSubsystemStatus(const std::string& Subsystem, Status status);
private:
static inline SystemStatusMap mSystemStatusMap {};
static inline std::mutex mSystemStatusMapMutex {};
static inline std::string mPPS;
static inline std::unique_ptr<TConsole> mConsole;
static inline std::mutex mShutdownHandlersMutex {};

View File

@ -73,7 +73,24 @@ bool Application::IsOutdated(const Version& Current, const Version& Newest) {
}
}
void Application::SetSubsystemStatus(const std::string& Subsystem, Status status) {
switch (status) {
case Status::Good:
beammp_trace("Subsystem '" + Subsystem + "': Good");
break;
case Status::Bad:
beammp_trace("Subsystem '" + Subsystem + "': Bad");
break;
case Status::Starting:
beammp_trace("Subsystem '" + Subsystem + "': Starting");
break;
}
std::unique_lock Lock(mSystemStatusMapMutex);
mSystemStatusMap[Subsystem] = status;
}
void Application::CheckForUpdates() {
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Starting);
// checks current version against latest version
std::regex VersionRegex { R"(\d+\.\d+\.\d+\n*)" };
auto Response = Http::GET(GetBackendHostname(), 443, "/v/s");
@ -87,12 +104,14 @@ void Application::CheckForUpdates() {
} else {
beammp_info("Server up-to-date!");
}
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good);
} else {
beammp_warn("Unable to fetch version from backend.");
beammp_trace("got " + Response);
auto Lock = Sentry.CreateExclusiveContext();
Sentry.SetContext("get-response", { { "response", Response } });
Sentry.LogError("failed to get server version", _file_basename, _line);
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad);
}
}

View File

@ -264,6 +264,7 @@ void Http::Server::SetupEnvironment() {
}
Http::Server::THttpServerInstance::THttpServerInstance() {
Application::SetSubsystemStatus("HTTPServer", Application::Status::Starting);
mThread = std::thread(&Http::Server::THttpServerInstance::operator(), this);
mThread.detach();
}
@ -279,5 +280,6 @@ void Http::Server::THttpServerInstance::operator()() {
res.set_content("0", "text/plain");
res.status = 200;
});
Application::SetSubsystemStatus("HTTPServer", Application::Status::Good);
HttpLibServerInstance.listen("0.0.0.0", Application::Settings.HTTPServerPort);
}

View File

@ -31,6 +31,7 @@ static constexpr std::string_view StrHTTPServerPort = "HTTPServerPort";
TConfig::TConfig(const std::string& ConfigFileName)
: mConfigFileName(ConfigFileName) {
Application::SetSubsystemStatus("Config", Application::Status::Starting);
if (!fs::exists(mConfigFileName) || !fs::is_regular_file(mConfigFileName)) {
beammp_info("No config file found! Generating one...");
CreateConfigFile(mConfigFileName);
@ -115,6 +116,7 @@ void TConfig::CreateConfigFile(std::string_view name) {
ofs.close();
} else {
beammp_error("Couldn't create " + std::string(name) + ". Check permissions, try again, and contact support if it continues not to work.");
Application::SetSubsystemStatus("Config", Application::Status::Bad);
mFailed = true;
}
}
@ -151,6 +153,7 @@ void TConfig::ParseFromFile(std::string_view name) {
} catch (const std::exception& err) {
beammp_error("Error parsing config file value: " + std::string(err.what()));
mFailed = true;
Application::SetSubsystemStatus("Config", Application::Status::Bad);
return;
}
PrintDebug();
@ -161,7 +164,13 @@ void TConfig::ParseFromFile(std::string_view name) {
// all good so far, let's check if there's a key
if (Application::Settings.Key.empty()) {
beammp_error("No AuthKey specified in the \"" + std::string(mConfigFileName) + "\" file. Please get an AuthKey, enter it into the config file, and restart this server.");
Application::SetSubsystemStatus("Config", Application::Status::Bad);
mFailed = true;
return;
}
Application::SetSubsystemStatus("Config", Application::Status::Good);
if (Application::Settings.Key.size() != 36) {
beammp_warn("AuthKey specified is the wrong length and likely isn't valid.");
}
}

View File

@ -247,6 +247,34 @@ void TConsole::Command_Status(const std::string&) {
return true;
});
size_t SystemsStarting = 0;
size_t SystemsGood = 0;
size_t SystemsBad = 0;
std::string SystemsBadList {};
std::string SystemsGoodList {};
std::string SystemsStartingList {};
auto Statuses = Application::GetSubsystemStatuses();
for (const auto& NameStatusPair : Statuses) {
switch (NameStatusPair.second) {
case Application::Status::Good:
SystemsGood++;
SystemsGoodList += NameStatusPair.first + ", ";
break;
case Application::Status::Bad:
SystemsBad++;
SystemsBadList += NameStatusPair.first + ", ";
break;
case Application::Status::Starting:
SystemsStarting++;
SystemsStartingList += NameStatusPair.first + ", ";
break;
}
}
// remove ", " at the end
SystemsBadList = SystemsBadList.substr(0, SystemsBadList.size() - 2);
SystemsGoodList = SystemsGoodList.substr(0, SystemsGoodList.size() - 2);
SystemsStartingList = SystemsStartingList.substr(0, SystemsStartingList.size() - 2);
auto ElapsedTime = mLuaEngine->Server().UptimeTimer.GetElapsedTime();
Status << "BeamMP-Server Status:\n"
@ -262,6 +290,11 @@ void TConsole::Command_Status(const std::string&) {
<< "\t\tStates: " << mLuaEngine->GetLuaStateCount() << "\n"
<< "\t\tEvent timers: " << mLuaEngine->GetTimedEventsCount() << "\n"
<< "\t\tEvent handlers: " << mLuaEngine->GetRegisteredEventHandlerCount() << "\n"
<< "\tSubsystems:\n"
<< "\t\tGood/Starting/Bad: " << SystemsGood << "/" << SystemsStarting << "/" << SystemsBad << "\n"
<< "\t\tGood: [ " << SystemsGoodList << " ]\n"
<< "\t\tStarting: [ " << SystemsStartingList << " ]\n"
<< "\t\tBad: [ " << SystemsBadList << " ]\n"
<< "";
Application::Console().WriteRaw(Status.str());

View File

@ -6,7 +6,6 @@
#include <sstream>
void THeartbeatThread::operator()() {
return;/*
RegisterThread("Heartbeat");
std::string Body;
std::string T;
@ -55,20 +54,28 @@ void THeartbeatThread::operator()() {
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
beammp_trace("got " + T + " from backend");
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
beammp_warn("Backend system refused server! Server will not show in the public server list.");
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
isAuth = false;
SentryReportError(Application::GetBackup2Hostname() + Target, ResponseCode);
} else {
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
}
} else {
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
}
} else {
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
}
if (!isAuth) {
@ -83,7 +90,6 @@ void THeartbeatThread::operator()() {
// SocketIO::Get().SetAuthenticated(isAuth);
}
*/
}
std::string THeartbeatThread::GenerateCall() {
@ -108,6 +114,7 @@ std::string THeartbeatThread::GenerateCall() {
THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& Server)
: mResourceManager(ResourceManager)
, mServer(Server) {
Application::SetSubsystemStatus("Heartbeat", Application::Status::Starting);
Application::RegisterShutdownHandler([&] {
if (mThread.joinable()) {
mShutdown = true;

View File

@ -16,6 +16,7 @@ TLuaEngine* LuaAPI::MP::Engine;
TLuaEngine::TLuaEngine()
: mPluginMonitor(fs::path(Application::Settings.Resource) / "Server", *this, mShutdown) {
Application::SetSubsystemStatus("LuaEngine", Application::Status::Starting);
LuaAPI::MP::Engine = this;
if (!fs::exists(Application::Settings.Resource)) {
fs::create_directory(Application::Settings.Resource);
@ -36,6 +37,7 @@ TLuaEngine::TLuaEngine()
void TLuaEngine::operator()() {
RegisterThread("LuaEngine");
Application::SetSubsystemStatus("LuaEngine", Application::Status::Good);
// lua engine main thread
CollectAndInitPlugins();
// now call all onInit's

View File

@ -11,6 +11,8 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R
: mServer(Server)
, mPPSMonitor(PPSMonitor)
, mResourceManager(ResourceManager) {
Application::SetSubsystemStatus("TCPNetwork", Application::Status::Starting);
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Starting);
Application::RegisterShutdownHandler([&] {
beammp_debug("Kicking all players due to shutdown");
Server.ForEachClient([&](std::weak_ptr<TClient> client) -> bool {
@ -56,10 +58,10 @@ void TNetwork::UDPServerMain() {
if (bind(mUDPSock, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) {
beammp_error("bind() failed: " + GetPlatformAgnosticErrorString());
std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1);
exit(-1); // TODO: Wtf.
// return;
}
Application::SetSubsystemStatus("UDPNetwork", Application::Status::Good);
beammp_info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ")
+ std::to_string(Application::Settings.MaxPlayers) + (" Clients"));
while (!mShutdown) {
@ -123,7 +125,7 @@ void TNetwork::TCPServerMain() {
if (bind(Listener, (sockaddr*)&addr, sizeof(addr)) != 0) {
beammp_error("bind() failed: " + GetPlatformAgnosticErrorString());
std::this_thread::sleep_for(std::chrono::seconds(5));
exit(-1);
exit(-1); // TODO: Wtf.
}
if (Listener == -1) {
beammp_error("Invalid listening socket");
@ -134,6 +136,7 @@ void TNetwork::TCPServerMain() {
// FIXME leak Listener
return;
}
Application::SetSubsystemStatus("TCPNetwork", Application::Status::Good);
beammp_info(("Vehicle event network online"));
do {
try {

View File

@ -4,6 +4,7 @@
TPPSMonitor::TPPSMonitor(TServer& Server)
: mServer(Server) {
Application::SetSubsystemStatus("PPSMonitor", Application::Status::Starting);
Application::SetPPS("-");
Application::RegisterShutdownHandler([&] {
if (mThread.joinable()) {
@ -22,6 +23,7 @@ void TPPSMonitor::operator()() {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
beammp_debug("PPSMonitor starting");
Application::SetSubsystemStatus("PPSMonitor", Application::Status::Good);
std::vector<std::shared_ptr<TClient>> TimedOutClients;
while (!mShutdown) {
std::this_thread::sleep_for(std::chrono::seconds(1));

View File

@ -6,6 +6,7 @@
namespace fs = std::filesystem;
TResourceManager::TResourceManager() {
Application::SetSubsystemStatus("ResourceManager", Application::Status::Starting);
std::string Path = Application::Settings.Resource + "/Client";
if (!fs::exists(Path))
fs::create_directories(Path);
@ -29,4 +30,6 @@ TResourceManager::TResourceManager() {
if (mModsLoaded)
beammp_info("Loaded " + std::to_string(mModsLoaded) + " Mods");
Application::SetSubsystemStatus("ResourceManager", Application::Status::Good);
}

View File

@ -55,6 +55,7 @@ void TSentry::SetupUser() {
if (!mValid) {
return;
}
Application::SetSubsystemStatus("Sentry", Application::Status::Good);
sentry_value_t user = sentry_value_new_object();
if (Application::Settings.Key.size() == 36) {
sentry_value_set_by_key(user, "id", sentry_value_new_string(Application::Settings.Key.c_str()));

View File

@ -17,6 +17,7 @@ namespace json = rapidjson;
TServer::TServer(const std::vector<std::string_view>& Arguments) {
beammp_info("BeamMP Server v" + Application::ServerVersionString());
Application::SetSubsystemStatus("Server", Application::Status::Starting);
if (Arguments.size() > 1) {
Application::Settings.CustomIP = Arguments[0];
size_t n = std::count(Application::Settings.CustomIP.begin(), Application::Settings.CustomIP.end(), '.');
@ -28,6 +29,7 @@ TServer::TServer(const std::vector<std::string_view>& Arguments) {
beammp_info("server started with custom IP");
}
}
Application::SetSubsystemStatus("Server", Application::Status::Good);
}
void TServer::RemoveClient(const std::weak_ptr<TClient>& WeakClientPtr) {

View File

@ -78,6 +78,7 @@ int main(int argc, char** argv) {
int BeamMPServerMain(MainArguments Arguments) {
setlocale(LC_ALL, "C");
Application::InitializeConsole();
Application::SetSubsystemStatus("Main", Application::Status::Starting);
SetupSignalHandlers();
@ -161,17 +162,35 @@ int BeamMPServerMain(MainArguments Arguments) {
Http::Server::THttpServerInstance HttpServerInstance {};
}
Application::SetSubsystemStatus("Main", Application::Status::Good);
RegisterThread("Main(Waiting)");
bool FullyStarted = false;
while (!Shutdown) {
if (!FullyStarted) {
FullyStarted = true;
bool WithErrors = false;
std::string SystemsBadList {};
auto Statuses = Application::GetSubsystemStatuses();
for (const auto& NameStatusPair : Statuses) {
if (NameStatusPair.second != Application::Status::Good) {
beammp_info("not good: " + NameStatusPair.first);
if (NameStatusPair.second == Application::Status::Starting) {
FullyStarted = false;
} else if (NameStatusPair.second == Application::Status::Bad) {
SystemsBadList += NameStatusPair.first + ", ";
WithErrors = true;
}
}
while (!Shutdown) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// remove ", "
SystemsBadList = SystemsBadList.substr(0, SystemsBadList.size() - 2);
if (FullyStarted) {
if (!WithErrors) {
beammp_info("ALL SYSTEMS STARTED SUCCESSFULLY, EVERYTHING IS OKAY");
} else {
beammp_error("STARTUP NOT SUCCESSFUL, SYSTEMS " + SystemsBadList + " HAD ERRORS. THIS MAY OR MAY NOT CAUSE ISSUES.");
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
beammp_info("Shutdown.");
return 0;