diff --git a/CHANGELOG b/CHANGELOG index 1b0fea1877..6f2119bd55 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ devel ----- +* Export Version and Storage Engine in `_admin/cluster/health` for Coordinators and DBServers. + * fixed Foxx complaining about valid `$schema` value in manifest.json * Foxx `req.makeAbsolute` now will return meaningful values when ArangoDB is using diff --git a/arangod/Agency/Supervision.cpp b/arangod/Agency/Supervision.cpp index 129a90ff43..25e040bfad 100644 --- a/arangod/Agency/Supervision.cpp +++ b/arangod/Agency/Supervision.cpp @@ -53,13 +53,17 @@ struct HealthRecord { std::string advertisedEndpoint; std::string lastAcked; std::string hostId; + std::string serverVersion; + std::string engine; size_t version; explicit HealthRecord() : version(0) {} HealthRecord( - std::string const& sn, std::string const& ep, std::string const& ho) : - shortName(sn), endpoint(ep), hostId(ho), version(0) {} + std::string const& sn, std::string const& ep, std::string const& ho, + std::string const& en, std::string const& sv) : + shortName(sn), endpoint(ep), hostId(ho), serverVersion(sv), + engine(en), version(0) {} explicit HealthRecord(Node const& node) { *this = node; @@ -94,6 +98,12 @@ struct HealthRecord { if (node.has("AdvertisedEndpoint")) { version = 3; advertisedEndpoint = node.hasAsString("AdvertisedEndpoint").first; + + if (node.has("Engine") && node.has("Version")) { + version = 4; + engine = node.hasAsString("Engine").first; + serverVersion = node.hasAsString("Version").first; + } } } else if (node.has("LastHeartbeatStatus")) { version = 1; @@ -116,6 +126,8 @@ struct HealthRecord { advertisedEndpoint = other.advertisedEndpoint; endpoint = other.endpoint; hostId = other.hostId; + engine = other.engine; + serverVersion = other.serverVersion; version = other.version; return *this; } @@ -128,6 +140,8 @@ struct HealthRecord { obj.add("Host", VPackValue(hostId)); obj.add("SyncStatus", VPackValue(syncStatus)); obj.add("Status", VPackValue(status)); + obj.add("Version", VPackValue(serverVersion)); + obj.add("Engine", VPackValue(engine)); if (syncTime.empty()) { obj.add("Timestamp", VPackValue(timepointToString(std::chrono::system_clock::now()))); @@ -443,18 +457,31 @@ std::vector Supervision::check(std::string const& type) { shortName = tmp_shortName.first; - // "/arango/Current//endpoint" + // "/arango/Current/ServersRegistered//endpoint" std::string endpoint; std::string epPath = serverID + "/endpoint"; if (serversRegistered.has(epPath)) { endpoint = serversRegistered.hasAsString(epPath).first; } - // "/arango/Current//host" + // "/arango/Current/ServersRegistered//host" std::string hostId; std::string hoPath = serverID + "/host"; if (serversRegistered.has(hoPath)) { hostId = serversRegistered.hasAsString(hoPath).first; } + // "/arango/Current/ServersRegistered//serverVersion" + std::string serverVersion; + std::string svPath = serverID + "/versionString"; + if (serversRegistered.has(svPath)) { + serverVersion = serversRegistered.hasAsString(svPath).first; + } + // "/arango/Current/ServersRegistered//engine" + std::string engine; + std::string enPath = serverID + "/engine"; + if (serversRegistered.has(enPath)) { + engine = serversRegistered.hasAsString(enPath).first; + } + // "/arango/Current//externalEndpoint" /*std::string externalEndpoint; @@ -464,8 +491,8 @@ std::vector Supervision::check(std::string const& type) { }*/ // Health records from persistence, from transience and a new one - HealthRecord transist(shortName, endpoint, hostId); - HealthRecord persist(shortName, endpoint, hostId); + HealthRecord transist(shortName, endpoint, hostId, engine, serverVersion); + HealthRecord persist(shortName, endpoint, hostId, engine, serverVersion); // Get last health entries from transient and persistent key value stores if (_transient.has(healthPrefix + serverID)) { @@ -1021,7 +1048,7 @@ void Supervision::workJobs() { void Supervision::readyOrphanedIndexCreations() { _lock.assertLockedByCurrentThread(); - + if (_snapshot.has(planColPrefix) && _snapshot.has(curColPrefix)) { auto const& plannedDBs = _snapshot(planColPrefix).children(); auto const& currentDBs = _snapshot(curColPrefix); @@ -1053,7 +1080,7 @@ void Supervision::readyOrphanedIndexCreations() { for (auto const& sh : shards.children()) { auto const& shname = sh.first; - + if (currentDBs.has(colPath + shname + "/indexes")) { auto const& curIndexes = currentDBs(colPath + shname + "/indexes").slice(); @@ -1107,7 +1134,7 @@ void Supervision::readyOrphanedIndexCreations() { { VPackObjectBuilder precondition(envelope.get()); envelope->add( VPackValue( - _agencyPrefix + planColPrefix + colPath + "indexes")); + _agencyPrefix + planColPrefix + colPath + "indexes")); envelope->add(indexes); } }} @@ -1116,7 +1143,7 @@ void Supervision::readyOrphanedIndexCreations() { LOG_TOPIC(DEBUG, Logger::SUPERVISION) << "failed to report ready index to agency. Will retry."; } - } + } } } } diff --git a/arangod/Cluster/ServerState.cpp b/arangod/Cluster/ServerState.cpp index 691b8974b0..a2e04c95b6 100644 --- a/arangod/Cluster/ServerState.cpp +++ b/arangod/Cluster/ServerState.cpp @@ -484,16 +484,16 @@ static constexpr char const* currentServersRegisteredPref = "/Current/ServersReg /// @brief check equality of engines with other registered servers bool ServerState::checkEngineEquality(AgencyComm& comm) { std::string engineName = EngineSelectorFeature::engineName(); - + AgencyCommResult result = comm.getValues(currentServersRegisteredPref); if (result.successful()) { // no error if we cannot reach agency directly - + auto slicePath = AgencyCommManager::slicePath(currentServersRegisteredPref); VPackSlice servers = result.slice()[0].get(slicePath); if (!servers.isObject()) { return true; // do not do anything harsh here } - + for (VPackObjectIterator::ObjectPair pair : VPackObjectIterator(servers)) { if (pair.value.isObject()) { VPackSlice engineStr = pair.value.get("engine"); @@ -503,7 +503,7 @@ bool ServerState::checkEngineEquality(AgencyComm& comm) { } } } - + return true; } @@ -645,7 +645,7 @@ bool ServerState::registerAtAgencyPhase1(AgencyComm& comm, bool ServerState::registerAtAgencyPhase2(AgencyComm& comm) { TRI_ASSERT(!_id.empty() && !_myEndpoint.empty()); - + while (!application_features::ApplicationServer::isStopping()) { VPackBuilder builder; try { @@ -654,14 +654,15 @@ bool ServerState::registerAtAgencyPhase2(AgencyComm& comm) { builder.add("advertisedEndpoint", VPackValue(_advertisedEndpoint)); builder.add("host", VPackValue(getHost())); builder.add("version", VPackValue(rest::Version::getNumericServerVersion())); + builder.add("versionString", VPackValue(rest::Version::getServerVersion())); builder.add("engine", VPackValue(EngineSelectorFeature::engineName())); } catch (...) { LOG_TOPIC(FATAL, arangodb::Logger::CLUSTER) << "out of memory"; FATAL_ERROR_EXIT(); } - + auto result = comm.setValue(currentServersRegisteredPref + _id, builder.slice(), 0.0); - + if (result.successful()) { return true; } else { @@ -669,10 +670,10 @@ bool ServerState::registerAtAgencyPhase2(AgencyComm& comm) { << "failed to register server in agency: http code: " << result.httpCode() << ", body: '" << result.body() << "', retrying ..."; } - + std::this_thread::sleep_for(std::chrono::seconds(1)); } - + return false; }