summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/core/collStats_numericOnly.js43
-rw-r--r--src/mongo/db/ftdc/ftdc_mongod.cpp3
-rw-r--r--src/mongo/db/pipeline/storage_stats_spec.idl3
-rw-r--r--src/mongo/db/stats/storage_stats.cpp7
-rw-r--r--src/mongo/db/storage/devnull/devnull_kv_engine.cpp6
-rw-r--r--src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h6
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h6
-rw-r--r--src/mongo/db/storage/record_store.h21
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp35
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h10
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp26
11 files changed, 137 insertions, 29 deletions
diff --git a/jstests/core/collStats_numericOnly.js b/jstests/core/collStats_numericOnly.js
new file mode 100644
index 00000000000..e1bc22ccb4a
--- /dev/null
+++ b/jstests/core/collStats_numericOnly.js
@@ -0,0 +1,43 @@
+/**
+ * Tests that collStats does not return expensive creationString field when numericOnly is true.
+ * @tags: [requires_wiredtiger, requires_collstats]
+ */
+(function() {
+"use strict";
+
+// Grab the storage engine, default is wiredTiger
+var storageEngine = jsTest.options().storageEngine || "wiredTiger";
+
+// Although this test is tagged with 'requires_wiredtiger', this is not sufficient for ensuring
+// that the parallel suite runs this test only on WT configurations. See SERVER-36181.
+if (storageEngine !== 'wiredTiger') {
+ jsTest.log('Skipping test because storageEngine is not "wiredTiger"');
+ return;
+}
+
+const dbName = "test";
+const collName = "collStats_numericOnly";
+
+const testDB = db.getSiblingDB(dbName);
+const testColl = testDB.getCollection(collName);
+
+assert.commandWorked(testColl.insert({a: 1}));
+
+{
+ // The collStats result should not contain the creationString field.
+ const res = assert.commandWorked(testDB.runCommand({collStats: collName, numericOnly: true}));
+ assert(res.hasOwnProperty("wiredTiger"));
+ assert(res.wiredTiger.hasOwnProperty("cache"));
+ assert(!res.wiredTiger.hasOwnProperty("creationString"));
+ assert(!res.wiredTiger.hasOwnProperty("metadata"));
+}
+
+{
+ // By default the creationString field should exist.
+ const res = assert.commandWorked(testDB.runCommand({collStats: collName}));
+ assert(res.hasOwnProperty("wiredTiger"));
+ assert(res.wiredTiger.hasOwnProperty("cache"));
+ assert(res.wiredTiger.hasOwnProperty("creationString"));
+ assert(res.wiredTiger.hasOwnProperty("metadata"));
+}
+})();
diff --git a/src/mongo/db/ftdc/ftdc_mongod.cpp b/src/mongo/db/ftdc/ftdc_mongod.cpp
index abe40e9a081..5f2a874d3e7 100644
--- a/src/mongo/db/ftdc/ftdc_mongod.cpp
+++ b/src/mongo/db/ftdc/ftdc_mongod.cpp
@@ -60,7 +60,8 @@ void registerMongoDCollectors(FTDCController* controller) {
"local",
BSON("collStats"
<< "oplog.rs"
- << "waitForLock" << false)));
+ << "waitForLock" << false
+ << "numericOnly" << true)));
if (serverGlobalParams.clusterRole != ClusterRole::ShardServer) {
// GetDefaultRWConcern
controller->addOnRotateCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
diff --git a/src/mongo/db/pipeline/storage_stats_spec.idl b/src/mongo/db/pipeline/storage_stats_spec.idl
index 74c6775673c..8052f09de51 100644
--- a/src/mongo/db/pipeline/storage_stats_spec.idl
+++ b/src/mongo/db/pipeline/storage_stats_spec.idl
@@ -48,3 +48,6 @@ structs:
waitForLock:
type: optionalBool
default: true
+ numericOnly:
+ type: optionalBool
+ default: false
diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp
index a2253d49706..7bf30e0cd3d 100644
--- a/src/mongo/db/stats/storage_stats.cpp
+++ b/src/mongo/db/stats/storage_stats.cpp
@@ -53,6 +53,7 @@ Status appendCollectionStorageStats(OperationContext* opCtx,
auto scale = storageStatsSpec.getScale().value_or(1);
bool verbose = storageStatsSpec.getVerbose();
bool waitForLock = storageStatsSpec.getWaitForLock();
+ bool numericOnly = storageStatsSpec.getNumericOnly();
const auto bucketNss = nss.makeTimeseriesBucketsNamespace();
const auto isTimeseries = nss.isTimeseriesBucketsCollection() ||
@@ -122,7 +123,11 @@ Status appendCollectionStorageStats(OperationContext* opCtx,
result->appendNumber("maxSize", collection->getCappedMaxSize() / scale);
}
- recordStore->appendCustomStats(opCtx, result, scale);
+ if (numericOnly) {
+ recordStore->appendNumericCustomStats(opCtx, result, scale);
+ } else {
+ recordStore->appendAllCustomStats(opCtx, result, scale);
+ }
const IndexCatalog* indexCatalog = collection->getIndexCatalog();
result->append("nindexes", indexCatalog->numIndexesTotal(opCtx));
diff --git a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
index b244ce0ebb1..982a1a8e318 100644
--- a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
+++ b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp
@@ -145,9 +145,9 @@ public:
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive) {}
- virtual void appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const {
+ virtual void appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {
result->appendNumber("numInserts", _numInserts);
}
diff --git a/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h b/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
index 5170412252f..536d4b8d9c8 100644
--- a/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
+++ b/src/mongo/db/storage/devnull/ephemeral_catalog_record_store.h
@@ -90,9 +90,9 @@ public:
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive);
- virtual void appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const {}
+ virtual void appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {}
virtual int64_t storageSize(OperationContext* opCtx,
BSONObjBuilder* extraInfo = nullptr,
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
index a000617d1fe..18a438303f5 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_record_store.h
@@ -96,9 +96,9 @@ public:
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive);
- virtual void appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const {}
+ virtual void appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {}
virtual void updateStatsAfterRepair(OperationContext* opCtx,
long long numRecords,
diff --git a/src/mongo/db/storage/record_store.h b/src/mongo/db/storage/record_store.h
index bd5ad8ebd8f..77a6d6e2782 100644
--- a/src/mongo/db/storage/record_store.h
+++ b/src/mongo/db/storage/record_store.h
@@ -491,11 +491,24 @@ public:
/**
* @param scaleSize - amount by which to scale size metrics
- * appends any custom stats from the RecordStore or other unique stats
+ * Appends any numeric custom stats from the RecordStore or other unique stats, it should
+ * avoid any expensive calls
*/
- virtual void appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const = 0;
+ virtual void appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const = 0;
+
+
+ /**
+ * @param scaleSize - amount by which to scale size metrics
+ * Appends all custom stats from the RecordStore or other unique stats, it can be more
+ * expensive than RecordStore::appendNumericCustomStats
+ */
+ virtual void appendAllCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {
+ appendNumericCustomStats(opCtx, result, scale);
+ };
/**
* When we write to an oplog, we call this so that that the storage engine can manage the
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index cb0837ddd01..566745b8223 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -113,6 +113,16 @@ void checkOplogFormatVersion(OperationContext* opCtx, const std::string& uri) {
fassertNoTrace(39998, appMetadata.getValue().getIntField("oplogKeyExtractionVersion") == 1);
}
+
+void appendNumericStats(WT_SESSION* s, const std::string& uri, BSONObjBuilder& bob) {
+ Status status =
+ WiredTigerUtil::exportTableToBSON(s, "statistics:" + uri, "statistics=(fast)", &bob);
+ if (!status.isOK()) {
+ bob.append("error", "unable to retrieve statistics");
+ bob.append("code", static_cast<int>(status.code()));
+ bob.append("reason", status.reason());
+ }
+}
} // namespace
MONGO_FAIL_POINT_DEFINE(WTCompactRecordStoreEBUSY);
@@ -1679,9 +1689,20 @@ void WiredTigerRecordStore::validate(OperationContext* opCtx,
results->valid = false;
}
-void WiredTigerRecordStore::appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const {
+void WiredTigerRecordStore::appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {
+ WiredTigerSession* session = WiredTigerRecoveryUnit::get(opCtx)->getSessionNoTxn();
+ WT_SESSION* s = session->getSession();
+
+ BSONObjBuilder bob(result->subobjStart(_engineName));
+
+ appendNumericStats(s, getURI(), bob);
+}
+
+void WiredTigerRecordStore::appendAllCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const {
WiredTigerSession* session = WiredTigerRecoveryUnit::get(opCtx)->getSessionNoTxn();
WT_SESSION* s = session->getSession();
BSONObjBuilder bob(result->subobjStart(_engineName));
@@ -1710,13 +1731,7 @@ void WiredTigerRecordStore::appendCustomStats(OperationContext* opCtx,
bob.append("type", type);
}
- Status status =
- WiredTigerUtil::exportTableToBSON(s, "statistics:" + getURI(), "statistics=(fast)", &bob);
- if (!status.isOK()) {
- bob.append("error", "unable to retrieve statistics");
- bob.append("code", static_cast<int>(status.code()));
- bob.append("reason", status.reason());
- }
+ appendNumericStats(s, getURI(), bob);
}
void WiredTigerRecordStore::waitForAllEarlierOplogWritesToBeVisibleImpl(
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
index 95d6b6635fa..821cda6bf3a 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.h
@@ -188,9 +188,13 @@ public:
ValidateResults* results,
BSONObjBuilder* output);
- virtual void appendCustomStats(OperationContext* opCtx,
- BSONObjBuilder* result,
- double scale) const;
+ virtual void appendNumericCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const;
+
+ virtual void appendAllCustomStats(OperationContext* opCtx,
+ BSONObjBuilder* result,
+ double scale) const;
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive);
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
index 3fbf34025b8..7ccc4e7eb64 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store_test.cpp
@@ -315,7 +315,7 @@ TEST(WiredTigerRecordStoreTest, AppendCustomStatsMetadata) {
ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
BSONObjBuilder builder;
- rs->appendCustomStats(opCtx.get(), &builder, 1.0);
+ rs->appendAllCustomStats(opCtx.get(), &builder, 1.0);
BSONObj customStats = builder.obj();
BSONElement wiredTigerElement = customStats.getField(kWiredTigerEngineName);
@@ -333,6 +333,30 @@ TEST(WiredTigerRecordStoreTest, AppendCustomStatsMetadata) {
ASSERT_EQUALS(creationStringElement.type(), String);
}
+TEST(WiredTigerRecordStoreTest, AppendCustomNumericStats) {
+ std::unique_ptr<RecordStoreHarnessHelper> harnessHelper = newRecordStoreHarnessHelper();
+ unique_ptr<RecordStore> rs(harnessHelper->newNonCappedRecordStore("a.c"));
+
+ ServiceContext::UniqueOperationContext opCtx(harnessHelper->newOperationContext());
+ BSONObjBuilder builder;
+ rs->appendNumericCustomStats(opCtx.get(), &builder, 1.0);
+ BSONObj customStats = builder.obj();
+
+ BSONElement wiredTigerElement = customStats.getField(kWiredTigerEngineName);
+ ASSERT_TRUE(wiredTigerElement.isABSONObj());
+ BSONObj wiredTiger = wiredTigerElement.Obj();
+
+ ASSERT_FALSE(wiredTiger.hasField("metadata"));
+ ASSERT_FALSE(wiredTiger.hasField("creationString"));
+
+ BSONElement cacheElement = wiredTiger.getField("cache");
+ ASSERT_TRUE(cacheElement.isABSONObj());
+ BSONObj cache = cacheElement.Obj();
+
+ BSONElement bytesElement = cache.getField("bytes currently in the cache");
+ ASSERT_TRUE(bytesElement.isNumber());
+}
+
BSONObj makeBSONObjWithSize(const Timestamp& opTime, int size, char fill = 'x') {
BSONObj objTemplate = BSON("ts" << opTime << "str"
<< "");