diff --git a/.gitmodules b/.gitmodules index 051942e..b19591f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "libs/json"] path = libs/json url = https://github.com/nlohmann/json.git +[submodule "libs/spdlog"] + path = libs/spdlog + url = https://github.com/gabime/spdlog.git diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 444b296..78c94de 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -5,6 +5,7 @@ + diff --git a/CMakeLists.txt b/CMakeLists.txt index 005e8e9..f606364 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,17 @@ include_directories(libs/json/include) add_subdirectory(libs/yaml-cpp) include_directories(libs/yaml-cpp/include) +# Include AMQP-CPP (RabbitMQ). +add_subdirectory(libs/AMQP-CPP) +include_directories(libs/AMQP-CPP/include) + +# Include spdlog. +add_subdirectory(libs/spdlog) +include_directories(libs/spdlog/include) + +# Include Prometheus metrics. +find_package(prometheus-cpp CONFIG REQUIRED) + set(ARDOS_WANT_DB_SERVER ON CACHE BOOL "If on, Ardos will be built with the Database Server component.") if (ARDOS_WANT_DB_SERVER) # Include MongoDB driver. @@ -42,13 +53,6 @@ if (ARDOS_WANT_DB_SERVER) add_definitions(-DARDOS_WANT_DB_SERVER) endif () -# Include AMQP-CPP (RabbitMQ). -add_subdirectory(libs/AMQP-CPP) -include_directories(libs/AMQP-CPP/include) - -# Include Prometheus metrics. -find_package(prometheus-cpp CONFIG REQUIRED) - # Optimize windows build. if (WIN32) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) diff --git a/config.example.yml b/config.example.yml index b86c1c7..a3e24b4 100644 --- a/config.example.yml +++ b/config.example.yml @@ -1,6 +1,6 @@ -# Console output log level. -# Options are verbose, info, warn, error or none. -log-level: verbose +# Global console output log level. +# Options are debug, info, warn, error or none. +log-level: info # DC (Distributed Class) file paths. # These should be kept in-sync globally. @@ -42,6 +42,10 @@ uberdogs: # Web Panel configuration. # Can be accessed via the Ardos Web panel for debugging. web-panel: + # Components can have their own individual log level set. + # This will override the global log level set previously. + log-level: debug + name: Ardos # The cluster name to appear in the dashboard. port: 7781 # Port the WS connection listens on. diff --git a/libs/spdlog b/libs/spdlog new file mode 160000 index 0000000..a2b4262 --- /dev/null +++ b/libs/spdlog @@ -0,0 +1 @@ +Subproject commit a2b4262090fd3f005c2315dcb5be2f0f1774a005 diff --git a/src/clientagent/client_agent.cpp b/src/clientagent/client_agent.cpp index 9751ec4..33510ba 100644 --- a/src/clientagent/client_agent.cpp +++ b/src/clientagent/client_agent.cpp @@ -1,5 +1,7 @@ #include "client_agent.h" +#include + #include "../util/config.h" #include "../util/globals.h" #include "../util/logger.h" @@ -10,12 +12,19 @@ namespace Ardos { ClientAgent::ClientAgent() { - Logger::Info("Starting Client Agent component..."); + spdlog::info("Starting Client Agent component..."); _listenHandle = g_loop->resource(); auto config = Config::Instance()->GetNode("client-agent"); + // Log configuration. + spdlog::stdout_color_mt("ca"); + if (auto logLevel = config["log-level"]) { + spdlog::get("ca")->set_level( + Logger::LevelFromString(logLevel.as())); + } + // Listen configuration. if (auto hostParam = config["host"]) { _host = hostParam.as(); @@ -54,9 +63,9 @@ ClientAgent::ClientAgent() { DCClass *dcc = g_dc_file->get_class_by_name(uberdog["class"].as()); if (!dcc) { - Logger::Error(std::format( - "[CA] UberDOG: {} Distributed Class: {} does not exist!", - uberdog["id"].as(), uberdog["class"].as())); + spdlog::get("ca")->error( + "UberDOG: {} Distributed Class: {} does not exist!", + uberdog["id"].as(), uberdog["class"].as()); exit(1); } @@ -134,7 +143,7 @@ ClientAgent::ClientAgent() { _listenHandle->bind(_host, _port); _listenHandle->listen(); - Logger::Info(std::format("[CA] Listening on {}:{}", _host, _port)); + spdlog::get("ca")->info("Listening on {}:{}", _host, _port); } /** diff --git a/src/clientagent/client_participant.cpp b/src/clientagent/client_participant.cpp index f4fcd5e..2e392df 100644 --- a/src/clientagent/client_participant.cpp +++ b/src/clientagent/client_participant.cpp @@ -12,12 +12,12 @@ ClientParticipant::ClientParticipant( ClientAgent *clientAgent, const std::shared_ptr &socket) : NetworkClient(socket), ChannelSubscriber(), _clientAgent(clientAgent) { auto address = GetRemoteAddress(); - Logger::Verbose(std::format("[CA] Client connected from {}:{}", address.ip, - address.port)); + spdlog::get("ca")->debug("Client connected from {}:{}", address.ip, + address.port); _channel = _clientAgent->AllocateChannel(); if (!_channel) { - Logger::Error("[CA] Channel range depleted!"); + spdlog::get("ca")->error("Channel range depleted!"); SendDisconnect(CLIENT_DISCONNECT_GENERIC, "Channel range depleted"); return; } @@ -91,8 +91,8 @@ void ClientParticipant::Shutdown() { while (!_sessionObjects.empty()) { uint32_t doId = *_sessionObjects.begin(); _sessionObjects.erase(doId); - Logger::Verbose(std::format( - "[CA] Client: {} exited, deleting session object: {}", _channel, doId)); + spdlog::get("ca")->debug("Client: {} exited, deleting session object: {}", + _channel, doId); auto dg = std::make_shared(doId, _channel, STATESERVER_OBJECT_DELETE_RAM); @@ -107,8 +107,8 @@ void ClientParticipant::Shutdown() { (it++)->second->Finish(); } - Logger::Verbose(std::format("[CA] Routing {} post-remove(s) for '{}'", - _postRemoves.size(), _channel)); + spdlog::get("ca")->debug("Routing {} post-remove(s) for '{}'", + _postRemoves.size(), _channel); // Route any post remove datagrams we might have stored. for (const auto &dg : _postRemoves) { @@ -125,8 +125,8 @@ void ClientParticipant::HandleDisconnect(uv_errno_t code) { auto address = GetRemoteAddress(); auto errorEvent = uvw::error_event{(int)code}; - Logger::Verbose(std::format("[CA] Lost connection from {}:{}: {}", - address.ip, address.port, errorEvent.what())); + spdlog::get("ca")->debug("Lost connection from {}:{}: {}", address.ip, + address.port, errorEvent.what()); } Shutdown(); @@ -270,9 +270,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { uint16_t dcId = dgi.GetUint16(); if (_declaredObjects.contains(doId)) { - Logger::Warn(std::format( - "[CA] Client: {} received duplicate object declaration: {}", _channel, - doId)); + spdlog::get("ca")->warn( + "Client: {} received duplicate object declaration: {}", _channel, + doId); break; } @@ -285,9 +285,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { case CLIENTAGENT_UNDECLARE_OBJECT: { uint32_t doId = dgi.GetUint32(); if (!_declaredObjects.contains(doId)) { - Logger::Warn(std::format( - "[CA] Client: {} received un-declare object for unknown DoId: ", - _channel, doId)); + spdlog::get("ca")->warn( + "Client: {} received un-declare object for unknown DoId: ", _channel, + doId); break; } @@ -309,14 +309,14 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { case CLIENTAGENT_ADD_SESSION_OBJECT: { uint32_t doId = dgi.GetUint32(); if (_sessionObjects.contains(doId)) { - Logger::Warn(std::format( - "[CA] Client: {} received duplicate session object declaration: {}", - _channel, doId)); + spdlog::get("ca")->warn( + "Client: {} received duplicate session object declaration: {}", + _channel, doId); break; } - Logger::Verbose(std::format("[CA] Client: {} added session object: {}", - _channel, doId)); + spdlog::get("ca")->debug("Client: {} added session object: {}", _channel, + doId); _sessionObjects.insert(doId); break; @@ -324,15 +324,14 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { case CLIENTAGENT_REMOVE_SESSION_OBJECT: { uint32_t doId = dgi.GetUint32(); if (!_sessionObjects.contains(doId)) { - Logger::Warn(std::format( - "[CA] Client: {} received remove session object for unknown DoId: {}", - _channel, doId)); + spdlog::get("ca")->warn( + "Client: {} received remove session object for unknown DoId: {}", + _channel, doId); break; } - Logger::Verbose( - std::format("[CA] Client: {} removed session object with DoId: {}", - _channel, doId)); + spdlog::get("ca")->debug("Client: {} removed session object with DoId: {}", + _channel, doId); _sessionObjects.erase(doId); break; @@ -355,9 +354,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { return; } - Logger::Warn(std::format("[CA] Client: {} received server-side field " - "update for unknown object: {}", - _channel, doId)); + spdlog::get("ca")->warn("Client: {} received server-side field " + "update for unknown object: {}", + _channel, doId); return; } @@ -374,10 +373,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { return; } - Logger::Warn( - std::format("[CA] Client: {} received server-side multi-field " - "update for unknown object: {}", - _channel, doId)); + spdlog::get("ca")->warn("Client: {} received server-side multi-field " + "update for unknown object: {}", + _channel, doId); return; } @@ -390,18 +388,18 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { case STATESERVER_OBJECT_DELETE_RAM: { uint32_t doId = dgi.GetUint32(); - Logger::Verbose(std::format( - "[CA] Client: {} received DeleteRam for object with DoId: {}", _channel, - doId)); + spdlog::get("ca")->debug( + "Client: {} received DeleteRam for object with DoId: {}", _channel, + doId); if (!LookupObject(doId)) { if (TryQueuePending(doId, dgi.GetUnderlyingDatagram())) { return; } - Logger::Warn(std::format( - "[CA] Client: {} received server-side delete for unknown object: {}", - _channel, doId)); + spdlog::get("ca")->warn( + "Client: {} received server-side delete for unknown object: {}", + _channel, doId); return; } @@ -483,9 +481,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { uint32_t requestContext = dgi.GetUint32(); auto it = _pendingInterests.find(requestContext); if (it == _pendingInterests.end()) { - Logger::Warn(std::format("[CA] Client: {} received object entrance into " - "interest with unknown context: {}", - _channel, requestContext)); + spdlog::get("ca")->warn("Client: {} received object entrance into " + "interest with unknown context: {}", + _channel, requestContext); return; } @@ -503,9 +501,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { auto it = _pendingInterests.find(context); if (it == _pendingInterests.end()) { - Logger::Error(std::format( - "[CA] Client: {} received GET_ZONES_COUNT for unknown context: {}", - _channel, context)); + spdlog::get("ca")->error( + "Client: {} received GET_ZONES_COUNT for unknown context: {}", + _channel, context); return; } @@ -603,9 +601,9 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { } if (!_ownedObjects.contains(doId)) { - Logger::Error(std::format( - "[CA] Client: {} received changing owner for unowned object: {}", - _channel, doId)); + spdlog::get("ca")->error( + "Client: {} received changing owner for unowned object: {}", _channel, + doId); return; } @@ -624,8 +622,8 @@ void ClientParticipant::HandleDatagram(const std::shared_ptr &dg) { break; } default: - Logger::Error(std::format("Client: {} received unknown MsgType: {}", - _channel, msgType)); + spdlog::get("ca")->error("Client: {} received unknown MsgType: {}", + _channel, msgType); } } @@ -642,9 +640,10 @@ void ClientParticipant::SendDisconnect(const uint16_t &reason, return; } - std::string logOut = std::format("[CA] Ejecting client: '{}': {} - {}", - _channel, reason, message); - security ? Logger::Error(logOut) : Logger::Warn(logOut); + security ? spdlog::get("ca")->error("Ejecting client: '{}': {} - {}", + _channel, reason, message) + : spdlog::get("ca")->warn("Ejecting client: '{}': {} - {}", _channel, + reason, message); auto dg = std::make_shared(); dg->AddUint16(CLIENT_EJECT); @@ -745,7 +744,7 @@ void ClientParticipant::HandlePreHello(DatagramIterator &dgi) { void ClientParticipant::HandleLoginLegacy(DatagramIterator &dgi) { uint32_t authShim = _clientAgent->GetAuthShim(); if (!authShim) { - Logger::Error("[CA] No configured auth shim for legacy login!"); + spdlog::get("ca")->error("No configured auth shim for legacy login!"); SendDisconnect(CLIENT_DISCONNECT_GENERIC, "No available login handler!"); return; } @@ -753,8 +752,8 @@ void ClientParticipant::HandleLoginLegacy(DatagramIterator &dgi) { // Get the configured shim UberDOG. DCClass *authClass = LookupObject(authShim); if (!authClass) { - Logger::Error(std::format( - "[CA] Auth shim DoId: {} is not a configured UberDOG", authShim)); + spdlog::get("ca")->error("Auth shim DoId: {} is not a configured UberDOG", + authShim); SendDisconnect(CLIENT_DISCONNECT_GENERIC, "No available login handler!"); return; } @@ -763,8 +762,8 @@ void ClientParticipant::HandleLoginLegacy(DatagramIterator &dgi) { // messages. DCField *authField = authClass->get_field_by_name("login"); if (!authField) { - Logger::Error(std::format( - "[CA] Auth shim UberDOG: {} does not define a login field", authShim)); + spdlog::get("ca")->error( + "Auth shim UberDOG: {} does not define a login field", authShim); SendDisconnect(CLIENT_DISCONNECT_GENERIC, "No available login handler!"); return; } @@ -961,8 +960,8 @@ void ClientParticipant::HandleClientObjectUpdateField(DatagramIterator &dgi) { // Get the configured shim UberDOG. DCClass *chatClass = LookupObject(chatShim); if (!chatClass) { - Logger::Error(std::format( - "[CA] Chat shim DoId: {} is not a configured UberDOG", chatShim)); + spdlog::get("ca")->error( + "Chat shim DoId: {} is not a configured UberDOG", chatShim); // Just drop the message to be safe. return; } @@ -971,9 +970,9 @@ void ClientParticipant::HandleClientObjectUpdateField(DatagramIterator &dgi) { // This is a 1-1 mapping with the TalkPath_ field names. DCField *chatField = chatClass->get_field_by_name(field->get_name()); if (!chatField) { - Logger::Error(std::format( - "[CA] Chat shim UberDOG: {} does not define chat field: {}", - chatShim, field->get_name())); + spdlog::get("ca")->error( + "Chat shim UberDOG: {} does not define chat field: {}", chatShim, + field->get_name()); // Just drop the message to be safe. return; } @@ -1036,9 +1035,9 @@ void ClientParticipant::HandleClientObjectLocation(DatagramIterator &dgi) { auto parentId = dgi.GetUint32(); auto zoneId = dgi.GetUint32(); - Logger::Verbose(std::format( - "[CA] Client: {} relocating owned object: {} to location: {}/{}", - _channel, doId, parentId, zoneId)); + spdlog::get("ca")->debug( + "Client: {} relocating owned object: {} to location: {}/{}", _channel, + doId, parentId, zoneId); // Update the object's location with the state server. auto dg = std::make_shared(doId, _channel, @@ -1381,8 +1380,8 @@ void ClientParticipant::HandleAddObject( auto dg = std::make_shared(); dg->AddUint16(other ? CLIENT_ENTER_OBJECT_REQUIRED_OTHER : CLIENT_ENTER_OBJECT_REQUIRED); - Logger::Verbose(std::format("[CA] Sending entry of object: {} to client: {}", - doId, _channel)); + spdlog::get("ca")->debug("Sending entry of object: {} to client: {}", doId, + _channel); #ifdef ARDOS_USE_LEGACY_CLIENT // TODO: Check if this is the same for Toontown/Pirates. dg->AddLocation(parentId, zoneId); @@ -1436,8 +1435,8 @@ void ClientParticipant::HandleAddOwnership( const uint32_t &doId, const uint32_t &parentId, const uint32_t &zoneId, const uint16_t &dcId, DatagramIterator &dgi, const bool &other) { auto dg = std::make_shared(); - Logger::Info(std::format( - "[CA] Sending owner entry of object: {} to client: {}", doId, _channel)); + spdlog::get("ca")->debug("Sending owner entry of object: {} to client: {}", + doId, _channel); #ifdef ARDOS_USE_LEGACY_CLIENT // Fairies only accepts OTHER_OWNER entries and has a slightly different data // order. diff --git a/src/clientagent/interest_operation.cpp b/src/clientagent/interest_operation.cpp index d6a6c8f..4ec8710 100644 --- a/src/clientagent/interest_operation.cpp +++ b/src/clientagent/interest_operation.cpp @@ -35,8 +35,8 @@ InterestOperation::~InterestOperation() { } void InterestOperation::HandleInterestTimeout() { - Logger::Warn(std::format("Interest operation: {}:{} timed out, forcing...", - _interestId, _clientContext)); + spdlog::get("ca")->warn("Interest operation: {}:{} timed out, forcing...", + _interestId, _clientContext); _client->_clientAgent->RecordInterestTimeout(); diff --git a/src/database/database_server.cpp b/src/database/database_server.cpp index c380bda..fb4ba29 100644 --- a/src/database/database_server.cpp +++ b/src/database/database_server.cpp @@ -1,12 +1,11 @@ #include "database_server.h" -#include - #include #include #include #include #include +#include #include "../util/config.h" #include "../util/globals.h" @@ -21,18 +20,24 @@ using namespace bsoncxx::builder::stream; namespace Ardos { DatabaseServer::DatabaseServer() : ChannelSubscriber() { - Logger::Info("Starting Database Server component..."); + spdlog::info("Starting Database Server component..."); // Database Server configuration. auto config = Config::Instance()->GetNode("database-server"); + // Log configuration. + spdlog::stdout_color_mt("db"); + if (auto logLevel = config["log-level"]) { + spdlog::get("db")->set_level( + Logger::LevelFromString(logLevel.as())); + } + if (!config["channel"]) { - Logger::Error("[DB] Missing or invalid channel!"); + spdlog::get("db")->error("Missing or invalid channel!"); exit(1); } - if (!config["mongodb-uri"]) { - Logger::Error("[DB] Missing or invalid MongoDB URI!"); + spdlog::get("db")->error("Missing or invalid MongoDB URI!"); exit(1); } @@ -52,8 +57,7 @@ DatabaseServer::DatabaseServer() : ChannelSubscriber() { bsoncxx::builder::basic::kvp("ping", 1)); _db.run_command(pingCommand.view()); } catch (const std::exception &e) { - Logger::Error( - std::format("[DB] Failed to connect to MongoDB: {}", e.what())); + spdlog::get("db")->error("Failed to connect to MongoDB: {}", e.what()); exit(1); } @@ -81,7 +85,7 @@ DatabaseServer::DatabaseServer() : ChannelSubscriber() { // Initialize metrics. InitMetrics(); - Logger::Info(std::format("[DB] Connected to MongoDB: {}", _uri.to_string())); + spdlog::get("db")->info("Connected to MongoDB: {}", _uri.to_string()); } void DatabaseServer::HandleDatagram(const std::shared_ptr &dg) { @@ -114,11 +118,12 @@ void DatabaseServer::HandleDatagram(const std::shared_ptr &dg) { case DBSERVER_OBJECT_DELETE_FIELD: case DBSERVER_OBJECT_DELETE_FIELDS: // TODO: Implement this. - Logger::Error("[DB] OBJECT_DELETE_FIELD(S) NOT YET IMPLEMENTED!"); + spdlog::get("db")->error("OBJECT_DELETE_FIELD(S) NOT YET IMPLEMENTED!"); break; case DBSERVER_OBJECT_SET_FIELD_IF_EMPTY: // TODO: Implement this. - Logger::Error("[DB] OBJECT_SET_FIELD_IF_EMPTY NOT YET IMPLEMENTED!"); + spdlog::get("db")->error( + "OBJECT_SET_FIELD_IF_EMPTY NOT YET IMPLEMENTED!"); break; case DBSERVER_OBJECT_SET_FIELD_IF_EQUALS: case DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS: @@ -127,12 +132,11 @@ void DatabaseServer::HandleDatagram(const std::shared_ptr &dg) { break; default: // Hopefully we managed to unpack the sender... - Logger::Warn( - std::format("[DB] Received unknown message: {} from sender: {}", - msgType, sender)); + spdlog::get("db")->warn("Received unknown message: {} from sender: {}", + msgType, sender); } } catch (const DatagramIteratorEOF &) { - Logger::Error("[DB] Received a truncated datagram!"); + spdlog::get("db")->error("Received a truncated datagram!"); } } @@ -182,18 +186,18 @@ uint32_t DatabaseServer::AllocateDoId() { // We've got none left, return an invalid DoId. return INVALID_DO_ID; } catch (const ConversionException &e) { - Logger::Error(std::format( - "[DB] Conversion error occurred while allocating DoId: {}", e.what())); + spdlog::get("db")->error( + "Conversion error occurred while allocating DoId: {}", e.what()); return INVALID_DO_ID; } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] MongoDB error occurred while allocating DoId: {}", e.what())); + spdlog::get("db")->error("MongoDB error occurred while allocating DoId: {}", + e.what()); return INVALID_DO_ID; } } void DatabaseServer::FreeDoId(const uint32_t &doId) { - Logger::Verbose(std::format("[DB] Freeing DoId: {}", doId)); + spdlog::get("db")->debug("Freeing DoId: {}", doId); try { _db["globals"].update_one( @@ -206,8 +210,7 @@ void DatabaseServer::FreeDoId(const uint32_t &doId) { _freeChannelsGauge->Increment(); } } catch (const mongocxx::operation_exception &e) { - Logger::Error( - std::format("[DB] Failed to free DoId: {}: {}", doId, e.what())); + spdlog::get("db")->error("Failed to free DoId: {}: {}", doId, e.what()); } } @@ -223,8 +226,8 @@ void DatabaseServer::HandleCreate(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class(dcId); if (!dcClass) { - Logger::Error(std::format( - "[DB] Received create for unknown distributed class: {}", dcId)); + spdlog::get("db")->error( + "Received create for unknown distributed class: {}", dcId); HandleCreateDone(sender, context, INVALID_DO_ID); ReportFailed(CREATE_OBJECT); @@ -241,9 +244,9 @@ void DatabaseServer::HandleCreate(DatagramIterator &dgi, // Make sure that all present fields actually belong to the distributed class. if (!DatabaseUtils::VerifyFields(dcClass, objectFields)) { - Logger::Error(std::format( - "[DB] Failed to create object: {} with non-belonging fields", - dcClass->get_name())); + spdlog::get("db")->error( + "Failed to create object: {} with non-belonging fields", + dcClass->get_name()); HandleCreateDone(sender, context, INVALID_DO_ID); ReportFailed(CREATE_OBJECT); @@ -277,8 +280,8 @@ void DatabaseServer::HandleCreate(DatagramIterator &dgi, packer.end_unpack(); } } catch (const ConversionException &e) { - Logger::Error(std::format( - "[DB] Failed to unpack object fields for create: {}", e.what())); + spdlog::get("db")->error("Failed to unpack object fields for create: {}", + e.what()); HandleCreateDone(sender, context, INVALID_DO_ID); ReportFailed(CREATE_OBJECT); @@ -294,17 +297,16 @@ void DatabaseServer::HandleCreate(DatagramIterator &dgi, return; } - Logger::Verbose(std::format("[DB] Inserting new {} ({}): {}", - dcClass->get_name(), doId, - bsoncxx::to_json(fields))); + spdlog::get("db")->debug("Inserting new {} ({}): {}", dcClass->get_name(), + doId, bsoncxx::to_json(fields)); try { _db["objects"].insert_one(document{} << "_id" << static_cast(doId) << "dclass" << dcClass->get_name() << "fields" << fields << finalize); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format("[DB] Failed to insert new {} ({}): {}", - dcClass->get_name(), doId, e.what())); + spdlog::get("db")->error("Failed to insert new {} ({}): {}", + dcClass->get_name(), doId, e.what()); // Attempt to free the DoId we just allocated. FreeDoId(doId); @@ -340,9 +342,7 @@ void DatabaseServer::HandleDelete(DatagramIterator &dgi) { // Make sure we actually deleted the object. if (!result || result->deleted_count() != 1) { - Logger::Error( - std::format("[DB] Tried to delete non-existent object: {}", doId)); - + spdlog::get("db")->error("Tried to delete non-existent object: {}", doId); ReportFailed(DELETE_OBJECT); return; } @@ -350,13 +350,11 @@ void DatabaseServer::HandleDelete(DatagramIterator &dgi) { // Free the DoId. FreeDoId(doId); - Logger::Verbose(std::format("[DB] Deleted object: {}", doId)); - + spdlog::get("db")->debug("Deleted object: {}", doId); ReportCompleted(DELETE_OBJECT, startTime); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while deleting object {}: {}", doId, e.what())); - + spdlog::get("db")->error("Unexpected error while deleting object {}: {}", + doId, e.what()); ReportFailed(DELETE_OBJECT); } } @@ -373,8 +371,8 @@ void DatabaseServer::HandleGetAll(DatagramIterator &dgi, obj = _db["objects"].find_one( document{} << "_id" << static_cast(doId) << finalize); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while fetching object {}: {}", doId, e.what())); + spdlog::get("db")->error("Unexpected error while fetching object {}: {}", + doId, e.what()); HandleContextFailure(DBSERVER_OBJECT_GET_ALL_RESP, sender, context); ReportFailed(GET_OBJECT); @@ -382,8 +380,7 @@ void DatabaseServer::HandleGetAll(DatagramIterator &dgi, } if (!obj) { - Logger::Error( - std::format("[DB] Failed to fetch non-existent object: {}", doId)); + spdlog::get("db")->error("Failed to fetch non-existent object: {}", doId); HandleContextFailure(DBSERVER_OBJECT_GET_ALL_RESP, sender, context); ReportFailed(GET_OBJECT); @@ -395,9 +392,9 @@ void DatabaseServer::HandleGetAll(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class_by_name(dclassName); if (!dcClass) { - Logger::Error(std::format( - "[DB] Encountered unknown dclass while fetching object {}: {}", doId, - dclassName)); + spdlog::get("db")->error( + "Encountered unknown dclass while fetching object {}: {}", doId, + dclassName); HandleContextFailure(DBSERVER_OBJECT_GET_ALL_RESP, sender, context); ReportFailed(GET_OBJECT); @@ -415,9 +412,9 @@ void DatabaseServer::HandleGetAll(DatagramIterator &dgi, DCField *field = dcClass->get_field_by_name(fieldName); if (!field) { - Logger::Warn(std::format("[DB] Encountered unexpected field while " - "fetching object {}: {} - {}", - doId, dclassName, fieldName)); + spdlog::get("db")->warn("Encountered unexpected field while " + "fetching object {}: {} - {}", + doId, dclassName, fieldName); continue; } @@ -430,9 +427,9 @@ void DatabaseServer::HandleGetAll(DatagramIterator &dgi, objectDg.Clear(); } } catch (const ConversionException &e) { - Logger::Error( - std::format("[DB] Failed to unpack field fetching object {}: {} - {}", - doId, dclassName, e.what())); + spdlog::get("db")->error( + "Failed to unpack field fetching object {}: {} - {}", doId, dclassName, + e.what()); HandleContextFailure(DBSERVER_OBJECT_GET_ALL_RESP, sender, context); ReportFailed(GET_OBJECT); @@ -471,9 +468,9 @@ void DatabaseServer::HandleGetField(DatagramIterator &dgi, obj = _db["objects"].find_one( document{} << "_id" << static_cast(doId) << finalize); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while getting field(s) on object {}: {}", doId, - e.what())); + spdlog::get("db")->error( + "Unexpected error while getting field(s) on object {}: {}", doId, + e.what()); HandleContextFailure(responseType, sender, ctx); ReportFailed(GET_OBJECT_FIELDS); @@ -481,8 +478,8 @@ void DatabaseServer::HandleGetField(DatagramIterator &dgi, } if (!obj) { - Logger::Error(std::format( - "[DB] Failed to get field(s) on non-existent object: {}", doId)); + spdlog::get("db")->error( + "Failed to get field(s) on non-existent object: {}", doId); HandleContextFailure(responseType, sender, ctx); ReportFailed(GET_OBJECT_FIELDS); @@ -494,9 +491,9 @@ void DatabaseServer::HandleGetField(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class_by_name(dclassName); if (!dcClass) { - Logger::Error(std::format( - "[DB] Received get field(s) for unknown distributed class {}: {}", doId, - dclassName)); + spdlog::get("db")->error( + "Received get field(s) for unknown distributed class {}: {}", doId, + dclassName); HandleContextFailure(responseType, sender, ctx); ReportFailed(GET_OBJECT_FIELDS); @@ -514,9 +511,9 @@ void DatabaseServer::HandleGetField(DatagramIterator &dgi, auto fieldNum = dgi.GetUint16(); DCField *field = dcClass->get_field_by_index(fieldNum); if (!field) { - Logger::Error(std::format("[DB] Encountered unexpected field while " - "fetching object {}: {} - {}", - doId, dclassName, fieldNum)); + spdlog::get("db")->error("[DB] Encountered unexpected field while " + "fetching object {}: {} - {}", + doId, dclassName, fieldNum); HandleContextFailure(responseType, sender, ctx); ReportFailed(GET_OBJECT_FIELDS); @@ -541,9 +538,9 @@ void DatabaseServer::HandleGetField(DatagramIterator &dgi, objectDg.Clear(); } } catch (const ConversionException &e) { - Logger::Error( - std::format("[DB] Failed to unpack field fetching object {}: {} - {}", - doId, dclassName, e.what())); + spdlog::get("db")->error( + "Failed to unpack field fetching object {}: {} - {}", doId, dclassName, + e.what()); HandleContextFailure(responseType, sender, ctx); ReportFailed(GET_OBJECT_FIELDS); @@ -577,17 +574,17 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, obj = _db["objects"].find_one( document{} << "_id" << static_cast(doId) << finalize); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while setting field(s) on object {}: {}", doId, - e.what())); + spdlog::get("db")->error( + "Unexpected error while setting field(s) on object {}: {}", doId, + e.what()); ReportFailed(SET_OBJECT_FIELDS); return; } if (!obj) { - Logger::Error(std::format( - "[DB] Failed to set field(s) on non-existent object: {}", doId)); + spdlog::get("db")->error( + "Failed to set field(s) on non-existent object: {}", doId); ReportFailed(SET_OBJECT_FIELDS); return; @@ -598,9 +595,9 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class_by_name(dclassName); if (!dcClass) { - Logger::Error(std::format( - "[DB] Received set field(s) for unknown distributed class {}: {}", doId, - dclassName)); + spdlog::get("db")->error( + "Received set field(s) for unknown distributed class {}: {}", doId, + dclassName); ReportFailed(SET_OBJECT_FIELDS); return; @@ -609,8 +606,8 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, // Unpack the fields we've received in the 'set' message. FieldMap objectFields; if (!DatabaseUtils::UnpackFields(dgi, fieldCount, objectFields)) { - Logger::Error( - std::format("[DB] Failed to unpack set field(s) for object: {}", doId)); + spdlog::get("db")->error("Failed to unpack set field(s) for object: {}", + doId); ReportFailed(SET_OBJECT_FIELDS); return; @@ -618,8 +615,8 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, // Make sure that all present fields actually belong to the distributed class. if (!DatabaseUtils::VerifyFields(dcClass, objectFields)) { - Logger::Error(std::format("[DB] Failed to verify fields on object {}: {} ", - doId, dclassName)); + spdlog::get("db")->error("Failed to verify fields on object {}: {} ", doId, + dclassName); ReportFailed(SET_OBJECT_FIELDS); return; @@ -644,9 +641,9 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, packer.end_unpack(); } } catch (const ConversionException &e) { - Logger::Error(std::format( - "[DB] Failed to unpack object fields for set field(s) {}: {}", doId, - e.what())); + spdlog::get("db")->error( + "Failed to unpack object fields for set field(s) {}: {}", doId, + e.what()); ReportFailed(SET_OBJECT_FIELDS); return; @@ -661,21 +658,21 @@ void DatabaseServer::HandleSetField(DatagramIterator &dgi, fieldUpdate.view()); if (!updateOperation) { - Logger::Error(std::format( - "[DB] Set field(s) update operation failed for object {}", doId)); + spdlog::get("db")->error( + "Set field(s) update operation failed for object {}", doId); ReportFailed(SET_OBJECT_FIELDS); return; } - Logger::Verbose(std::format("[DB] Set field(s) for object {}: {}", doId, - bsoncxx::to_json(fieldBuilder.view()))); + spdlog::get("db")->debug("Set field(s) for object {}: {}", doId, + bsoncxx::to_json(fieldBuilder.view())); ReportCompleted(SET_OBJECT_FIELDS, startTime); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while setting field(s) on object {}: {}", doId, - e.what())); + spdlog::get("db")->error( + "Unexpected error while setting field(s) on object {}: {}", doId, + e.what()); ReportFailed(SET_OBJECT_FIELDS); } @@ -698,9 +695,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, obj = _db["objects"].find_one( document{} << "_id" << static_cast(doId) << finalize); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while setting field(s) equals on object {}: {}", - doId, e.what())); + spdlog::get("db")->error( + "Unexpected error while setting field(s) equals on object {}: {}", doId, + e.what()); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -708,8 +705,8 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, } if (!obj) { - Logger::Error(std::format( - "[DB] Failed to set field(s) equals on non-existent object: {}", doId)); + spdlog::get("db")->error( + "Failed to set field(s) equals on non-existent object: {}", doId); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -721,9 +718,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class_by_name(dclassName); if (!dcClass) { - Logger::Error(std::format("[DB] Received set field(s) equals for unknown " - "distributed class {}: {}", - doId, dclassName)); + spdlog::get("db")->error("Received set field(s) equals for unknown " + "distributed class {}: {}", + doId, dclassName); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -735,8 +732,8 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, FieldMap expectedFields; if (!DatabaseUtils::UnpackFields(dgi, fieldCount, objectFields, expectedFields)) { - Logger::Error(std::format( - "[DB] Failed to unpack set field(s) equals for object: {}", doId)); + spdlog::get("db")->error( + "Failed to unpack set field(s) equals for object: {}", doId); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -745,18 +742,18 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, // Make sure that all present fields actually belong to the distributed class. if (!DatabaseUtils::VerifyFields(dcClass, objectFields)) { - Logger::Error(std::format( - "[DB] Failed to verify set field(s) equals for object {}: {} ", doId, - dclassName)); + spdlog::get("db")->error( + "Failed to verify set field(s) equals for object {}: {} ", doId, + dclassName); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); return; } if (!DatabaseUtils::VerifyFields(dcClass, expectedFields)) { - Logger::Error(std::format( - "[DB] Failed to verify expected field(s) equals for object {}: {} ", - doId, dclassName)); + spdlog::get("db")->error( + "Failed to verify expected field(s) equals for object {}: {} ", doId, + dclassName); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -774,9 +771,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, // Hmm, the field doesn't exist at all. // Just insert an empty vector as its data. failedFields[it.first] = std::vector(); - Logger::Verbose(std::format("[DB] Missing expected field {} in set " - "field(s) equals for object {}: {}", - it.first->get_name(), doId, dclassName)); + spdlog::get("db")->debug("Missing expected field {} in set " + "field(s) equals for object {}: {}", + it.first->get_name(), doId, dclassName); continue; } @@ -787,9 +784,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, if (it.second != objectDg.GetBytes()) { // The field exists but the actual/expected data is mismatched. failedFields[it.first] = objectDg.GetBytes(); - Logger::Verbose(std::format("[DB] Mismatched expected field {} in set " - "field(s) equals for object {}: {}", - it.first->get_name(), doId, dclassName)); + spdlog::get("db")->debug("Mismatched expected field {} in set " + "field(s) equals for object {}: {}", + it.first->get_name(), doId, dclassName); continue; } @@ -834,9 +831,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, packer.end_unpack(); } } catch (const ConversionException &e) { - Logger::Error(std::format( - "[DB] Failed to unpack object fields for set field(s) equals {}: {}", - doId, e.what())); + spdlog::get("db")->error( + "Failed to unpack object fields for set field(s) equals {}: {}", doId, + e.what()); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -852,16 +849,16 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, fieldUpdate.view()); if (!updateOperation) { - Logger::Error(std::format( - "[DB] Set field(s) equals operation failed for object {}", doId)); + spdlog::get("db")->error( + "Set field(s) equals operation failed for object {}", doId); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); return; } - Logger::Verbose(std::format("[DB] Set field(s) equals for object {}: {}", - doId, bsoncxx::to_json(fieldBuilder.view()))); + spdlog::get("db")->debug("Set field(s) equals for object {}: {}", doId, + bsoncxx::to_json(fieldBuilder.view())); // Success! Notify the sender. auto dg = std::make_shared(sender, _channel, responseType); @@ -871,9 +868,9 @@ void DatabaseServer::HandleSetFieldEquals(DatagramIterator &dgi, ReportCompleted(UPDATE_OBJECT_FIELDS, startTime); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format( - "[DB] Unexpected error while setting field(s) equals on object {}: {}", - doId, e.what())); + spdlog::get("db")->error( + "Unexpected error while setting field(s) equals on object {}: {}", doId, + e.what()); HandleContextFailure(responseType, sender, ctx); ReportFailed(UPDATE_OBJECT_FIELDS); @@ -972,14 +969,14 @@ void DatabaseServer::InitFreeChannelsMetric() { _freeChannelsGauge->Set((double)(_maxDoId - currDoId + freeDoIds)); } catch (const ConversionException &e) { - Logger::Error(std::format("[DB] Conversion error occurred while " - "calculating free channel metrics: {}", - e.what())); + spdlog::get("db")->error("Conversion error occurred while " + "calculating free channel metrics: {}", + e.what()); _freeChannelsGauge->Set(0); } catch (const mongocxx::operation_exception &e) { - Logger::Error(std::format("[DB] MongoDB error occurred while calculating " - "free channel metrics: {}", - e.what())); + spdlog::get("db")->error("MongoDB error occurred while calculating " + "free channel metrics: {}", + e.what()); _freeChannelsGauge->Set(0); } } diff --git a/src/database/database_utils.cpp b/src/database/database_utils.cpp index 92ee066..0ab8345 100644 --- a/src/database/database_utils.cpp +++ b/src/database/database_utils.cpp @@ -5,9 +5,9 @@ #include #include #include +#include #include "../util/globals.h" -#include "../util/logger.h" namespace Ardos { @@ -18,8 +18,8 @@ bool DatabaseUtils::UnpackFields(DatagramIterator &dgi, uint16_t fieldId = dgi.GetUint16(); auto field = g_dc_file->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format("[DB] Attempted to unpack invalid field ID: {}", - fieldId)); + spdlog::get("db")->error("Attempted to unpack invalid field ID: {}", + fieldId); return false; } @@ -39,16 +39,15 @@ bool DatabaseUtils::UnpackFields(DatagramIterator &dgi, out[field] = std::vector(); } } catch (const DatagramIteratorEOF &) { - Logger::Error(std::format( - "[DB] Received truncated field in create/modify request: {}", - field->get_name())); + spdlog::get("db")->error( + "Received truncated field in create/modify request: {}", + field->get_name()); return false; } } else { // Oops, we got a non-db field. - Logger::Error( - std::format("[DB] Got non-db field in create/modify request: {}", - field->get_name())); + spdlog::get("db")->error("Got non-db field in create/modify request: {}", + field->get_name()); // Don't read-in a non-db field. if (!clearFields) { @@ -67,8 +66,8 @@ bool DatabaseUtils::UnpackFields(DatagramIterator &dgi, uint16_t fieldId = dgi.GetUint16(); auto field = g_dc_file->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format("[DB] Attempted to unpack invalid field ID: {}", - fieldId)); + spdlog::get("db")->error("Attempted to unpack invalid field ID: {}", + fieldId); return false; } @@ -80,15 +79,15 @@ bool DatabaseUtils::UnpackFields(DatagramIterator &dgi, // Unpack the updated field value. dgi.UnpackField(field, out[field]); } catch (const DatagramIteratorEOF &) { - Logger::Error( - std::format("[DB] Received truncated field in modify request: {}", - field->get_name())); + spdlog::get("db")->error( + "Received truncated field in modify request: {}", + field->get_name()); return false; } } else { // Oops, we got a non-db field. - Logger::Error(std::format("[DB] Got non-db field in modify request: {}", - field->get_name())); + spdlog::get("db")->error("Got non-db field in modify request: {}", + field->get_name()); // We need valid db fields for _IF_EQUALS updates. return false; @@ -448,9 +447,9 @@ bool DatabaseUtils::VerifyFields(const DCClass *dclass, if (!dclass->get_field_by_index(field.first->get_number())) { // We don't immediately break out here in case we have multiple // non-belonging fields. - Logger::Error(std::format("[DB] Failed to verify field on class: {} " - "with non-belonging field: {}", - dclass->get_name(), field.first->get_name())); + spdlog::get("db")->error("Failed to verify field on class: {} " + "with non-belonging field: {}", + dclass->get_name(), field.first->get_name()); errors = true; } } diff --git a/src/main.cpp b/src/main.cpp index e83412e..b2d05f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,5 @@ +#include + #include "messagedirector/message_director.h" #include "util/config.h" #include "util/globals.h" @@ -16,18 +18,20 @@ int main(int argc, char *argv[]) { } } - Config::Instance()->LoadConfig(configName); + spdlog::info("Starting Ardos cluster..."); - Logger::SetLogLevel(Config::Instance()->GetString("log-level", "warning")); + Config::Instance()->LoadConfig(configName); - Logger::Info("Starting Ardos cluster..."); + // Set global log level. + spdlog::set_level(Logger::LevelFromString( + Config::Instance()->GetString("log-level", "warning"))); // Load DC files from config. g_dc_file = new DCFile(); auto dcList = Config::Instance()->GetNode("dc-files"); if (!dcList) { - Logger::Error("Your config file must contain a dc-files definition!"); + spdlog::error("Your config file must contain a dc-files definition!"); return EXIT_FAILURE; } @@ -36,12 +40,12 @@ int main(int argc, char *argv[]) { if (!g_dc_file->read(dcName)) { // Just die if we can't read a DC file, they're very important to have // loaded correctly. - Logger::Error(std::format("Failed to read DC file `{}`!", dcName)); + spdlog::error("Failed to read DC file `{}`!", dcName); return EXIT_FAILURE; } } - Logger::Verbose(std::format("Computed DC hash: {}", g_dc_file->get_hash())); + spdlog::debug("Computed DC hash: {}", g_dc_file->get_hash()); // Setup main event loop. g_main_thread_id = std::this_thread::get_id(); diff --git a/src/messagedirector/channel_subscriber.cpp b/src/messagedirector/channel_subscriber.cpp index e5b2dda..eb99979 100644 --- a/src/messagedirector/channel_subscriber.cpp +++ b/src/messagedirector/channel_subscriber.cpp @@ -1,7 +1,6 @@ #include "channel_subscriber.h" #include "../net/datagram_iterator.h" -#include "../util/logger.h" #include "message_director.h" namespace Ardos { diff --git a/src/messagedirector/md_participant.cpp b/src/messagedirector/md_participant.cpp index eda8899..c7c7079 100644 --- a/src/messagedirector/md_participant.cpp +++ b/src/messagedirector/md_participant.cpp @@ -1,8 +1,9 @@ #include "md_participant.h" +#include + #include "../net/datagram_iterator.h" #include "../net/message_types.h" -#include "../util/logger.h" #include "message_director.h" namespace Ardos { @@ -10,8 +11,8 @@ namespace Ardos { MDParticipant::MDParticipant(const std::shared_ptr &socket) : NetworkClient(socket), ChannelSubscriber() { auto address = GetRemoteAddress(); - Logger::Info(std::format("[MD] Participant connected from {}:{}", address.ip, - address.port)); + spdlog::get("md")->info("Participant connected from {}:{}", address.ip, + address.port); MessageDirector::Instance()->ParticipantJoined(); } @@ -38,8 +39,8 @@ void MDParticipant::Shutdown() { // us. ChannelSubscriber::Shutdown(); - Logger::Verbose(std::format("[MD] Routing {} post-remove(s) for '{}'", - _postRemoves.size(), _connName)); + spdlog::get("md")->debug("Routing {} post-remove(s) for '{}'", + _postRemoves.size(), _connName); // Route any post remove datagrams we might have stored. for (const auto &dg : _postRemoves) { @@ -55,9 +56,8 @@ void MDParticipant::HandleDisconnect(uv_errno_t code) { auto address = GetRemoteAddress(); auto errorEvent = uvw::error_event{(int)code}; - Logger::Info(std::format("[MD] Lost connection from '{}' ({}:{}): {}", - _connName, address.ip, address.port, - errorEvent.what())); + spdlog::get("md")->info("Lost connection from '{}' ({}:{}): {}", _connName, + address.ip, address.port, errorEvent.what()); Shutdown(); } @@ -91,9 +91,9 @@ void MDParticipant::HandleClientDatagram(const std::shared_ptr &dg) { _connName = dgi.GetString(); break; default: - Logger::Error(std::format( - "[MD] Participant '{}' received unknown control message: {}", - _connName, msgType)); + spdlog::get("md")->error( + "Participant '{}' received unknown control message: {}", _connName, + msgType); } // We've handled their control message, no need to route through MD. @@ -103,8 +103,8 @@ void MDParticipant::HandleClientDatagram(const std::shared_ptr &dg) { // This wasn't a control message, route it through the message director. PublishDatagram(dg); } catch (const DatagramIteratorEOF &) { - Logger::Error(std::format( - "[MD] Participant '{}' received a truncated datagram!", _connName)); + spdlog::get("md")->error("Participant '{}' received a truncated datagram!", + _connName); Shutdown(); } } diff --git a/src/messagedirector/message_director.cpp b/src/messagedirector/message_director.cpp index aec1db6..7758723 100644 --- a/src/messagedirector/message_director.cpp +++ b/src/messagedirector/message_director.cpp @@ -1,5 +1,7 @@ #include "message_director.h" +#include + #include "../clientagent/client_agent.h" #ifdef ARDOS_WANT_DB_SERVER #include "../database/database_server.h" @@ -25,13 +27,20 @@ MessageDirector *MessageDirector::Instance() { } MessageDirector::MessageDirector() { - Logger::Info("Starting Message Director component..."); + spdlog::info("Starting Message Director component..."); _connectHandle = g_loop->resource(); _listenHandle = g_loop->resource(); auto config = Config::Instance()->GetNode("message-director"); + // Log configuration. + spdlog::stdout_color_mt("md"); + if (auto logLevel = config["log-level"]) { + spdlog::get("md")->set_level( + Logger::LevelFromString(logLevel.as())); + } + // Listen configuration. if (auto hostParam = config["host"]) { _host = hostParam.as(); @@ -71,7 +80,7 @@ MessageDirector::MessageDirector() { [](const uvw::error_event &event, uvw::tcp_handle &) { // Just die on error, the message director always needs a connection to // RabbitMQ. - Logger::Error(std::format("[MD] Socket error: {}", event.what())); + spdlog::get("md")->error("Socket error: {}", event.what()); exit(1); }); @@ -184,8 +193,9 @@ void MessageDirector::onReady(AMQP::Connection *connection) { #ifdef ARDOS_WANT_DB_SERVER _db = std::make_unique(); #else - Logger::Error("want-database was set to true but Ardos was " - "built without ARDOS_WANT_DB_SERVER"); + spdlog::get("md")->error( + "want-database was set to true but Ardos was " + "built without ARDOS_WANT_DB_SERVER"); exit(1); #endif } @@ -201,20 +211,18 @@ void MessageDirector::onReady(AMQP::Connection *connection) { // Start listening for incoming connections. _listenHandle->listen(); - Logger::Verbose(std::format("[MD] Local Queue: {}", _localQueue)); - - Logger::Info( - std::format("[MD] Listening on {}:{}", _host, _port)); + spdlog::get("md")->debug("Local Queue: {}", _localQueue); + spdlog::get("md")->info("Listening on {}:{}", _host, _port); }) .onError([](const char *message) { - Logger::Error(std::format( - "[MD] Failed to declare local queue: {}", message)); + spdlog::get("md")->error("Failed to declare local queue: {}", + message); exit(1); }); }) .onError([](const char *message) { - Logger::Error( - std::format("[MD] Failed to declare global exchange: {}", message)); + spdlog::get("md")->error("Failed to declare global exchange: {}", + message); exit(1); }); } @@ -234,7 +242,7 @@ void MessageDirector::onError(AMQP::Connection *connection, const char *message) { // The connection is dead at this point. // Log out an exception and shut everything down. - Logger::Error(std::format("[MD] RabbitMQ error: {}", message)); + spdlog::get("md")->error("RabbitMQ error: {}", message); exit(1); } @@ -402,10 +410,10 @@ void MessageDirector::StartConsuming() { _leavingSubscribers.clear(); }) .onCancelled([](const std::string &consumerTag) { - Logger::Error("[MD] Channel consuming cancelled unexpectedly."); + spdlog::get("md")->error("Channel consuming cancelled unexpectedly."); }) .onError([](const char *message) { - Logger::Error(std::format("[MD] Received error: {}", message)); + spdlog::get("md")->error("Received error: {}", message); }); } diff --git a/src/net/address_utils.cpp b/src/net/address_utils.cpp index 1339424..49ab9b0 100644 --- a/src/net/address_utils.cpp +++ b/src/net/address_utils.cpp @@ -1,6 +1,6 @@ #include "address_utils.h" -#include "../util/logger.h" +#include namespace Ardos { @@ -23,8 +23,7 @@ std::string AddressUtils::resolve_host(const std::shared_ptr &loop, auto dnsRequest = loop->resource(); auto dnsResult = dnsRequest->addr_info_sync(host, std::to_string(port)); if (!dnsResult.first) { - Logger::Error( - std::format("[NET] Failed to resolve host address: {}:{}", host, port)); + spdlog::error("[NET] Failed to resolve host address: {}:{}", host, port); exit(1); } @@ -32,11 +31,10 @@ std::string AddressUtils::resolve_host(const std::shared_ptr &loop, if (inet_ntop(dnsResult.second->ai_family, get_in_addr(dnsResult.second->ai_addr), addr, dnsResult.second->ai_addrlen)) { - return std::string(addr); + return {addr}; } - Logger::Error( - std::format("[NET] Failed to parse host address: {}:{}", host, port)); + spdlog::error("[NET] Failed to parse host address: {}:{}", host, port); exit(1); } diff --git a/src/net/datagram_iterator.cpp b/src/net/datagram_iterator.cpp index 5f484d6..b04c91e 100644 --- a/src/net/datagram_iterator.cpp +++ b/src/net/datagram_iterator.cpp @@ -1,8 +1,6 @@ #include "datagram_iterator.h" -#include - -#include "../util/logger.h" +#include namespace Ardos { @@ -218,8 +216,8 @@ void DatagramIterator::UnpackField(const DCPackerInterface *field, break; } default: - Logger::Error(std::format( - "[DGI] Unhandled field unpack for variable length: {}", length)); + spdlog::error("[DGI] Unhandled field unpack for variable length: {}", + length); } // Unpack field data into the buffer. @@ -293,8 +291,8 @@ void DatagramIterator::SkipField(const DCPackerInterface *field) { break; } default: - Logger::Error(std::format( - "[DGI] Unhandled field unpack for variable length: {}", length)); + spdlog::error("[DGI] Unhandled field unpack for variable length: {}", + length); } // Skip the field data. @@ -314,7 +312,9 @@ void DatagramIterator::SkipField(const DCPackerInterface *field) { * Returns the remaining read size in bytes. * @return */ -size_t DatagramIterator::GetRemainingSize() const { return _dg->Size() - _offset; } +size_t DatagramIterator::GetRemainingSize() const { + return _dg->Size() - _offset; +} /** * Returns the remaining bytes to be read. diff --git a/src/stateserver/database_state_server.cpp b/src/stateserver/database_state_server.cpp index f80d16f..326cd85 100644 --- a/src/stateserver/database_state_server.cpp +++ b/src/stateserver/database_state_server.cpp @@ -1,6 +1,6 @@ #include "database_state_server.h" -#include +#include #include "../util/config.h" #include "../util/logger.h" @@ -11,12 +11,30 @@ namespace Ardos { DatabaseStateServer::DatabaseStateServer() : ChannelSubscriber() { - Logger::Info("Starting Database State Server component..."); + spdlog::info("Starting Database State Server component..."); // Database State Server configuration. auto config = Config::Instance()->GetNode("db-state-server"); + + // Log configuration. + spdlog::stdout_color_mt("dbss"); + if (auto logLevel = config["log-level"]) { + spdlog::get("dbss")->set_level( + Logger::LevelFromString(logLevel.as())); + } + + // If we don't already have a State Server category setup, + // we need to create one for Distributed Object's. + if (!spdlog::get("ss")) { + spdlog::stdout_color_mt("ss"); + if (auto logLevel = config["log-level"]) { + spdlog::get("ss")->set_level( + Logger::LevelFromString(logLevel.as())); + } + } + if (!config["database"]) { - Logger::Error("[DBSS] Missing or invalid database channel!"); + spdlog::get("dbss")->error("Missing or invalid database channel!"); exit(1); } @@ -107,11 +125,11 @@ void DatabaseStateServer::HandleDatagram(const std::shared_ptr &dg) { break; default: // Hopefully we managed to unpack the sender... - Logger::Verbose(std::format("[DBSS] Ignoring message: {} from sender: {}", - msgType, sender)); + spdlog::get("dbss")->debug("Ignoring message: {} from sender: {}", + msgType, sender); } } catch (const DatagramIteratorEOF &) { - Logger::Error("[DBSS] Received a truncated datagram!"); + spdlog::get("dbss")->error("Received a truncated datagram!"); } } @@ -123,8 +141,8 @@ void DatabaseStateServer::HandleActivate(DatagramIterator &dgi, // Make sure we don't have a duplicate generate. if (_distObjs.contains(doId) || _loadObjs.contains(doId)) { - Logger::Error( - std::format("[DBSS] Received duplicate generate for DoId: {}", doId)); + spdlog::get("dbss")->error("Received duplicate generate for DoId: {}", + doId); return; } @@ -146,9 +164,9 @@ void DatabaseStateServer::HandleActivate(DatagramIterator &dgi, // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class(dcId); if (!dcClass) { - Logger::Error(std::format( - "[DBSS] Received ACTIVATE_OTHER with unknown distributed class {}: {}", - doId, dcId)); + spdlog::get("dbss")->error( + "Received ACTIVATE_OTHER with unknown distributed class {}: {}", doId, + dcId); return; } @@ -225,9 +243,9 @@ void DatabaseStateServer::HandleSetField(DatagramIterator &dgi, auto field = g_dc_file->get_field_by_index(fieldId); if (!field) { - Logger::Warn(std::format("[DBSS] Distributed object: {} received set " - "field(s) with invalid field id: {}", - doId, fieldId)); + spdlog::get("dbss")->warn("Distributed object: {} received set " + "field(s) with invalid field id: {}", + doId, fieldId); continue; } diff --git a/src/stateserver/distributed_object.cpp b/src/stateserver/distributed_object.cpp index ccea20e..a391089 100644 --- a/src/stateserver/distributed_object.cpp +++ b/src/stateserver/distributed_object.cpp @@ -1,12 +1,10 @@ #include "distributed_object.h" -#include #include #include #include - -#include "../util/logger.h" +#include namespace Ardos { @@ -32,9 +30,9 @@ DistributedObject::DistributedObject(StateServerImplementation *stateServer, uint16_t fieldId = dgi.GetUint16(); auto field = _dclass->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format( - "[SS] Received generated with unknown field id: {} for DoId: {}", - fieldId, _doId)); + spdlog::get("ss")->error( + "Received generated with unknown field id: {} for DoId: {}", + fieldId, _doId); break; } @@ -43,18 +41,17 @@ DistributedObject::DistributedObject(StateServerImplementation *stateServer, if (field->is_ram()) { dgi.UnpackField(field, _ramFields[field]); } else { - Logger::Error(std::format( - "[SS] Received generated with non RAM field: {} for DoId: ", - field->get_name(), _doId)); + spdlog::get("ss")->error( + "Received generated with non RAM field: {} for DoId: ", + field->get_name(), _doId); } } } SubscribeChannel(_doId); - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' generated with DoId: {}", - _dclass->get_name(), _doId)); + spdlog::get("ss")->debug("Distributed Object: '{}' generated with DoId: {}", + _dclass->get_name(), _doId); dgi.SeekPayload(); HandleLocationChange(parentId, zoneId, dgi.GetUint64()); @@ -72,9 +69,8 @@ DistributedObject::DistributedObject(StateServerImplementation *stateServer, _requiredFields(reqFields), _ramFields(ramFields) { SubscribeChannel(_doId); - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' generated with DoId: {}", - _dclass->get_name(), _doId)); + spdlog::get("ss")->debug("Distributed Object: '{}' generated with DoId: {}", + _dclass->get_name(), _doId); HandleLocationChange(parentId, zoneId, sender); WakeChildren(); @@ -131,7 +127,7 @@ void DistributedObject::Annihilate(const uint64_t &sender, _stateServer->RemoveDistributedObject(_doId); ChannelSubscriber::Shutdown(); - Logger::Verbose(std::format("[SS] Distributed Object: '{}' deleted.", _doId)); + spdlog::get("ss")->debug("Distributed Object: '{}' deleted.", _doId); } void DistributedObject::DeleteChildren(const uint64_t &sender) { @@ -156,9 +152,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { case STATESERVER_DELETE_AI_OBJECTS: { uint64_t channel = dgi.GetUint64(); if (_aiChannel != channel) { - Logger::Warn(std::format("[SS] Distributed Object: '{}' ({}) received " - "delete for wrong AI channel: {}", - _doId, _aiChannel, channel)); + spdlog::get("ss")->warn("Distributed Object: '{}' ({}) received " + "delete for wrong AI channel: {}", + _doId, _aiChannel, channel); break; } Annihilate(sender); @@ -203,14 +199,14 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { uint32_t parentId = dgi.GetUint32(); uint64_t newChannel = dgi.GetUint64(); - Logger::Verbose(std::format( - "[SS] Distributed Object: '{}' received changing AI from: {}", _doId, - parentId)); + spdlog::get("ss")->debug( + "Distributed Object: '{}' received changing AI from: {}", _doId, + parentId); if (parentId != _parentId) { - Logger::Warn(std::format("[SS] Distributed Object: '{}' received " - "changing AI from: {} but my parent is: {}", - _doId, parentId, _parentId)); + spdlog::get("ss")->warn("Distributed Object: '{}' received " + "changing AI from: {} but my parent is: {}", + _doId, parentId, _parentId); break; } @@ -224,16 +220,15 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { case STATESERVER_OBJECT_SET_AI: { uint64_t newChannel = dgi.GetUint64(); - Logger::Verbose(std::format( - "[SS] Distributed Object: '{}' updating AI to: {}", _doId, newChannel)); + spdlog::get("ss")->debug("Distributed Object: '{}' updating AI to: {}", + _doId, newChannel); HandleAIChange(newChannel, sender, true); break; } case STATESERVER_OBJECT_GET_AI: { - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' received AI query from: {}", - _doId, sender)); + spdlog::get("ss")->debug( + "Distributed Object: '{}' received AI query from: {}", _doId, sender); auto dg = std::make_shared(sender, _doId, STATESERVER_OBJECT_GET_AI_RESP); @@ -247,14 +242,14 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { dgi.GetUint32(); // Discard context. uint32_t parentId = dgi.GetUint32(); - Logger::Verbose(std::format( - "[SS] Distributed Object: '{}' received AI query response from: {}", - _doId, parentId)); + spdlog::get("ss")->debug( + "Distributed Object: '{}' received AI query response from: {}", _doId, + parentId); if (parentId != _parentId) { - Logger::Warn(std::format("[SS] Distributed Object: '{}' received AI " - "channel from: {} but my parent is: {}", - _doId, parentId, _parentId)); + spdlog::get("ss")->warn("Distributed Object: '{}' received AI " + "channel from: {} but my parent is: {}", + _doId, parentId, _parentId); break; } @@ -300,10 +295,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { _zoneObjects.erase(zoneId); } } else { - Logger::Warn( - std::format("[SS] Distributed Object: '{}' received changing " - "location from: {} for mismatched DoId: {}", - _doId, childId, doId)); + spdlog::get("ss")->warn("Distributed Object: '{}' received changing " + "location from: {} for mismatched DoId: {}", + _doId, childId, doId); } break; } @@ -311,19 +305,18 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { uint32_t parentId = dgi.GetUint32(); uint32_t zoneId = dgi.GetUint32(); if (parentId != _parentId) { - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' received location " - "acknowledgement from: {} but my parent is: {}", - _doId, parentId, _parentId)); + spdlog::get("ss")->debug("Distributed Object: '{}' received location " + "acknowledgement from: {} but my parent is: {}", + _doId, parentId, _parentId); } else if (zoneId != _zoneId) { - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' received location " - "acknowledgement for zone: {} but my zone is: {}", - _doId, zoneId, _zoneId)); + spdlog::get("ss")->debug( + "Distributed Object: '{}' received location " + "acknowledgement for zone: {} but my zone is: {}", + _doId, zoneId, _zoneId); } else { - Logger::Verbose(std::format("[SS] Distributed Object: '{}' parent " - "acknowledged my location change.", - _doId)); + spdlog::get("ss")->debug("Distributed Object: '{}' parent " + "acknowledged my location change.", + _doId); _parentSynchronized = true; } break; @@ -332,9 +325,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { uint32_t newParent = dgi.GetUint32(); uint32_t newZone = dgi.GetUint32(); - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' updating location to: {}/{}", - _doId, newParent, newZone)); + spdlog::get("ss")->debug( + "Distributed Object: '{}' updating location to: {}/{}", _doId, + newParent, newZone); HandleLocationChange(newParent, newZone, sender); break; @@ -356,9 +349,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { // of its pre-existing children. if (dgi.GetUint32() != STATESERVER_CONTEXT_WAKE_CHILDREN) { - Logger::Warn(std::format("[SS] Distributed Object: '{}' received " - "unexpected location response from: {}", - _doId, dgi.GetUint32())); + spdlog::get("ss")->warn("Distributed Object: '{}' received " + "unexpected location response from: {}", + _doId, dgi.GetUint32()); break; } @@ -427,9 +420,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { if (!requestedFields.insert(fieldId).second) { DCField *field = _dclass->get_field_by_index(i); if (field) { - Logger::Warn(std::format("[SS] Distributed Object: '{}' received " - "duplicate field: {} in get fields", - _doId, field->get_name())); + spdlog::get("ss")->warn("Distributed Object: '{}' received " + "duplicate field: {} in get fields", + _doId, field->get_name()); } } } @@ -466,9 +459,8 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { case STATESERVER_OBJECT_SET_OWNER: { uint64_t newOwner = dgi.GetUint64(); - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' updating owner to: {}", - _doId, newOwner)); + spdlog::get("ss")->debug("Distributed Object: '{}' updating owner to: {}", + _doId, newOwner); if (newOwner == _ownerChannel) { return; @@ -495,9 +487,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { uint32_t context = dgi.GetUint32(); uint32_t queriedParent = dgi.GetUint32(); - Logger::Verbose(std::format("[SS] Distributed Object: '{}' handling get " - "zones with parent: {} where my parent is: {}", - _doId, queriedParent, _parentId)); + spdlog::get("ss")->debug("Distributed Object: '{}' handling get " + "zones with parent: {} where my parent is: {}", + _doId, queriedParent, _parentId); uint16_t zoneCount = 1; if (msgType == STATESERVER_OBJECT_GET_ZONES_OBJECTS) { @@ -577,9 +569,9 @@ void DistributedObject::HandleDatagram(const std::shared_ptr &dgIn) { break; } default: - Logger::Warn(std::format( - "[SS] Distributed Object: '{}' ignoring unknown message type: {}", - _doId, msgType)); + spdlog::get("ss")->warn( + "Distributed Object: '{}' ignoring unknown message type: {}", _doId, + msgType); } } @@ -604,8 +596,8 @@ void DistributedObject::HandleLocationChange(const uint32_t &newParent, // Make sure we're not breaking our DO tree. if (newParent == _doId) { - Logger::Warn(std::format( - "[SS] Distributed Object: '{}' cannot be parented to itself.", _doId)); + spdlog::get("ss")->warn( + "Distributed Object: '{}' cannot be parented to itself.", _doId); return; } @@ -699,8 +691,8 @@ void DistributedObject::HandleAIChange(const uint64_t &newAI, PublishDatagram(dg); if (newAI) { - Logger::Verbose(std::format( - "[SS] Distributed Object: '{}' sending AI entry to: {}", _doId, newAI)); + spdlog::get("ss")->debug( + "[SS] Distributed Object: '{}' sending AI entry to: {}", _doId, newAI); SendAIEntry(newAI); } } @@ -828,24 +820,24 @@ bool DistributedObject::HandleOneUpdate(DatagramIterator &dgi, DCField *field = _dclass->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format("[SS] Distributed Object: '{}' received field " - "update for invalid field: {} - {}", - _doId, fieldId, _dclass->get_name())); + spdlog::get("ss")->error("Distributed Object: '{}' received field " + "update for invalid field: {} - {}", + _doId, fieldId, _dclass->get_name()); return false; } - Logger::Verbose( - std::format("[SS] Distributed Object: '{}' handling field update for: {}", - _doId, field->get_name())); + spdlog::get("ss")->debug( + "Distributed Object: '{}' handling field update for: {}", _doId, + field->get_name()); uint16_t fieldStart = dgi.Tell(); try { dgi.UnpackField(field, data); } catch (const DatagramIteratorEOF &) { - Logger::Error(std::format( - "[SS] Distributed Object: '{}' received truncated field update for: {}", - _doId, field->get_name())); + spdlog::get("ss")->error( + "Distributed Object: '{}' received truncated field update for: {}", + _doId, field->get_name()); return false; } @@ -893,9 +885,9 @@ bool DistributedObject::HandleOneGet(const std::shared_ptr &dg, const bool &isSubfield) { DCField *field = _dclass->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format( - "[SS] Distributed Object: '{}' get field for: {} not valid for class: ", - _doId, fieldId, _dclass->get_name())); + spdlog::get("ss")->error( + "Distributed Object: '{}' get field for: {} not valid for class: ", + _doId, fieldId, _dclass->get_name()); return false; } diff --git a/src/stateserver/loading_object.cpp b/src/stateserver/loading_object.cpp index ee09292..061c4e5 100644 --- a/src/stateserver/loading_object.cpp +++ b/src/stateserver/loading_object.cpp @@ -1,7 +1,5 @@ #include "loading_object.h" -#include - #include "../util/logger.h" namespace Ardos { @@ -39,18 +37,18 @@ LoadingObject::LoadingObject(DatabaseStateServer *stateServer, auto field = _dclass->get_field_by_index(fieldId); if (!field) { - Logger::Error(std::format("[DBSS] Loading object: {} received invalid " - "field index on generate: {}", - _doId, fieldId)); + spdlog::get("dbss")->error("Loading object: {} received invalid " + "field index on generate: {}", + _doId, fieldId); return; } if (field->is_ram() || field->is_required()) { dgi.UnpackField(field, _fieldUpdates[field]); } else { - Logger::Error(std::format( - "[DBSS] Loading object: {} received non-RAM field on generate: {}", - _doId, field->get_name())); + spdlog::get("dbss")->error( + "Loading object: {} received non-RAM field on generate: {}", _doId, + field->get_name()); } } @@ -88,19 +86,19 @@ void LoadingObject::HandleDatagram(const std::shared_ptr &dg) { // Make sure the context from the database is valid. uint32_t context = dgi.GetUint32(); if (context != _context && !_validContexts.contains(context)) { - Logger::Warn(std::format("[DBSS] Loading object: {} received " - "GET_ALL_RESP with invalid context: {}", - _doId, context)); + spdlog::get("dbss")->warn("Loading object: {} received " + "GET_ALL_RESP with invalid context: {}", + _doId, context); break; } - Logger::Verbose(std::format( - "[DBSS] Loading object: {} received GET_ALL_RESP", _doId)); + spdlog::get("dbss")->debug("Loading object: {} received GET_ALL_RESP", + _doId); _isLoaded = true; if (!dgi.GetBool()) { - Logger::Verbose(std::format( - "[DBSS] Loading object: {} was not found in database", _doId)); + spdlog::get("dbss")->debug( + "Loading object: {} was not found in database", _doId); Finalize(); break; } @@ -108,27 +106,26 @@ void LoadingObject::HandleDatagram(const std::shared_ptr &dg) { uint16_t dcId = dgi.GetUint16(); auto dcClass = g_dc_file->get_class(dcId); if (!dcClass) { - Logger::Error(std::format("[DBSS] Loading object: {} received invalid " - "dclass from database: {}", - _doId, dcId)); + spdlog::get("dbss")->error("Loading object: {} received invalid " + "dclass from database: {}", + _doId, dcId); Finalize(); break; } // Make sure both dclass's match if we were supplied with one. if (_dclass && dcClass != _dclass) { - Logger::Error(std::format( - "[DBSS] Loading object: {} received mismatched dclass: {} - {}", - _doId, _dclass->get_name(), dcClass->get_name())); + spdlog::get("dbss")->error( + "Loading object: {} received mismatched dclass: {} - {}", _doId, + _dclass->get_name(), dcClass->get_name()); Finalize(); break; } // Unpack fields from database. if (!UnpackDBFields(dgi, dcClass, _requiredFields, _ramFields)) { - Logger::Error(std::format( - "[DBSS] Loading object: {} failed to unpack fields from database.", - _doId)); + spdlog::get("dbss")->error( + "Loading object: {} failed to unpack fields from database.", _doId); Finalize(); break; } @@ -176,8 +173,8 @@ void LoadingObject::HandleDatagram(const std::shared_ptr &dg) { break; } } catch (const DatagramIteratorEOF &) { - Logger::Error(std::format( - "[DBSS] Loading object: {} received a truncated datagram!", _doId)); + spdlog::get("dbss")->error( + "Loading object: {} received a truncated datagram!", _doId); } } @@ -189,30 +186,29 @@ void LoadingObject::Finalize() { } void LoadingObject::ReplayDatagrams(DistributedObject *distObj) { - Logger::Verbose(std::format( - "[DBSS] Loading object: {} replaying datagrams received while loading...", - _doId)); + spdlog::get("dbss")->debug( + "Loading object: {} replaying datagrams received while loading...", + _doId); for (const auto &dg : _datagramQueue) { if (!_stateServer->_distObjs.contains(_doId)) { - Logger::Verbose( - std::format("[DBSS] Deleted while replaying, aborting...", _doId)); + spdlog::get("dbss")->debug("Deleted while replaying, aborting...", _doId); return; } distObj->HandleDatagram(dg); } - Logger::Verbose(std::format("[DBSS] Replay finished.", _doId)); + spdlog::get("dbss")->debug("Replay finished."); } void LoadingObject::ForwardDatagrams() { - Logger::Verbose(std::format("[DBSS] Loading object: {} forwarding datagrams " - "received while loading...", - _doId)); + spdlog::get("dbss")->debug("Loading object: {} forwarding datagrams " + "received while loading...", + _doId); for (const auto &dg : _datagramQueue) { _stateServer->HandleDatagram(dg); } - Logger::Verbose(std::format("[DBSS] Finished forwarding.", _doId)); + spdlog::get("dbss")->debug("Finished forwarding."); } } // namespace Ardos \ No newline at end of file diff --git a/src/stateserver/state_server.cpp b/src/stateserver/state_server.cpp index 5609359..a8fb0fe 100644 --- a/src/stateserver/state_server.cpp +++ b/src/stateserver/state_server.cpp @@ -1,6 +1,7 @@ #include "state_server.h" #include +#include #include "../net/message_types.h" #include "../util/config.h" @@ -13,12 +14,20 @@ namespace Ardos { StateServer::StateServer() : ChannelSubscriber() { - Logger::Info("Starting State Server component..."); + spdlog::info("Starting State Server component..."); // State Server configuration. auto config = Config::Instance()->GetNode("state-server"); + + // Log configuration. + spdlog::stdout_color_mt("ss"); + if (auto logLevel = config["log-level"]) { + spdlog::get("ss")->set_level( + Logger::LevelFromString(logLevel.as())); + } + if (!config["channel"]) { - Logger::Error("[SS] Missing or invalid channel!"); + spdlog::get("ss")->error("Missing or invalid channel!"); exit(1); } @@ -60,12 +69,11 @@ void StateServer::HandleDatagram(const std::shared_ptr &dg) { break; default: // Hopefully we managed to unpack the sender... - Logger::Warn( - std::format("[SS] Received unknown message: {} from sender: {}", - msgType, sender)); + spdlog::get("ss")->warn("Received unknown message: {} from sender: {}", + msgType, sender); } } catch (const DatagramIteratorEOF &) { - Logger::Error("[SS] Received a truncated datagram!"); + spdlog::get("ss")->error("Received a truncated datagram!"); } } @@ -77,16 +85,15 @@ void StateServer::HandleGenerate(DatagramIterator &dgi, const bool &other) { // Make sure we don't have a duplicate generate. if (_distObjs.contains(doId)) { - Logger::Error( - std::format("[SS] Received duplicate generate for DoId: {}", doId)); + spdlog::get("ss")->error("Received duplicate generate for DoId: {}", doId); return; } // Make sure we have a valid distributed class. DCClass *dcClass = g_dc_file->get_class(dcId); if (!dcClass) { - Logger::Error(std::format( - "[SS] Received generate for unknown distributed class: {}", dcId)); + spdlog::get("ss")->error( + "Received generate for unknown distributed class: {}", dcId); return; } @@ -107,8 +114,8 @@ void StateServer::HandleDeleteAI(DatagramIterator &dgi, const uint64_t &sender) { uint64_t aiChannel = dgi.GetUint64(); - Logger::Info(std::format("[SS] AI '{}' going offline... Deleting objects.", - aiChannel)); + spdlog::get("ss")->info("AI '{}' going offline... Deleting objects.", + aiChannel); std::unordered_set targets; for (const auto &distObj : _distObjs) { diff --git a/src/util/config.cpp b/src/util/config.cpp index 06907de..4da19b3 100644 --- a/src/util/config.cpp +++ b/src/util/config.cpp @@ -1,7 +1,6 @@ #include "config.h" #include "logger.h" -#include #include namespace Ardos { @@ -19,8 +18,7 @@ Config *Config::Instance() { void Config::LoadConfig(const std::string &name) { std::ifstream file(name.c_str()); if (!file.is_open()) { - Logger::Error( - std::format("Failed to open config file `{}`. Does it exist?", name)); + spdlog::error("Failed to open config file `{}`. Does it exist?", name); exit(1); } diff --git a/src/util/logger.cpp b/src/util/logger.cpp deleted file mode 100644 index 040bf93..0000000 --- a/src/util/logger.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "logger.h" - -#include -#include -#include -#include - -namespace Ardos { - -LogLevel Logger::_logLevel = LL_Warning; - -void Logger::SetLogLevel(const LogLevel &level) { _logLevel = level; } - -void Logger::SetLogLevel(const std::string_view level) { - if (level.compare("verbose") == 0) { - SetLogLevel(LL_Verbose); - } else if (level.compare("info") == 0) { - SetLogLevel(LL_Info); - } else if (level.compare("warning") == 0 || level.compare("warn") == 0) { - SetLogLevel(LL_Warning); - } else if (level.compare("error") == 0) { - SetLogLevel(LL_Error); - } else if (level.compare("none") == 0) { - SetLogLevel(LL_None); - } else { - Logger::Error(std::format( - "Invalid config log-level `{}`, defaulting to warn...", level)); - SetLogLevel(LL_Warning); - } -} - -void Logger::Verbose(const std::string_view out) { - if (_logLevel < LL_Verbose) { - return; - } - - std::cout << "[" << GetTime() << "] " - << "[VERBOSE]: " << out << std::endl; -} - -void Logger::Info(const std::string_view out) { - if (_logLevel < LL_Info) { - return; - } - - std::cout << "[" << GetTime() << "] " - << "[INFO]: " << out << std::endl; -} - -void Logger::Warn(const std::string_view out) { - if (_logLevel < LL_Warning) { - return; - } - - std::cout << "[" << GetTime() << "] " - << "[WARNING]: " << out << std::endl; -} - -void Logger::Error(const std::string_view out) { - if (_logLevel < LL_Error) { - return; - } - - std::cout << "[" << GetTime() << "] " - << "[ERROR]: " << out << std::endl; -} - -std::string Logger::GetTime() { - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - - std::ostringstream oss; - oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S"); - return oss.str(); -} - -} // namespace Ardos \ No newline at end of file diff --git a/src/util/logger.h b/src/util/logger.h index e861dd2..6c5493e 100644 --- a/src/util/logger.h +++ b/src/util/logger.h @@ -1,35 +1,29 @@ #ifndef ARDOS_LOGGER_H #define ARDOS_LOGGER_H -#include +#include namespace Ardos { -enum LogLevel { - LL_None, - LL_Error, - LL_Warning, - LL_Info, - LL_Verbose, -}; - class Logger { public: - static void SetLogLevel(const LogLevel &level); - static void SetLogLevel(std::string_view level); - - static void Verbose(std::string_view message); - static void Info(std::string_view message); - static void Warn(std::string_view message); - static void Error(std::string_view message); - -protected: - Logger() = default; - ~Logger() = default; - - static LogLevel _logLevel; - - static std::string GetTime(); + static spdlog::level::level_enum LevelFromString(const std::string &level) { + if (level == "debug" || level == "verbose") { + return spdlog::level::debug; + } else if (level == "info") { + return spdlog::level::info; + } else if (level == "warning" || level == "warn") { + return spdlog::level::warn; + } else if (level == "error") { + return spdlog::level::err; + } else if (level == "none") { + return spdlog::level::off; + } else { + spdlog::error("Invalid config log-level `{}`, defaulting to warn...", + level); + return spdlog::level::warn; + } + } }; } // namespace Ardos diff --git a/src/util/metrics.cpp b/src/util/metrics.cpp index f867888..edcb3e7 100644 --- a/src/util/metrics.cpp +++ b/src/util/metrics.cpp @@ -1,8 +1,7 @@ #include "metrics.h" -#include - #include +#include #include "config.h" #include "logger.h" @@ -26,8 +25,17 @@ Metrics::Metrics() { return; } + spdlog::info("Starting Metrics component..."); + auto config = Config::Instance()->GetNode("metrics"); + // Log configuration. + spdlog::stdout_color_mt("metrics"); + if (auto logLevel = config["log-level"]) { + spdlog::get("metrics")->set_level( + Logger::LevelFromString(logLevel.as())); + } + // Listen configuration. if (auto hostParam = config["host"]) { _host = hostParam.as(); @@ -44,7 +52,7 @@ Metrics::Metrics() { _registry = std::make_shared(); _exposer->RegisterCollectable(_registry); - Logger::Info(std::format("[METRICS] Listening on {}:{}", _host, _port)); + spdlog::get("metrics")->info("Listening on {}:{}", _host, _port); } bool Metrics::WantMetrics() const { return _wantMetrics; } diff --git a/src/web/web_panel.cpp b/src/web/web_panel.cpp index 68f545e..f414ad0 100644 --- a/src/web/web_panel.cpp +++ b/src/web/web_panel.cpp @@ -1,13 +1,12 @@ #include "web_panel.h" +#include + #include "../clientagent/client_agent.h" #include "../database/database_server.h" #include "../messagedirector/message_director.h" -#include "../net/datagram.h" #include "../stateserver/database_state_server.h" -#include "../stateserver/state_server.h" #include "../util/config.h" -#include "../util/globals.h" #include "../util/logger.h" namespace Ardos { @@ -15,13 +14,20 @@ namespace Ardos { WebPanel *WebPanel::Instance = nullptr; WebPanel::WebPanel() { - Logger::Info("Starting Web Panel component..."); + spdlog::info("Starting Web Panel component..."); Instance = this; // Web Panel configuration. auto config = Config::Instance()->GetNode("web-panel"); + // Log configuration. + spdlog::stdout_color_mt("web"); + if (auto logLevel = config["log-level"]) { + spdlog::get("web")->set_level( + Logger::LevelFromString(logLevel.as())); + } + // Cluster name configuration. if (auto nameParam = config["name"]) { _name = nameParam.as(); @@ -56,18 +62,17 @@ WebPanel::WebPanel() { SSL_CTX *ctx = SSL_CTX_new(method); if (!ctx) { - Logger::Error("Unable to create SSL context"); + spdlog::get("web")->error("Unable to create SSL context"); } if (SSL_CTX_use_certificate_file(ctx, _cert.c_str(), SSL_FILETYPE_PEM) <= 0) { - Logger::Error(std::format("[WEB] Failed to load cert file: {}", _cert)); + spdlog::get("web")->error("Failed to load cert file: {}", _cert); exit(1); } if (SSL_CTX_use_PrivateKey_file(ctx, _key.c_str(), SSL_FILETYPE_PEM) <= 0) { - Logger::Error( - std::format("[WEB] Failed to load private key file: {}", _cert)); + spdlog::get("web")->error("Failed to load private key file: {}", _cert); exit(1); } @@ -87,8 +92,7 @@ WebPanel::WebPanel() { _server->SetClientConnectedCallback( [](ws28::Client *client, ws28::HTTPRequest &) { - Logger::Verbose( - std::format("[WEB] Client connected from {}", client->GetIP())); + spdlog::get("web")->debug("Client connected from {}", client->GetIP()); auto *data = (ClientData *)malloc(sizeof(ClientData)); data->authed = false; @@ -97,8 +101,7 @@ WebPanel::WebPanel() { }); _server->SetClientDisconnectedCallback([](ws28::Client *client) { - Logger::Verbose( - std::format("[WEB] Client '{}' disconnected", client->GetIP())); + spdlog::get("web")->debug("Client '{}' disconnected", client->GetIP()); // Free alloc'd user data. if (client->GetUserData() != nullptr) { @@ -115,8 +118,8 @@ WebPanel::WebPanel() { // Start listening! _server->Listen(_port); - Logger::Info(std::format("[WEB] Listening on {} [{}]", _port, - _secure ? "SECURE" : "UNSECURE")); + spdlog::get("web")->info("Listening on {} [{}]", _port, + _secure ? "SECURE" : "UNSECURE"); } void WebPanel::Send(ws28::Client *client, const nlohmann::json &data) {