summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdityavardhan Agrawal <aa729@cornell.edu>2022-11-18 19:18:45 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-11-18 20:15:14 +0000
commit5765010714b9aa348be53b01a60fd4659216f53f (patch)
treee5bbbdd2bfb3fc3d2164fcb95fd79288f5175213
parentd44b5ed933e7444bed641b9878a8556903e57e78 (diff)
downloadmongo-5765010714b9aa348be53b01a60fd4659216f53f.tar.gz
SERVER-69056 Show resource consumption metrics in explain
-rw-r--r--jstests/noPassthrough/explain_operation_metrics.js75
-rw-r--r--src/mongo/db/query/explain.cpp15
2 files changed, 89 insertions, 1 deletions
diff --git a/jstests/noPassthrough/explain_operation_metrics.js b/jstests/noPassthrough/explain_operation_metrics.js
new file mode 100644
index 00000000000..a50ae0c69c6
--- /dev/null
+++ b/jstests/noPassthrough/explain_operation_metrics.js
@@ -0,0 +1,75 @@
+/**
+ * Tests explain when profileOperationResourceConsumptionMetrics is set to true and explain
+ * verbosity is "executionStats" or "allPlansExecution".
+ * @tags: [
+ * requires_replication,
+ * requires_sharding,
+ * requires_wiredtiger
+ * ]
+ */
+(function() {
+"use strict";
+const dbName = jsTestName();
+const collName = 'coll';
+
+const runTest = (db) => {
+ for (const verbosity of ["executionStats", "allPlansExecution"]) {
+ jsTestLog("Testing with verbosity: " + verbosity);
+ const coll = db[collName];
+ coll.drop();
+ const docs = [{a: 0, b: 0}, {a: 0, b: 0}, {a: 0, b: 0}];
+ assert.commandWorked(coll.insertMany(docs));
+
+ const result = assert.commandWorked(coll.find().explain(verbosity));
+ assert(result.hasOwnProperty("executionStats"), result);
+ const execStats = result.executionStats;
+ assert(execStats.hasOwnProperty("operationMetrics"), execStats);
+ const operationMetrics = execStats.operationMetrics;
+ assert.eq(132, operationMetrics.docBytesRead);
+ assert.eq(3, operationMetrics.docUnitsRead);
+
+ const aggResult =
+ assert.commandWorked(coll.explain(verbosity).aggregate({$project: {a: "$a"}}));
+ assert(aggResult.hasOwnProperty("executionStats"), aggResult);
+ const aggExecStats = aggResult.executionStats;
+ assert(aggExecStats.hasOwnProperty("operationMetrics"), aggExecStats);
+ const aggOperationMetrics = aggExecStats.operationMetrics;
+ assert.eq(132, aggOperationMetrics.docBytesRead);
+ assert.eq(3, aggOperationMetrics.docUnitsRead);
+
+ assert.commandWorked(coll.createIndex({a: 1}));
+ const idxFindResult = assert.commandWorked(coll.find({a: 0}).explain(verbosity));
+ assert(idxFindResult.hasOwnProperty("executionStats"), idxFindResult);
+ const idxFindExecutionStats = idxFindResult.executionStats;
+ assert(idxFindExecutionStats.hasOwnProperty("operationMetrics"), idxFindExecutionStats);
+ const idxFindOperationMetrics = idxFindExecutionStats.operationMetrics;
+ assert.eq(132, idxFindOperationMetrics.docBytesRead);
+ assert.eq(3, idxFindOperationMetrics.docUnitsRead);
+ assert.eq(12, idxFindOperationMetrics.idxEntryBytesRead);
+ assert.eq(3, idxFindOperationMetrics.idxEntryUnitsRead);
+ assert.eq(4, idxFindOperationMetrics.cursorSeeks);
+ }
+};
+
+const setParams = {
+ profileOperationResourceConsumptionMetrics: true
+};
+
+jsTestLog("Testing standalone");
+(function testStandalone() {
+ const conn = MongoRunner.runMongod({setParameter: setParams});
+ const db = conn.getDB(dbName);
+ runTest(db);
+ MongoRunner.stopMongod(conn);
+})();
+
+jsTestLog("Testing replica set");
+(function testReplicaSet() {
+ const rst = new ReplSetTest({nodes: 2, nodeOptions: {setParameter: setParams}});
+ rst.startSet();
+ rst.initiate();
+ const db = rst.getPrimary().getDB(dbName);
+ runTest(db);
+ rst.stopSet();
+})();
+})();
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index 3c9cbe69c1d..9a460447ba8 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -59,6 +59,7 @@
#include "mongo/db/query/query_settings_decoration.h"
#include "mongo/db/query/stage_builder.h"
#include "mongo/db/server_options.h"
+#include "mongo/db/stats/resource_consumption_metrics.h"
#include "mongo/util/hex.h"
#include "mongo/util/net/socket_utils.h"
#include "mongo/util/overloaded_visitor.h"
@@ -222,6 +223,18 @@ void generateSinglePlanExecutionInfo(const PlanExplainer::PlanStatsDetails& deta
out->append("executionStages", stats);
}
+void generateOperationMetrics(PlanExecutor* exec, BSONObjBuilder* out) {
+ if (ResourceConsumption::isMetricsProfilingEnabled()) {
+ auto& metricsCollector = ResourceConsumption::MetricsCollector::get(exec->getOpCtx());
+ if (metricsCollector.hasCollectedMetrics()) {
+ BSONObjBuilder metricsBuilder(out->subobjStart("operationMetrics"));
+ auto& metrics = metricsCollector.getMetrics();
+ metrics.toBsonNonZeroFields(&metricsBuilder);
+ metricsBuilder.doneFast();
+ }
+ }
+}
+
/**
* Adds the "executionStats" field to out. Assumes that the PlanExecutor has already been executed
* to the point of reaching EOF. Also assumes that verbosity >= kExecStats.
@@ -287,7 +300,7 @@ void generateExecutionInfo(PlanExecutor* exec,
}
allPlansBob.doneFast();
}
-
+ generateOperationMetrics(exec, &execBob);
execBob.doneFast();
}