diff options
author | Blake Oler <blake.oler@mongodb.com> | 2022-09-21 17:45:44 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-09-21 20:05:35 +0000 |
commit | 02948a5102d2be9f5b727045cf787fc7dda2fcb7 (patch) | |
tree | 04e2238886ea27354c6e991a5440bbe136a39703 | |
parent | bf191b0361e837a17c743941180a4d77de875a9d (diff) | |
download | mongo-02948a5102d2be9f5b727045cf787fc7dda2fcb7.tar.gz |
SERVER-64005 Add metric tracking listener socket backlog queue depth
-rw-r--r-- | src/mongo/db/commands/server_status_servers.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_mongod.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_mongos.cpp | 3 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer.h | 7 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_asio.cpp | 128 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_asio.h | 16 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_asio_test.cpp | 86 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_ftdc_collector.h | 50 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_manager.cpp | 8 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_manager.h | 3 | ||||
-rw-r--r-- | src/mongo/util/net/sockaddr.cpp | 10 | ||||
-rw-r--r-- | src/mongo/util/net/sockaddr.h | 1 |
12 files changed, 277 insertions, 40 deletions
diff --git a/src/mongo/db/commands/server_status_servers.cpp b/src/mongo/db/commands/server_status_servers.cpp index 6e6a265c9e0..d5dd31ca347 100644 --- a/src/mongo/db/commands/server_status_servers.cpp +++ b/src/mongo/db/commands/server_status_servers.cpp @@ -95,7 +95,7 @@ public: } } if (auto tl = svcCtx->getTransportLayer()) - tl->appendStats(&b); + tl->appendStatsForServerStatus(&b); return b.obj(); } diff --git a/src/mongo/db/ftdc/ftdc_mongod.cpp b/src/mongo/db/ftdc/ftdc_mongod.cpp index 8da45771f19..6ccae55e539 100644 --- a/src/mongo/db/ftdc/ftdc_mongod.cpp +++ b/src/mongo/db/ftdc/ftdc_mongod.cpp @@ -41,6 +41,7 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/storage/storage_options.h" +#include "mongo/transport/transport_layer_ftdc_collector.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -128,6 +129,8 @@ void registerMongoDCollectors(FTDCController* controller) { } controller->addPeriodicCollector(std::make_unique<FTDCCollectionStatsCollector>()); + + controller->addPeriodicCollector(std::make_unique<transport::TransportLayerFTDCCollector>()); } } // namespace diff --git a/src/mongo/db/ftdc/ftdc_mongos.cpp b/src/mongo/db/ftdc/ftdc_mongos.cpp index 53216762137..aeb457f38d7 100644 --- a/src/mongo/db/ftdc/ftdc_mongos.cpp +++ b/src/mongo/db/ftdc/ftdc_mongos.cpp @@ -45,6 +45,7 @@ #include "mongo/logv2/log.h" #include "mongo/s/grid.h" #include "mongo/stdx/thread.h" +#include "mongo/transport/transport_layer_ftdc_collector.h" #include "mongo/util/synchronized_value.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kFTDC @@ -111,6 +112,8 @@ void registerMongoSCollectors(FTDCController* controller) { controller->addPeriodicCollector(std::make_unique<NetworkInterfaceStatsCollector>()); + controller->addPeriodicCollector(std::make_unique<transport::TransportLayerFTDCCollector>()); + // GetDefaultRWConcern controller->addOnRotateCollector(std::make_unique<FTDCSimpleInternalCommandCollector>( "getDefaultRWConcern", diff --git a/src/mongo/transport/transport_layer.h b/src/mongo/transport/transport_layer.h index 24afafe1f01..369226ad7a9 100644 --- a/src/mongo/transport/transport_layer.h +++ b/src/mongo/transport/transport_layer.h @@ -123,8 +123,11 @@ public: */ virtual Status setup() = 0; - /** Allows a `TransportLayer` to contribute to a stats summary (e.g. `serverStatus`). */ - virtual void appendStats(BSONObjBuilder* bob) const {} + /** Allows a `TransportLayer` to contribute to a serverStatus readout. */ + virtual void appendStatsForServerStatus(BSONObjBuilder* bob) const {} + + /** Allows a `TransportLayer` to contribute to a FTDC readout. */ + virtual void appendStatsForFTDC(BSONObjBuilder& bob) const {} enum WhichReactor { kIngress, kEgress, kNewReactor }; virtual ReactorHandle getReactor(WhichReactor which) = 0; diff --git a/src/mongo/transport/transport_layer_asio.cpp b/src/mongo/transport/transport_layer_asio.cpp index 2f1b90095d6..903792c47e5 100644 --- a/src/mongo/transport/transport_layer_asio.cpp +++ b/src/mongo/transport/transport_layer_asio.cpp @@ -123,7 +123,8 @@ boost::optional<Status> maybeTcpFastOpenStatus; MONGO_FAIL_POINT_DEFINE(transportLayerASIOasyncConnectTimesOut); MONGO_FAIL_POINT_DEFINE(transportLayerASIOdelayConnection); -MONGO_FAIL_POINT_DEFINE(transportLayerASIOhangBeforeAccept); +MONGO_FAIL_POINT_DEFINE(transportLayerASIOhangBeforeAcceptCallback); +MONGO_FAIL_POINT_DEFINE(transportLayerASIOhangDuringAcceptCallback); #ifdef MONGO_CONFIG_SSL SSLConnectionContext::~SSLConnectionContext() = default; @@ -392,6 +393,17 @@ TransportLayerASIO::TransportLayerASIO(const TransportLayerASIO::Options& opts, TransportLayerASIO::~TransportLayerASIO() = default; +struct TransportLayerASIO::AcceptorRecord { + AcceptorRecord(SockAddr address, GenericAcceptor acceptor) + : address(std::move(address)), acceptor(std::move(acceptor)) {} + + SockAddr address; + GenericAcceptor acceptor; + // Tracks the amount of incoming connections waiting to be accepted by the server on this + // acceptor. + AtomicWord<int> backlogQueueDepth{0}; +}; + class WrappedEndpoint { public: using Endpoint = asio::generic::stream_protocol::endpoint; @@ -1262,24 +1274,29 @@ Status TransportLayerASIO::setup() { } } #endif + auto endpoint = acceptor.local_endpoint(ec); + if (ec) { + return errorCodeToStatus(ec); + } + auto hostAndPort = endpointToHostAndPort(endpoint); + + auto record = std::make_unique<AcceptorRecord>(SockAddr(addr->data(), addr->size()), + std::move(acceptor)); + if (_listenerOptions.port == 0 && (addr.family() == AF_INET || addr.family() == AF_INET6)) { if (_listenerPort != _listenerOptions.port) { return Status(ErrorCodes::BadValue, "Port 0 (ephemeral port) is not allowed when" " listening on multiple IP interfaces"); } - std::error_code ec; - auto endpoint = acceptor.local_endpoint(ec); - if (ec) { - return errorCodeToStatus(ec); - } - _listenerPort = endpointToHostAndPort(endpoint).port(); + _listenerPort = hostAndPort.port(); + record->address.setPort(_listenerPort); } - _acceptors.emplace_back(SockAddr(addr->data(), addr->size()), std::move(acceptor)); + _acceptorRecords.push_back(std::move(record)); } - if (_acceptors.empty() && _listenerOptions.isIngress()) { + if (_acceptorRecords.empty() && _listenerOptions.isIngress()) { return Status(ErrorCodes::SocketException, "No available addresses/ports to bind to"); } @@ -1294,9 +1311,31 @@ Status TransportLayerASIO::setup() { return Status::OK(); } -void TransportLayerASIO::appendStats(BSONObjBuilder* bob) const { - if (gFeatureFlagConnHealthMetrics.isEnabledAndIgnoreFCV()) +std::vector<std::pair<SockAddr, int>> TransportLayerASIO::getListenerSocketBacklogQueueDepths() + const { + std::vector<std::pair<SockAddr, int>> queueDepths; + for (auto&& record : _acceptorRecords) { + queueDepths.push_back({SockAddr(record->address), record->backlogQueueDepth.load()}); + } + return queueDepths; +} + +void TransportLayerASIO::appendStatsForServerStatus(BSONObjBuilder* bob) const { + if (gFeatureFlagConnHealthMetrics.isEnabledAndIgnoreFCV()) { bob->append("listenerProcessingTime", _listenerProcessingTime.load().toBSON()); + } +} + +void TransportLayerASIO::appendStatsForFTDC(BSONObjBuilder& bob) const { + if (gFeatureFlagConnHealthMetrics.isEnabledAndIgnoreFCV()) { + BSONArrayBuilder queueDepthsArrayBuilder( + bob.subarrayStart("listenerSocketBacklogQueueDepths")); + for (const auto& record : _acceptorRecords) { + BSONObjBuilder{queueDepthsArrayBuilder.subobjStart()}.append( + record->address.toString(), record->backlogQueueDepth.load()); + } + queueDepthsArrayBuilder.done(); + } } void TransportLayerASIO::_runListener() noexcept { @@ -1307,19 +1346,19 @@ void TransportLayerASIO::_runListener() noexcept { return; } - for (auto& acceptor : _acceptors) { + for (auto& acceptorRecord : _acceptorRecords) { asio::error_code ec; - acceptor.second.listen(serverGlobalParams.listenBacklog, ec); + acceptorRecord->acceptor.listen(serverGlobalParams.listenBacklog, ec); if (ec) { LOGV2_FATAL(31339, "Error listening for new connections on {listenAddress}: {error}", "Error listening for new connections on listen address", - "listenAddrs"_attr = acceptor.first, + "listenAddrs"_attr = acceptorRecord->address, "error"_attr = ec.message()); } - _acceptConnection(acceptor.second); - LOGV2(23015, "Listening on", "address"_attr = acceptor.first.getAddr()); + _acceptConnection(acceptorRecord->acceptor); + LOGV2(23015, "Listening on", "address"_attr = acceptorRecord->address.getAddr()); } const char* ssl = "off"; @@ -1345,9 +1384,9 @@ void TransportLayerASIO::_runListener() noexcept { // Loop through the acceptors and cancel their calls to async_accept. This will prevent new // connections from being opened. - for (auto& acceptor : _acceptors) { - acceptor.second.cancel(); - auto& addr = acceptor.first; + for (auto& acceptorRecord : _acceptorRecords) { + acceptorRecord->acceptor.cancel(); + auto& addr = acceptorRecord->address; if (addr.getType() == AF_UNIX && !addr.isAnonymousUNIXSocket()) { auto path = addr.getAddr(); LOGV2( @@ -1376,7 +1415,7 @@ Status TransportLayerASIO::start() { return Status::OK(); } - invariant(_acceptors.empty()); + invariant(_acceptorRecords.empty()); return Status::OK(); } @@ -1428,11 +1467,25 @@ ReactorHandle TransportLayerASIO::getReactor(WhichReactor which) { MONGO_UNREACHABLE; } +namespace { +void handleConnectionAcceptASIOError(const asio::system_error& e) { + // Swallow connection reset errors. Connection reset errors classically present as + // asio::error::eof, but can bubble up as asio::error::invalid_argument when calling + // into socket.set_option(). + if (e.code() != asio::error::eof && e.code() != asio::error::invalid_argument) { + LOGV2_WARNING(5746600, + "Error accepting new connection: {error}", + "Error accepting new connection", + "error"_attr = e.code().message()); + } +} +} // namespace + void TransportLayerASIO::_acceptConnection(GenericAcceptor& acceptor) { auto acceptCb = [this, &acceptor](const std::error_code& ec, ASIOSession::GenericSocket peerSocket) mutable { Timer timer; - transportLayerASIOhangBeforeAccept.pauseWhileSet(); + transportLayerASIOhangDuringAcceptCallback.pauseWhileSet(); if (auto lk = stdx::lock_guard(_mutex); _isShutdown) { return; @@ -1472,15 +1525,7 @@ void TransportLayerASIO::_acceptConnection(GenericAcceptor& acceptor) { _sep->startSession(std::move(session)); } } catch (const asio::system_error& e) { - // Swallow connection reset errors. Connection reset errors classically present as - // asio::error::eof, but can bubble up as asio::error::invalid_argument when calling - // into socket.set_option(). - if (e.code() != asio::error::eof && e.code() != asio::error::invalid_argument) { - LOGV2_WARNING(5746600, - "Error accepting new connection: {error}", - "Error accepting new connection", - "error"_attr = e.code().message()); - } + handleConnectionAcceptASIOError(e); } catch (const DBException& e) { LOGV2_WARNING(23023, "Error accepting new connection: {error}", @@ -1494,9 +1539,32 @@ void TransportLayerASIO::_acceptConnection(GenericAcceptor& acceptor) { _acceptConnection(acceptor); }; + transportLayerASIOhangBeforeAcceptCallback.pauseWhileSet(); + + _trySetListenerSocketBacklogQueueDepth(acceptor); + acceptor.async_accept(*_ingressReactor, std::move(acceptCb)); } +void TransportLayerASIO::_trySetListenerSocketBacklogQueueDepth( + GenericAcceptor& acceptor) noexcept { +#ifdef __linux__ + try { + auto matchingRecord = + std::find_if(begin(_acceptorRecords), end(_acceptorRecords), [&](const auto& record) { + return acceptor.local_endpoint() == record->acceptor.local_endpoint(); + }); + invariant(matchingRecord != std::end(_acceptorRecords)); + + TcpInfoOption tcpi; + acceptor.get_option(tcpi); + (*matchingRecord)->backlogQueueDepth.store(tcpi->tcpi_unacked); + } catch (const asio::system_error& e) { + handleConnectionAcceptASIOError(e); + } +#endif +} + #ifdef MONGO_CONFIG_SSL SSLParams::SSLModes TransportLayerASIO::_sslMode() const { return static_cast<SSLParams::SSLModes>(getSSLGlobalParams().sslMode.load()); diff --git a/src/mongo/transport/transport_layer_asio.h b/src/mongo/transport/transport_layer_asio.h index 797cabb5ba6..3258c28c0ad 100644 --- a/src/mongo/transport/transport_layer_asio.h +++ b/src/mongo/transport/transport_layer_asio.h @@ -74,7 +74,10 @@ extern FailPoint transportLayerASIOshortOpportunisticReadWrite; // Cause an asyncConnect to timeout after it's successfully connected to the remote peer extern FailPoint transportLayerASIOasyncConnectTimesOut; -extern FailPoint transportLayerASIOhangBeforeAccept; +extern FailPoint transportLayerASIOhangBeforeAcceptCallback; + +extern FailPoint transportLayerASIOhangDuringAcceptCallback; + /** * A TransportLayer implementation based on ASIO networking primitives. @@ -198,7 +201,9 @@ public: void shutdown() final; - void appendStats(BSONObjBuilder* bob) const override; + void appendStatsForServerStatus(BSONObjBuilder* bob) const override; + + void appendStatsForFTDC(BSONObjBuilder& bob) const override; int listenerPort() const { return _listenerPort; @@ -208,6 +213,8 @@ public: return _listenerOptions.loadBalancerPort; } + std::vector<std::pair<SockAddr, int>> getListenerSocketBacklogQueueDepths() const; + #ifdef __linux__ BatonHandle makeBaton(OperationContext* opCtx) const override; #endif @@ -251,6 +258,8 @@ private: void _runListener() noexcept; + void _trySetListenerSocketBacklogQueueDepth(GenericAcceptor& acceptor) noexcept; + #ifdef MONGO_CONFIG_SSL SSLParams::SSLModes _sslMode() const; #endif @@ -287,7 +296,8 @@ private: synchronized_value<std::shared_ptr<const SSLConnectionContext>> _sslContext; #endif - std::vector<std::pair<SockAddr, GenericAcceptor>> _acceptors; + struct AcceptorRecord; + std::vector<std::unique_ptr<AcceptorRecord>> _acceptorRecords; // Only used if _listenerOptions.async is false. struct Listener { diff --git a/src/mongo/transport/transport_layer_asio_test.cpp b/src/mongo/transport/transport_layer_asio_test.cpp index 2a5c4677254..9d9c8536559 100644 --- a/src/mongo/transport/transport_layer_asio_test.cpp +++ b/src/mongo/transport/transport_layer_asio_test.cpp @@ -43,6 +43,7 @@ #include "mongo/db/concurrency/locker_noop_service_context_test_fixture.h" #include "mongo/db/server_options.h" #include "mongo/db/service_context_test_fixture.h" +#include "mongo/idl/server_parameter_test_util.h" #include "mongo/logv2/log.h" #include "mongo/platform/atomic_word.h" #include "mongo/platform/basic.h" @@ -319,9 +320,39 @@ public: return *_tla; } + void setUpHangDuringAcceptingFirstConnection() { + _hangDuringAcceptTimesEntered = _hangDuringAccept.setMode(FailPoint::alwaysOn); + } + + void waitForHangDuringAcceptingFirstConnection() { + _hangDuringAccept.waitForTimesEntered(_hangDuringAcceptTimesEntered + 1); + } + + void waitForHangDuringAcceptingNextConnection() { + _hangBeforeAcceptTimesEntered = _hangBeforeAccept.setMode(FailPoint::alwaysOn); + _hangDuringAccept.setMode(FailPoint::off); + _hangBeforeAccept.waitForTimesEntered(_hangBeforeAcceptTimesEntered + 1); + + _hangDuringAcceptTimesEntered = _hangDuringAccept.setMode(FailPoint::alwaysOn); + _hangBeforeAccept.setMode(FailPoint::off); + _hangDuringAccept.waitForTimesEntered(_hangDuringAcceptTimesEntered + 1); + } + + void stopHangDuringAcceptingConnection() { + _hangDuringAccept.setMode(FailPoint::off); + } + private: + RAIIServerParameterControllerForTest _featureFlagController{"featureFlagConnHealthMetrics", + true}; std::unique_ptr<transport::TransportLayerASIO> _tla; MockSEP _sep; + + FailPoint& _hangBeforeAccept = transport::transportLayerASIOhangBeforeAcceptCallback; + FailPoint& _hangDuringAccept = transport::transportLayerASIOhangDuringAcceptCallback; + + FailPoint::EntryCountT _hangBeforeAcceptTimesEntered{0}; + FailPoint::EntryCountT _hangDuringAcceptTimesEntered{0}; }; TEST(TransportLayerASIO, ListenerPortZeroTreatedAsEphemeral) { @@ -361,7 +392,7 @@ TEST(TransportLayerASIO, TCPResetAfterConnectionIsSilentlySwallowed) { tf.sep().setOnStartSession([&](auto&&) { sessionsCreated.fetchAndAdd(1); }); LOGV2(6109515, "connecting"); - auto& fp = transport::transportLayerASIOhangBeforeAccept; + auto& fp = transport::transportLayerASIOhangDuringAcceptCallback; auto timesEntered = fp.setMode(FailPoint::alwaysOn); ConnectionThread connectThread(tf.tla().listenerPort(), &setNoLinger); fp.waitForTimesEntered(timesEntered + 1); @@ -376,6 +407,59 @@ TEST(TransportLayerASIO, TCPResetAfterConnectionIsSilentlySwallowed) { ASSERT_EQ(sessionsCreated.load(), 0); } +#ifdef __linux__ +/** + * Test that the server successfully captures the TCP socket queue depth, and places the value both + * into the TransportLayerASIO class and FTDC output. + */ +TEST(TransportLayerASIO, TCPCheckQueueDepth) { + // Set the listenBacklog to a parameter greater than the number of connection threads we intend + // to create. + serverGlobalParams.listenBacklog = 10; + TestFixture tf; + + LOGV2(6400501, "Starting and hanging three connection threads"); + tf.setUpHangDuringAcceptingFirstConnection(); + + ConnectionThread connectThread1(tf.tla().listenerPort()); + ConnectionThread connectThread2(tf.tla().listenerPort()); + ConnectionThread connectThread3(tf.tla().listenerPort()); + + tf.waitForHangDuringAcceptingFirstConnection(); + connectThread1.wait(); + connectThread2.wait(); + connectThread3.wait(); + + LOGV2(6400502, "Processing one connection thread"); + + tf.waitForHangDuringAcceptingNextConnection(); + + const auto& depths = tf.tla().getListenerSocketBacklogQueueDepths(); + ASSERT_EQ(depths.size(), 1); + + auto depth = depths[0]; + ASSERT_EQ(depth.first.getPort(), tf.tla().listenerPort()); + ASSERT_EQ(depth.second, 2); + + + BSONObjBuilder tlaFTDCBuilder; + tf.tla().appendStatsForFTDC(tlaFTDCBuilder); + BSONObj tlaFTDCStats = tlaFTDCBuilder.obj(); + + const auto& queueDepthsArray = + tlaFTDCStats.getField("listenerSocketBacklogQueueDepths").Array(); + ASSERT_EQ(queueDepthsArray.size(), 1); + + const auto& queueDepthObj = queueDepthsArray[0].Obj(); + ASSERT_EQ(HostAndPort(queueDepthObj.firstElementFieldName()).port(), tf.tla().listenerPort()); + ASSERT_EQ(queueDepthObj.firstElement().Int(), 2); + + LOGV2(6400503, "Stopping failpoints, shutting down test"); + + tf.stopHangDuringAcceptingConnection(); +} +#endif + TEST(TransportLayerASIO, ThrowOnNetworkErrorInEnsureSync) { TestFixture tf; Notification<SessionThread*> mockSessionCreated; diff --git a/src/mongo/transport/transport_layer_ftdc_collector.h b/src/mongo/transport/transport_layer_ftdc_collector.h new file mode 100644 index 00000000000..5c5744d8c9c --- /dev/null +++ b/src/mongo/transport/transport_layer_ftdc_collector.h @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2022-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include "mongo/db/ftdc/collector.h" +#include "mongo/db/operation_context.h" + +namespace mongo::transport { + +class TransportLayerFTDCCollector final : public FTDCCollectorInterface { +public: + void collect(OperationContext* opCtx, BSONObjBuilder& builder) override { + if (auto tl = opCtx->getServiceContext()->getTransportLayer()) { + tl->appendStatsForFTDC(builder); + } + } + + std::string name() const override { + return "transportLayerStats"; + } +}; + +} // namespace mongo::transport diff --git a/src/mongo/transport/transport_layer_manager.cpp b/src/mongo/transport/transport_layer_manager.cpp index 7b2468a8848..32702186ea0 100644 --- a/src/mongo/transport/transport_layer_manager.cpp +++ b/src/mongo/transport/transport_layer_manager.cpp @@ -117,8 +117,12 @@ Status TransportLayerManager::setup() { return Status::OK(); } -void TransportLayerManager::appendStats(BSONObjBuilder* bob) const { - _foreach([&](const TransportLayer* tl) { tl->appendStats(bob); }); +void TransportLayerManager::appendStatsForServerStatus(BSONObjBuilder* bob) const { + _foreach([&](const TransportLayer* tl) { tl->appendStatsForServerStatus(bob); }); +} + +void TransportLayerManager::appendStatsForFTDC(BSONObjBuilder& bob) const { + _foreach([&](const TransportLayer* tl) { tl->appendStatsForFTDC(bob); }); } Status TransportLayerManager::addAndStartTransportLayer(std::unique_ptr<TransportLayer> tl) { diff --git a/src/mongo/transport/transport_layer_manager.h b/src/mongo/transport/transport_layer_manager.h index 750712b2811..b446197f31c 100644 --- a/src/mongo/transport/transport_layer_manager.h +++ b/src/mongo/transport/transport_layer_manager.h @@ -81,7 +81,8 @@ public: Status start() override; void shutdown() override; Status setup() override; - void appendStats(BSONObjBuilder* bob) const override; + void appendStatsForServerStatus(BSONObjBuilder* bob) const override; + void appendStatsForFTDC(BSONObjBuilder& bob) const override; ReactorHandle getReactor(WhichReactor which) override; diff --git a/src/mongo/util/net/sockaddr.cpp b/src/mongo/util/net/sockaddr.cpp index 2b6d20ec865..abca48f5c9a 100644 --- a/src/mongo/util/net/sockaddr.cpp +++ b/src/mongo/util/net/sockaddr.cpp @@ -294,6 +294,16 @@ unsigned SockAddr::getPort() const { } } +void SockAddr::setPort(int port) { + if (auto type = getType(); type == AF_INET) { + as<sockaddr_in>().sin_port = htons(port); + } else if (type == AF_INET6) { + as<sockaddr_in6>().sin6_port = htons(port); + } else { + massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); + } +} + std::string SockAddr::getAddr() const { switch (getType()) { case AF_INET: diff --git a/src/mongo/util/net/sockaddr.h b/src/mongo/util/net/sockaddr.h index 79e08ba1045..f62e6c25702 100644 --- a/src/mongo/util/net/sockaddr.h +++ b/src/mongo/util/net/sockaddr.h @@ -127,6 +127,7 @@ struct SockAddr { sa_family_t getType() const; unsigned getPort() const; + void setPort(int port); std::string getAddr() const; |