diff options
author | Adityavardhan Agrawal <aa729@cornell.edu> | 2022-11-18 19:18:45 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-11-18 20:15:14 +0000 |
commit | 5765010714b9aa348be53b01a60fd4659216f53f (patch) | |
tree | e5bbbdd2bfb3fc3d2164fcb95fd79288f5175213 | |
parent | d44b5ed933e7444bed641b9878a8556903e57e78 (diff) | |
download | mongo-5765010714b9aa348be53b01a60fd4659216f53f.tar.gz |
SERVER-69056 Show resource consumption metrics in explain
-rw-r--r-- | jstests/noPassthrough/explain_operation_metrics.js | 75 | ||||
-rw-r--r-- | src/mongo/db/query/explain.cpp | 15 |
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(); } |