diff options
author | A. Jesse Jiryu Davis <jesse@mongodb.com> | 2019-05-16 14:48:19 -0400 |
---|---|---|
committer | A. Jesse Jiryu Davis <jesse@mongodb.com> | 2019-05-21 16:35:25 -0400 |
commit | f30e70b5d1ebae87f373de108314993e58309739 (patch) | |
tree | 97b5f921d9329cd573fc76d536105c50196d04d2 /src/mongo | |
parent | db55694f289d99db4f808a44643130818f3048a4 (diff) | |
download | mongo-f30e70b5d1ebae87f373de108314993e58309739.tar.gz |
SERVER-36099 Trim FTDC connection pool stats
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/client/replica_set_monitor.cpp | 35 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor.h | 5 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor_manager.cpp | 9 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor_manager.h | 5 | ||||
-rw-r--r-- | src/mongo/db/commands/conn_pool_stats.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/ftdc/SConscript | 5 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_mongos.cpp | 45 | ||||
-rw-r--r-- | src/mongo/dbtests/replica_set_monitor_test.cpp | 3 | ||||
-rw-r--r-- | src/mongo/executor/connection_pool_stats.cpp | 25 | ||||
-rw-r--r-- | src/mongo/executor/connection_pool_stats.h | 2 | ||||
-rw-r--r-- | src/mongo/shell/shell_utils.cpp | 6 |
11 files changed, 109 insertions, 35 deletions
diff --git a/src/mongo/client/replica_set_monitor.cpp b/src/mongo/client/replica_set_monitor.cpp index 21b2e42b4ad..25927212728 100644 --- a/src/mongo/client/replica_set_monitor.cpp +++ b/src/mongo/client/replica_set_monitor.cpp @@ -157,6 +157,15 @@ struct HostNotIn { const std::set<HostAndPort>& _hosts; }; +int32_t pingTimeMillis(const Node& node) { + auto latencyMillis = node.latencyMicros / 1000; + if (latencyMillis > numeric_limits<int32_t>::max()) { + // In particular, Node::unknownLatency does not fit in an int32. + return numeric_limits<int32_t>::max(); + } + return latencyMillis; +} + /** * Replica set refresh period on the task executor. */ @@ -397,12 +406,21 @@ ReplicaSetChangeNotifier& ReplicaSetMonitor::getNotifier() { } // TODO move to correct order with non-statics before pushing -void ReplicaSetMonitor::appendInfo(BSONObjBuilder& bsonObjBuilder) const { +void ReplicaSetMonitor::appendInfo(BSONObjBuilder& bsonObjBuilder, bool forFTDC) const { stdx::lock_guard<stdx::mutex> lk(_state->mutex); + BSONObjBuilder monitorInfo(bsonObjBuilder.subobjStart(getName())); + if (forFTDC) { + for (size_t i = 0; i < _state->nodes.size(); i++) { + const Node& node = _state->nodes[i]; + monitorInfo.appendNumber(node.host.toString(), pingTimeMillis(node)); + } + return; + } + // NOTE: the format here must be consistent for backwards compatibility - BSONArrayBuilder hosts(bsonObjBuilder.subarrayStart("hosts")); - for (unsigned i = 0; i < _state->nodes.size(); i++) { + BSONArrayBuilder hosts(monitorInfo.subarrayStart("hosts")); + for (size_t i = 0; i < _state->nodes.size(); i++) { const Node& node = _state->nodes[i]; BSONObjBuilder builder; @@ -411,15 +429,7 @@ void ReplicaSetMonitor::appendInfo(BSONObjBuilder& bsonObjBuilder) const { builder.append("ismaster", node.isMaster); // intentionally not camelCase builder.append("hidden", false); // we don't keep hidden nodes in the set builder.append("secondary", node.isUp && !node.isMaster); - - int32_t pingTimeMillis = 0; - if (node.latencyMicros / 1000 > numeric_limits<int32_t>::max()) { - // In particular, Node::unknownLatency does not fit in an int32. - pingTimeMillis = numeric_limits<int32_t>::max(); - } else { - pingTimeMillis = node.latencyMicros / 1000; - } - builder.append("pingTimeMillis", pingTimeMillis); + builder.append("pingTimeMillis", pingTimeMillis(node)); if (!node.tags.isEmpty()) { builder.append("tags", node.tags); @@ -427,7 +437,6 @@ void ReplicaSetMonitor::appendInfo(BSONObjBuilder& bsonObjBuilder) const { hosts.append(builder.obj()); } - hosts.done(); } void ReplicaSetMonitor::shutdown() { diff --git a/src/mongo/client/replica_set_monitor.h b/src/mongo/client/replica_set_monitor.h index a306b1b9547..b28364c6a25 100644 --- a/src/mongo/client/replica_set_monitor.h +++ b/src/mongo/client/replica_set_monitor.h @@ -155,9 +155,10 @@ public: bool contains(const HostAndPort& server) const; /** - * Writes information about our cached view of the set to a BSONObjBuilder. + * Writes information about our cached view of the set to a BSONObjBuilder. If + * forFTDC, trim to minimize its size for full-time diagnostic data capture. */ - void appendInfo(BSONObjBuilder& b) const; + void appendInfo(BSONObjBuilder& b, bool forFTDC = false) const; /** * Returns true if the monitor knows a usable primary from it's interal view. diff --git a/src/mongo/client/replica_set_monitor_manager.cpp b/src/mongo/client/replica_set_monitor_manager.cpp index f8f6078b23a..dff3d8a16c4 100644 --- a/src/mongo/client/replica_set_monitor_manager.cpp +++ b/src/mongo/client/replica_set_monitor_manager.cpp @@ -203,19 +203,22 @@ void ReplicaSetMonitorManager::removeAllMonitors() { } } -void ReplicaSetMonitorManager::report(BSONObjBuilder* builder) { +void ReplicaSetMonitorManager::report(BSONObjBuilder* builder, bool forFTDC) { // Don't hold _mutex the whole time to avoid ever taking a monitor's mutex while holding the // manager's mutex. Otherwise we could get a deadlock between the manager's, monitor's, and // ShardRegistry's mutex due to the ReplicaSetMonitor's AsynchronousConfigChangeHook potentially // calling ShardRegistry::updateConfigServerConnectionString. auto setNames = getAllSetNames(); + + BSONObjBuilder setStats( + builder->subobjStart(forFTDC ? "replicaSetPingTimesMillis" : "replicaSets")); + for (const auto& setName : setNames) { auto monitor = getMonitor(setName); if (!monitor) { continue; } - BSONObjBuilder monitorInfo(builder->subobjStart(setName)); - monitor->appendInfo(monitorInfo); + monitor->appendInfo(setStats, forFTDC); } } diff --git a/src/mongo/client/replica_set_monitor_manager.h b/src/mongo/client/replica_set_monitor_manager.h index 1adf42fb16d..b0a08f8f4e5 100644 --- a/src/mongo/client/replica_set_monitor_manager.h +++ b/src/mongo/client/replica_set_monitor_manager.h @@ -86,9 +86,10 @@ public: void shutdown(); /** - * Reports information about the replica sets tracked by us, for diagnostic purposes. + * Reports information about the replica sets tracked by us, for diagnostic purposes. If + * forFTDC, trim to minimize its size for full-time diagnostic data capture. */ - void report(BSONObjBuilder* builder); + void report(BSONObjBuilder* builder, bool forFTDC = false); /** * Returns an executor for running RSM tasks. diff --git a/src/mongo/db/commands/conn_pool_stats.cpp b/src/mongo/db/commands/conn_pool_stats.cpp index 604472d5a13..5a6684f3fec 100644 --- a/src/mongo/db/commands/conn_pool_stats.cpp +++ b/src/mongo/db/commands/conn_pool_stats.cpp @@ -107,9 +107,7 @@ public: stats.appendToBSON(result); // Always report all replica sets being tracked. - BSONObjBuilder setStats(result.subobjStart("replicaSets")); - globalRSMonitorManager.report(&setStats); - setStats.doneFast(); + globalRSMonitorManager.report(&result); return true; } diff --git a/src/mongo/db/ftdc/SConscript b/src/mongo/db/ftdc/SConscript index f342e3b079a..45852f61159 100644 --- a/src/mongo/db/ftdc/SConscript +++ b/src/mongo/db/ftdc/SConscript @@ -83,8 +83,11 @@ env.Library( 'ftdc_mongos.cpp', ], LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/client/clientdriver_minimal', + '$BUILD_DIR/mongo/executor/task_executor_pool', '$BUILD_DIR/mongo/idl/server_parameter', - 'ftdc_server' + '$BUILD_DIR/mongo/s/grid', + 'ftdc_server', ], ) diff --git a/src/mongo/db/ftdc/ftdc_mongos.cpp b/src/mongo/db/ftdc/ftdc_mongos.cpp index 6e70f3013a8..1a76c79bcf2 100644 --- a/src/mongo/db/ftdc/ftdc_mongos.cpp +++ b/src/mongo/db/ftdc/ftdc_mongos.cpp @@ -34,18 +34,59 @@ #include <boost/filesystem.hpp> +#include "mongo/client/connpool.h" +#include "mongo/client/dbclient_connection.h" +#include "mongo/client/global_conn_pool.h" #include "mongo/db/ftdc/controller.h" #include "mongo/db/ftdc/ftdc_server.h" +#include "mongo/db/repl/replication_coordinator.h" +#include "mongo/executor/connection_pool_stats.h" +#include "mongo/executor/task_executor_pool.h" +#include "mongo/s/grid.h" #include "mongo/stdx/thread.h" #include "mongo/util/log.h" #include "mongo/util/synchronized_value.h" namespace mongo { +class ConnPoolStatsCollector : public FTDCCollectorInterface { +public: + void collect(OperationContext* opCtx, BSONObjBuilder& builder) override { + executor::ConnectionPoolStats stats{}; + + // Global connection pool connections. + globalConnPool.appendConnectionStats(&stats); + + // Sharding connections. + { + auto const grid = Grid::get(opCtx); + if (grid->getExecutorPool()) { + grid->getExecutorPool()->appendConnectionStats(&stats); + } + + auto const customConnPoolStatsFn = grid->getCustomConnectionPoolStatsFn(); + if (customConnPoolStatsFn) { + customConnPoolStatsFn(&stats); + } + } + + // Output to a BSON object. + builder.appendNumber("numClientConnections", DBClientConnection::getNumConnections()); + builder.appendNumber("numAScopedConnections", AScopedConnection::getNumConnections()); + stats.appendToBSON(builder, true /* forFTDC */); + + // All replica sets being tracked. + globalRSMonitorManager.report(&builder, true /* forFTDC */); + } + + std::string name() const override { + return "connPoolStats"; + } +}; + void registerMongoSCollectors(FTDCController* controller) { // PoolStats - controller->addPeriodicCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>( - "connPoolStats", "connPoolStats", "", BSON("connPoolStats" << 1))); + controller->addPeriodicCollector(stdx::make_unique<ConnPoolStatsCollector>()); } void startMongoSFTDC() { diff --git a/src/mongo/dbtests/replica_set_monitor_test.cpp b/src/mongo/dbtests/replica_set_monitor_test.cpp index f168d7bbad9..2e0c5d612c2 100644 --- a/src/mongo/dbtests/replica_set_monitor_test.cpp +++ b/src/mongo/dbtests/replica_set_monitor_test.cpp @@ -170,7 +170,8 @@ TEST(ReplicaSetMonitorTest, PrimaryRemovedFromSetStress) { replMonitor->appendInfo(monitorStateBuilder); BSONObj monitorState = monitorStateBuilder.done(); - BSONElement hostsElem = monitorState["hosts"]; + // Stats are under the replica set name, "test". + BSONElement hostsElem = monitorState["test"]["hosts"]; BSONElement addrElem = hostsElem[mongo::str::stream() << idxToRemove]["addr"]; hostToRemove = addrElem.String(); } diff --git a/src/mongo/executor/connection_pool_stats.cpp b/src/mongo/executor/connection_pool_stats.cpp index d2f0fbfa8cb..b1d558bfd8b 100644 --- a/src/mongo/executor/connection_pool_stats.cpp +++ b/src/mongo/executor/connection_pool_stats.cpp @@ -69,24 +69,39 @@ void ConnectionPoolStats::updateStatsForHost(std::string pool, totalRefreshing += newStats.refreshing; } -void ConnectionPoolStats::appendToBSON(mongo::BSONObjBuilder& result) { +void ConnectionPoolStats::appendToBSON(mongo::BSONObjBuilder& result, bool forFTDC) { result.appendNumber("totalInUse", totalInUse); result.appendNumber("totalAvailable", totalAvailable); result.appendNumber("totalCreated", totalCreated); result.appendNumber("totalRefreshing", totalRefreshing); + if (forFTDC) { + BSONObjBuilder poolBuilder(result.subobjStart("connectionsInUsePerPool")); + for (const auto& pool : statsByPool) { + BSONObjBuilder poolInfo(poolBuilder.subobjStart(pool.first)); + auto& poolStats = pool.second; + poolInfo.appendNumber("poolInUse", poolStats.inUse); + for (const auto& host : statsByPoolHost[pool.first]) { + auto hostStats = host.second; + poolInfo.appendNumber(host.first.toString(), hostStats.inUse); + } + } + + return; + } + { BSONObjBuilder poolBuilder(result.subobjStart("pools")); - for (auto&& pool : statsByPool) { + for (const auto& pool : statsByPool) { BSONObjBuilder poolInfo(poolBuilder.subobjStart(pool.first)); - auto poolStats = pool.second; + auto& poolStats = pool.second; poolInfo.appendNumber("poolInUse", poolStats.inUse); poolInfo.appendNumber("poolAvailable", poolStats.available); poolInfo.appendNumber("poolCreated", poolStats.created); poolInfo.appendNumber("poolRefreshing", poolStats.refreshing); - for (auto&& host : statsByPoolHost[pool.first]) { + for (const auto& host : statsByPoolHost[pool.first]) { BSONObjBuilder hostInfo(poolInfo.subobjStart(host.first.toString())); - auto hostStats = host.second; + auto& hostStats = host.second; hostInfo.appendNumber("inUse", hostStats.inUse); hostInfo.appendNumber("available", hostStats.available); hostInfo.appendNumber("created", hostStats.created); diff --git a/src/mongo/executor/connection_pool_stats.h b/src/mongo/executor/connection_pool_stats.h index 374ba60aa62..0e5ec17407a 100644 --- a/src/mongo/executor/connection_pool_stats.h +++ b/src/mongo/executor/connection_pool_stats.h @@ -60,7 +60,7 @@ struct ConnectionStatsPer { struct ConnectionPoolStats { void updateStatsForHost(std::string pool, HostAndPort host, ConnectionStatsPer newStats); - void appendToBSON(mongo::BSONObjBuilder& result); + void appendToBSON(mongo::BSONObjBuilder& result, bool forFTDC = false); size_t totalInUse = 0u; size_t totalAvailable = 0u; diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp index 02fa51ed004..c26941d02de 100644 --- a/src/mongo/shell/shell_utils.cpp +++ b/src/mongo/shell/shell_utils.cpp @@ -310,7 +310,8 @@ BSONObj replMonitorStats(const BSONObj& a, void* data) { "replMonitorStats requires a single string argument (the ReplSet name)", a.nFields() == 1 && a.firstElement().type() == String); - ReplicaSetMonitorPtr rsm = ReplicaSetMonitor::get(a.firstElement().valuestrsafe()); + auto name = a.firstElement().valuestrsafe(); + ReplicaSetMonitorPtr rsm = ReplicaSetMonitor::get(name); if (!rsm) { return BSON("" << "no ReplSetMonitor exists by that name"); @@ -318,7 +319,8 @@ BSONObj replMonitorStats(const BSONObj& a, void* data) { BSONObjBuilder result; rsm->appendInfo(result); - return result.obj(); + // Stats are like {replSetName: {hosts: [{ ... }, { ... }]}}. + return result.obj()[name].Obj().getOwned(); } BSONObj useWriteCommandsDefault(const BSONObj& a, void* data) { |