summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Williams <louis.williams@mongodb.com>2020-12-15 17:09:46 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-12-15 22:48:51 +0000
commite9ba0db9a0b5f4e7116670118cf10184a14f2e40 (patch)
treeb28b5ebe86c72d59ca0e73c1f7cbd548ee77235c
parent843390351dc7cd2e30df9f823b3b37ccff6ae274 (diff)
downloadmongo-e9ba0db9a0b5f4e7116670118cf10184a14f2e40.tar.gz
SERVER-53216 Report number of databases in resource consumption serverStatus section
-rw-r--r--jstests/noPassthrough/aggregate_operation_metrics.js28
-rw-r--r--src/mongo/db/stats/resource_consumption_metrics.cpp39
-rw-r--r--src/mongo/db/stats/resource_consumption_metrics.h5
3 files changed, 51 insertions, 21 deletions
diff --git a/jstests/noPassthrough/aggregate_operation_metrics.js b/jstests/noPassthrough/aggregate_operation_metrics.js
index a1b1ff7a2cc..62533397cf7 100644
--- a/jstests/noPassthrough/aggregate_operation_metrics.js
+++ b/jstests/noPassthrough/aggregate_operation_metrics.js
@@ -57,10 +57,10 @@ let getDBMetrics = (adminDB) => {
return allMetrics;
};
-let getGlobalCpuTime = (db) => {
- let ss = db.serverStatus({resourceConsumption: true});
+let getServerStatusMetrics = (db) => {
+ let ss = db.serverStatus();
assert(ss.hasOwnProperty('resourceConsumption'), ss);
- return ss.resourceConsumption.cpuNanos;
+ return ss.resourceConsumption;
};
// Perform very basic reads and writes on two different databases.
@@ -75,10 +75,6 @@ const db2 = primary.getDB(db2Name);
assert.commandWorked(db2.coll1.insert({a: 1}));
assert.commandWorked(db2.coll2.insert({a: 1}));
-// The 'resourceConsumption' field should not be included in serverStatus by default.
-let ss = db1.serverStatus();
-assert(!ss.hasOwnProperty('resourceConsumption'), ss);
-
const secondary = rst.getSecondary();
[primary, secondary].forEach(function(node) {
jsTestLog("Testing node: " + node);
@@ -88,7 +84,7 @@ const secondary = rst.getSecondary();
rst.awaitReplication();
const adminDB = node.getDB('admin');
- let initialCpuTime = getGlobalCpuTime(adminDB);
+ let initialCpuTime = getServerStatusMetrics(adminDB).cpuNanos;
adminDB.aggregate([{$operationMetrics: {clearMetrics: true}}]);
@@ -117,6 +113,10 @@ const secondary = rst.getSecondary();
assertMetricsExist(allMetrics[db1Name]);
assertMetricsExist(allMetrics[db2Name]);
+ let ssMetrics = getServerStatusMetrics(adminDB);
+ assert.eq(ssMetrics.numMetrics, 2);
+ assert.gt(ssMetrics.memUsage, 0);
+
// Ensure read metrics are attributed to the correct replication state.
let lastDocBytesRead;
if (node === primary) {
@@ -148,7 +148,7 @@ const secondary = rst.getSecondary();
// CPU time aggregation is only supported on Linux.
if (isLinux) {
// Ensure the CPU time is increasing.
- let lastCpuTime = getGlobalCpuTime(adminDB);
+ let lastCpuTime = getServerStatusMetrics(adminDB).cpuNanos;
assert.gt(lastCpuTime, initialCpuTime);
// Ensure the global CPU time matches the aggregated time for both databases.
@@ -207,6 +207,16 @@ const secondary = rst.getSecondary();
cursor = adminDB.aggregate([{$operationMetrics: {}}]);
assert.eq(cursor.itcount(), 0);
+ // Ensure the serverStatus metrics are cleared except for cpuNanos.
+ ssMetrics = getServerStatusMetrics(adminDB);
+ assert.eq(0, ssMetrics.numMetrics);
+ assert.eq(0, ssMetrics.memUsage);
+ if (isLinux) {
+ assert.neq(0, ssMetrics.cpuNanos);
+ } else {
+ assert.eq(0, ssMetrics.cpuNanos);
+ }
+
// Insert something and ensure metrics are still reporting.
assert.commandWorked(db1.coll3.insert({a: 1}));
rst.awaitReplication();
diff --git a/src/mongo/db/stats/resource_consumption_metrics.cpp b/src/mongo/db/stats/resource_consumption_metrics.cpp
index 49c879cb272..fbc53138f3c 100644
--- a/src/mongo/db/stats/resource_consumption_metrics.cpp
+++ b/src/mongo/db/stats/resource_consumption_metrics.cpp
@@ -45,21 +45,23 @@ const OperationContext::Decoration<ResourceConsumption::MetricsCollector> getMet
const ServiceContext::Decoration<ResourceConsumption> getGlobalResourceConsumption =
ServiceContext::declareDecoration<ResourceConsumption>();
-static const char kPrimaryMetrics[] = "primaryMetrics";
-static const char kSecondaryMetrics[] = "secondaryMetrics";
+static const char kCpuNanos[] = "cpuNanos";
+static const char kCursorSeeks[] = "cursorSeeks";
static const char kDocBytesRead[] = "docBytesRead";
+static const char kDocBytesWritten[] = "docBytesWritten";
static const char kDocUnitsRead[] = "docUnitsRead";
+static const char kDocUnitsReturned[] = "docUnitsReturned";
+static const char kDocUnitsWritten[] = "docUnitsWritten";
static const char kIdxEntryBytesRead[] = "idxEntryBytesRead";
+static const char kIdxEntryBytesWritten[] = "idxEntryBytesWritten";
static const char kIdxEntryUnitsRead[] = "idxEntryUnitsRead";
+static const char kIdxEntryUnitsWritten[] = "idxEntryUnitsWritten";
static const char kKeysSorted[] = "keysSorted";
+static const char kMemUsage[] = "memUsage";
+static const char kNumMetrics[] = "numMetrics";
+static const char kPrimaryMetrics[] = "primaryMetrics";
+static const char kSecondaryMetrics[] = "secondaryMetrics";
static const char kSorterSpills[] = "sorterSpills";
-static const char kCpuNanos[] = "cpuNanos";
-static const char kDocBytesWritten[] = "docBytesWritten";
-static const char kDocUnitsWritten[] = "docUnitsWritten";
-static const char kIdxEntryBytesWritten[] = "idxEntryBytesWritten";
-static const char kIdxEntryUnitsWritten[] = "idxEntryUnitsWritten";
-static const char kDocUnitsReturned[] = "docUnitsReturned";
-static const char kCursorSeeks[] = "cursorSeeks";
inline void appendNonZeroMetric(BSONObjBuilder* builder, const char* name, long long value) {
if (value != 0) {
@@ -74,10 +76,10 @@ class ResourceConsumptionSSS : public ServerStatusSection {
public:
ResourceConsumptionSSS() : ServerStatusSection("resourceConsumption") {}
- // Do not include this metric by default. It is likely to be misleading for diagnostic purposes
- // because it does not include the CPU time for every operation or every command.
+ // Do not include this section unless metrics aggregation is enabled. It will not have populated
+ // data otherwise.
bool includeByDefault() const override {
- return false;
+ return ResourceConsumption::isMetricsAggregationEnabled();
}
BSONObj generateSection(OperationContext* opCtx, const BSONElement& configElem) const override {
@@ -87,6 +89,14 @@ public:
}
BSONObjBuilder builder;
builder.append(kCpuNanos, durationCount<Nanoseconds>(resourceConsumption.getCpuTime()));
+
+ // The memory usage we report only estimates the amount of memory from the metrics
+ // themselves, and does not include the overhead of the map container or its keys.
+ auto numMetrics = resourceConsumption.getNumDbMetrics();
+ builder.append(
+ kMemUsage,
+ static_cast<long long>(numMetrics * sizeof(ResourceConsumption::AggregatedMetrics)));
+ builder.append(kNumMetrics, static_cast<long long>(numMetrics));
return builder.obj();
}
} resourceConsumptionMetricSSM;
@@ -334,6 +344,11 @@ ResourceConsumption::MetricsMap ResourceConsumption::getDbMetrics() const {
return _dbMetrics;
}
+size_t ResourceConsumption::getNumDbMetrics() const {
+ stdx::lock_guard<Mutex> lk(_mutex);
+ return _dbMetrics.size();
+}
+
ResourceConsumption::MetricsMap ResourceConsumption::getAndClearDbMetrics() {
stdx::lock_guard<Mutex> lk(_mutex);
MetricsMap newMap;
diff --git a/src/mongo/db/stats/resource_consumption_metrics.h b/src/mongo/db/stats/resource_consumption_metrics.h
index 1dc401aef88..5e098b5c730 100644
--- a/src/mongo/db/stats/resource_consumption_metrics.h
+++ b/src/mongo/db/stats/resource_consumption_metrics.h
@@ -450,6 +450,11 @@ public:
MetricsMap getDbMetrics() const;
/**
+ * Returns the number of databases with aggregated metrics.
+ */
+ size_t getNumDbMetrics() const;
+
+ /**
* Returns the per-database metrics map and then clears the contents. This attempts to swap and
* return the metrics map rather than making a full copy like getDbMetrics.
*/