summaryrefslogtreecommitdiff
path: root/src/mongo/s
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2020-08-25 11:09:37 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-08-27 04:47:40 +0000
commitcefce38b2c914aa2167943e92fb4fe23a1cb9c3b (patch)
treef4859c4b91fea9fbfc87bbbbca6fad7366092b13 /src/mongo/s
parenta751610b2eb005c0b47f6ad637f009f8aa9c8346 (diff)
downloadmongo-cefce38b2c914aa2167943e92fb4fe23a1cb9c3b.tar.gz
SERVER-43902 Apply scaling for collection statistics after summing statistics from individual shards
Diffstat (limited to 'src/mongo/s')
-rw-r--r--src/mongo/s/commands/cluster_coll_stats_cmd.cpp73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/mongo/s/commands/cluster_coll_stats_cmd.cpp b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp
index e7e707cb156..c493f2a72f5 100644
--- a/src/mongo/s/commands/cluster_coll_stats_cmd.cpp
+++ b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp
@@ -40,6 +40,39 @@
namespace mongo {
namespace {
+auto fieldIsAnyOf = [](StringData v, std::initializer_list<StringData> il) {
+ auto ei = il.end();
+ return std::find(il.begin(), ei, v) != ei;
+};
+
+BSONObj scaleIndividualShardStatistics(const BSONObj& shardStats, int scale) {
+ BSONObjBuilder builder;
+
+ for (const auto& element : shardStats) {
+ std::string fieldName = element.fieldName();
+
+ if (fieldIsAnyOf(fieldName,
+ {"size", "maxSize", "storageSize", "totalIndexSize", "totalSize"})) {
+ builder.appendNumber(fieldName, element.numberLong() / scale);
+ } else if (fieldName == "scaleFactor") {
+ // Explicitly change the scale factor as we removed the scaling before getting the
+ // individual shards statistics.
+ builder.appendNumber(fieldName, scale);
+ } else if (fieldName == "indexSizes") {
+ BSONObjBuilder indexSizesBuilder(builder.subobjStart(fieldName));
+ for (const auto& entry : shardStats.getField(fieldName).Obj()) {
+ indexSizesBuilder.appendNumber(entry.fieldName(), entry.numberLong() / scale);
+ }
+ indexSizesBuilder.done();
+ } else {
+ // All the other fields that do not require further scaling.
+ builder.append(element);
+ }
+ }
+
+ return builder.obj();
+}
+
class CollectionStats : public BasicCommand {
public:
CollectionStats() : BasicCommand("collStats", "collstats") {}
@@ -87,13 +120,29 @@ public:
result.append("primary", routingInfo.db().primaryId().toString());
}
- auto shardResults = scatterGatherVersionedTargetByRoutingTable(
+ int scale = 1;
+ if (cmdObj["scale"].isNumber()) {
+ scale = cmdObj["scale"].numberInt();
+ uassert(4390200, "scale has to be >= 1", scale >= 1);
+ } else if (cmdObj["scale"].trueValue()) {
+ uasserted(4390201, "scale has to be a number >= 1");
+ }
+
+ // Re-construct the command's BSONObj without any scaling to be applied.
+ BSONObj cmdObjWithoutScale = cmdObj.removeField("scale");
+
+ // Unscaled individual shard results. This is required to apply scaling after summing the
+ // statistics from individual shards as opposed to adding the summation of the scaled
+ // statistics.
+ auto unscaledShardResults = scatterGatherVersionedTargetByRoutingTable(
opCtx,
nss.db(),
nss,
routingInfo,
applyReadWriteConcern(
- opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdObj)),
+ opCtx,
+ this,
+ CommandHelpers::filterCommandRequestForPassthrough(cmdObjWithoutScale)),
ReadPreferenceSetting::get(opCtx),
Shard::RetryPolicy::kIdempotent,
{},
@@ -109,7 +158,7 @@ public:
int nindexes = 0;
bool warnedAboutIndexes = false;
- for (const auto& shardResult : shardResults) {
+ for (const auto& shardResult : unscaledShardResults) {
const auto& shardId = shardResult.shardId;
const auto shardResponse = uassertStatusOK(std::move(shardResult.swResponse));
uassertStatusOK(shardResponse.status);
@@ -121,10 +170,6 @@ public:
// until we've iterated through all the fields before updating unscaledCollSize
const auto shardObjCount = static_cast<long long>(res["count"].Number());
- auto fieldIsAnyOf = [](StringData v, std::initializer_list<StringData> il) {
- auto ei = il.end();
- return std::find(il.begin(), ei, v) != ei;
- };
for (const auto& e : res) {
StringData fieldName = e.fieldNameStringData();
if (fieldIsAnyOf(fieldName, {"ns", "ok", "lastExtentSize", "paddingFactor"})) {
@@ -184,19 +229,24 @@ public:
}
}
- shardStats.append(shardId.toString(), res);
+ shardStats.append(shardId.toString(), scaleIndividualShardStatistics(res, scale));
}
result.append("ns", nss.ns());
for (const auto& countEntry : counts) {
- result.appendNumber(countEntry.first, countEntry.second);
+ if (fieldIsAnyOf(countEntry.first,
+ {"size", "storageSize", "totalIndexSize", "totalSize"})) {
+ result.appendNumber(countEntry.first, countEntry.second / scale);
+ } else {
+ result.appendNumber(countEntry.first, countEntry.second);
+ }
}
{
BSONObjBuilder ib(result.subobjStart("indexSizes"));
for (const auto& entry : indexSizes) {
- ib.appendNumber(entry.first, entry.second);
+ ib.appendNumber(entry.first, entry.second / scale);
}
ib.done();
}
@@ -208,8 +258,9 @@ public:
else
result.append("avgObjSize", 0.0);
- result.append("maxSize", maxSize);
+ result.append("maxSize", maxSize / scale);
result.append("nindexes", nindexes);
+ result.append("scaleFactor", scale);
result.append("nchunks", (routingInfo.cm() ? routingInfo.cm()->numChunks() : 1));
result.append("shards", shardStats.obj());