diff --git a/jstests/noPassthrough/delinquent_ops.js b/jstests/noPassthrough/delinquent_ops.js index edbebde5cc3..c901f68f06c 100644 --- a/jstests/noPassthrough/delinquent_ops.js +++ b/jstests/noPassthrough/delinquent_ops.js @@ -151,6 +151,7 @@ function testDelinquencyOnShard(routerDb, shardDb) { curOp.inprog.length === 1, "Expected to find exactly one active find() command with the comment " + findComment); assertDelinquentStats(curOp.inprog[0].delinquencyInfo, 2, curOp.inprog[0]); + assert.gte(curOp.inprog[0].numInterruptChecks, 2, curOp.inprog[0]); } // After the find() command, we check that the serverStatus has the delinquent stats @@ -176,6 +177,7 @@ function testDelinquencyOnShard(routerDb, shardDb) { const parsedLine = JSON.parse(line); const delinquencyInfo = parsedLine.attr.delinquencyInfo; assertDelinquentStats(delinquencyInfo, count, line); + assert.gte(parsedLine.attr.numInterruptChecks, count, parsedLine.attr); }; const globalLog = assert.commandWorked(shardDb.adminCommand({getLog: "global"})); @@ -199,6 +201,9 @@ function testDelinquencyOnShard(routerDb, shardDb) { assert.gte(queryStats[0].metrics.maxAcquisitionDelinquencyMillis.max, waitPerIterationMs, tojson(queryStats)); + // For first batch, numInterruptChecks >=4, time ~=600ms + // For second batch, numInterruptChecks >=3, time~=400ms + assert.gte(queryStats[0].metrics.numInterruptChecksPerSec.sum, 7, tojson(queryStats)); } { diff --git a/jstests/noPassthroughWithMongod/query/include_query_stats_metrics.js b/jstests/noPassthroughWithMongod/query/include_query_stats_metrics.js index c8da3d8a310..23c7e9159fa 100644 --- a/jstests/noPassthroughWithMongod/query/include_query_stats_metrics.js +++ b/jstests/noPassthroughWithMongod/query/include_query_stats_metrics.js @@ -51,6 +51,7 @@ function assertMetricsEqual(cursor, { assertMetricEqual(metrics, "usedDisk", usedDisk); assertMetricEqual(metrics, "fromMultiPlanner", fromMultiPlanner); assertMetricEqual(metrics, "fromPlanCache", fromPlanCache); + assertMetricEqual(metrics, "numInterruptChecks", undefined); // The following metrics exist but are 0 by default. assertMetricEqual(metrics, "delinquentAcquisitions", 0); assertMetricEqual(metrics, "totalAcquisitionDelinquencyMillis", 0); diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index f5fb0665113..9ac1150d2a0 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -421,6 +421,10 @@ void CurOp::setEndOfOpMetrics(long long nreturned) { admCtx.getMaxAcquisitionDelinquencyMillis())}; } + if (!parent()) { + metrics.numInterruptChecks = opCtx()->numInterruptChecks(); + } + try { // If we need them, try to fetch the storage stats. We use an unlimited timeout here, // but the lock acquisition could still be interrupted, which we catch and log. @@ -982,6 +986,9 @@ void CurOp::reportState(BSONObjBuilder* builder, OpDebug::appendDelinquentInfo(opCtx, sub); } + if (!parent()) { + builder->append("numInterruptChecks", opCtx->numInterruptChecks()); + } populateCurrentOpQueueStats(opCtx, _tickSource, builder); } diff --git a/src/mongo/db/curop_test.cpp b/src/mongo/db/curop_test.cpp index 088a272ac7d..ffdab0a143c 100644 --- a/src/mongo/db/curop_test.cpp +++ b/src/mongo/db/curop_test.cpp @@ -106,6 +106,8 @@ TEST(CurOpTest, AddingAdditiveMetricsObjectsTogetherShouldAddFieldsTogether) { additiveMetricsToAdd.totalAcquisitionDelinquencyMillis = Milliseconds{200}; currentAdditiveMetrics.maxAcquisitionDelinquencyMillis = Milliseconds{300}; additiveMetricsToAdd.maxAcquisitionDelinquencyMillis = Milliseconds{100}; + currentAdditiveMetrics.numInterruptChecks = 1; + additiveMetricsToAdd.numInterruptChecks = 2; // Save the current AdditiveMetrics object before adding. OpDebug::AdditiveMetrics additiveMetricsBeforeAdd; @@ -151,6 +153,9 @@ TEST(CurOpTest, AddingAdditiveMetricsObjectsTogetherShouldAddFieldsTogether) { ASSERT_EQ(*currentAdditiveMetrics.maxAcquisitionDelinquencyMillis, std::max(*additiveMetricsBeforeAdd.maxAcquisitionDelinquencyMillis, *additiveMetricsToAdd.maxAcquisitionDelinquencyMillis)); + ASSERT_EQ(*currentAdditiveMetrics.numInterruptChecks, + *additiveMetricsBeforeAdd.numInterruptChecks + + *additiveMetricsToAdd.numInterruptChecks); } TEST(CurOpTest, AddingUninitializedAdditiveMetricsFieldsShouldBeTreatedAsZero) { @@ -264,6 +269,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateCursorMetrics) { additiveMetrics.delinquentAcquisitions = 2; additiveMetrics.totalAcquisitionDelinquencyMillis = Milliseconds(400); additiveMetrics.maxAcquisitionDelinquencyMillis = Milliseconds(300); + additiveMetrics.numInterruptChecks = 2; CursorMetrics cursorMetrics(3 /* keysExamined */, 4 /* docsExamined */, @@ -278,6 +284,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateCursorMetrics) { cursorMetrics.setDelinquentAcquisitions(3); cursorMetrics.setTotalAcquisitionDelinquencyMillis(400); cursorMetrics.setMaxAcquisitionDelinquencyMillis(200); + cursorMetrics.setNumInterruptChecks(3); additiveMetrics.aggregateCursorMetrics(cursorMetrics); @@ -292,6 +299,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateCursorMetrics) { ASSERT_EQ(*additiveMetrics.delinquentAcquisitions, 5); ASSERT_EQ(*additiveMetrics.totalAcquisitionDelinquencyMillis, Milliseconds(800)); ASSERT_EQ(*additiveMetrics.maxAcquisitionDelinquencyMillis, Milliseconds(300)); + ASSERT_EQ(*additiveMetrics.numInterruptChecks, 5); } TEST(CurOpTest, AdditiveMetricsShouldAggregateNegativeCpuNanos) { @@ -333,11 +341,13 @@ TEST(CurOpTest, AdditiveMetricsAggregateCursorMetricsTreatsNoneAsZero) { false /* fromPlanCache */, 10 /* cpuNanos */); + cursorMetrics.setNumInterruptChecks(3); additiveMetrics.aggregateCursorMetrics(cursorMetrics); ASSERT_EQ(*additiveMetrics.keysExamined, 1); ASSERT_EQ(*additiveMetrics.docsExamined, 2); ASSERT_EQ(*additiveMetrics.bytesRead, 3); + ASSERT_EQ(*additiveMetrics.numInterruptChecks, 3); } TEST(CurOpTest, AdditiveMetricsShouldAggregateDataBearingNodeMetrics) { @@ -352,6 +362,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateDataBearingNodeMetrics) { additiveMetrics.delinquentAcquisitions = 2; additiveMetrics.totalAcquisitionDelinquencyMillis = Milliseconds(400); additiveMetrics.maxAcquisitionDelinquencyMillis = Milliseconds(200); + additiveMetrics.numInterruptChecks = 2; query_stats::DataBearingNodeMetrics remoteMetrics; remoteMetrics.keysExamined = 3; @@ -363,6 +374,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateDataBearingNodeMetrics) { remoteMetrics.delinquentAcquisitions = 1; remoteMetrics.totalAcquisitionDelinquencyMillis = Milliseconds(300); remoteMetrics.maxAcquisitionDelinquencyMillis = Milliseconds(300); + remoteMetrics.numInterruptChecks = 1; additiveMetrics.aggregateDataBearingNodeMetrics(remoteMetrics); @@ -375,6 +387,7 @@ TEST(CurOpTest, AdditiveMetricsShouldAggregateDataBearingNodeMetrics) { ASSERT_EQ(*additiveMetrics.delinquentAcquisitions, 3); ASSERT_EQ(*additiveMetrics.totalAcquisitionDelinquencyMillis, Milliseconds(700)); ASSERT_EQ(*additiveMetrics.maxAcquisitionDelinquencyMillis, Milliseconds(300)); + ASSERT_EQ(*additiveMetrics.numInterruptChecks, 3); } TEST(CurOpTest, AdditiveMetricsAggregateDataBearingNodeMetricsTreatsNoneAsZero) { @@ -583,6 +596,8 @@ TEST(CurOpTest, ReportStateIncludesDelinquentStatsIfNonZero) { curOp->reportState(&bob, SerializationContext{}); BSONObj state = bob.obj(); ASSERT_FALSE(state.hasField("delinquencyInfo")); + // Field numInterruptChecks should be always shown. + ASSERT_TRUE(state.hasField("numInterruptChecks")); } // If the delinquent stats are not zero, they *are* included in the state. @@ -597,6 +612,17 @@ TEST(CurOpTest, ReportStateIncludesDelinquentStatsIfNonZero) { ASSERT_EQ(state["delinquencyInfo"]["totalAcquisitionDelinquencyMillis"].Long(), 30); ASSERT_EQ(state["delinquencyInfo"]["maxAcquisitionDelinquencyMillis"].Long(), 20); } + + // If the delinquent stats are not zero, they *are* included in the state. + { + opCtx->checkForInterrupt(); + BSONObjBuilder bob; + curOp->reportState(&bob, SerializationContext{}); + BSONObj state = bob.obj(); + + ASSERT_TRUE(state.hasField("numInterruptChecks")) << state.toString(); + ASSERT_EQ(state["numInterruptChecks"].Number(), 1); + } } TEST(CurOpTest, ShouldNotReportFailpointMsgIfNotSet) { diff --git a/src/mongo/db/op_debug.cpp b/src/mongo/db/op_debug.cpp index ff15b28035c..c548b89ce35 100644 --- a/src/mongo/db/op_debug.cpp +++ b/src/mongo/db/op_debug.cpp @@ -457,6 +457,10 @@ void OpDebug::report(OperationContext* opCtx, pAttrs->add("delinquencyInfo", sub.obj()); } + if (!curop.parent()) { + pAttrs->add("numInterruptChecks", opCtx->numInterruptChecks()); + } + // Extract admission and execution control queueing stats from AdmissionContext stored on opCtx TicketHolderQueueStats queueingStats(opCtx); pAttrs->add("queues", queueingStats.toBson()); @@ -1249,6 +1253,8 @@ CursorMetrics OpDebug::getCursorMetrics() const { metrics.setMaxAcquisitionDelinquencyMillis( additiveMetrics.maxAcquisitionDelinquencyMillis.value_or(Milliseconds(0)).count()); + metrics.setNumInterruptChecks(additiveMetrics.numInterruptChecks.value_or(0)); + metrics.setHasSortStage(additiveMetrics.hasSortStage); metrics.setUsedDisk(additiveMetrics.usedDisk); metrics.setFromMultiPlanner(additiveMetrics.fromMultiPlanner); @@ -1355,6 +1361,8 @@ void OpDebug::AdditiveMetrics::add(const AdditiveMetrics& otherMetrics) { otherMetrics.maxAcquisitionDelinquencyMillis->count())}; } + numInterruptChecks = addOptionals(numInterruptChecks, otherMetrics.numInterruptChecks); + hasSortStage = hasSortStage || otherMetrics.hasSortStage; usedDisk = usedDisk || otherMetrics.usedDisk; fromMultiPlanner = fromMultiPlanner || otherMetrics.fromMultiPlanner; @@ -1384,6 +1392,8 @@ void OpDebug::AdditiveMetrics::aggregateDataBearingNodeMetrics( Milliseconds{std::max(maxAcquisitionDelinquencyMillis.value_or(Milliseconds(0)).count(), metrics.maxAcquisitionDelinquencyMillis.count())}; + numInterruptChecks = numInterruptChecks.value_or(0) + metrics.numInterruptChecks; + hasSortStage = hasSortStage || metrics.hasSortStage; usedDisk = usedDisk || metrics.usedDisk; fromMultiPlanner = fromMultiPlanner || metrics.fromMultiPlanner; @@ -1414,6 +1424,7 @@ void OpDebug::AdditiveMetrics::aggregateCursorMetrics(const CursorMetrics& metri static_cast(metrics.getDelinquentAcquisitions()), Milliseconds(metrics.getTotalAcquisitionDelinquencyMillis()), Milliseconds(metrics.getMaxAcquisitionDelinquencyMillis()), + static_cast(metrics.getNumInterruptChecks()), metrics.getHasSortStage(), metrics.getUsedDisk(), metrics.getFromMultiPlanner(), diff --git a/src/mongo/db/op_debug.h b/src/mongo/db/op_debug.h index 04c9f1a3b88..6bedf8a94f1 100644 --- a/src/mongo/db/op_debug.h +++ b/src/mongo/db/op_debug.h @@ -210,6 +210,9 @@ public: // set) to make the "sticky towards false" logic work. boost::optional fromPlanCache; + // Total number of checkForInterrupt() calls by an operation. + boost::optional numInterruptChecks; + // If query stats are being collected for this operation, stores the estimated cpu time // across the cluster. In a mongod, this is the local cpu time and in mongos this track the // total cpu time across the cluster. diff --git a/src/mongo/db/operation_context.cpp b/src/mongo/db/operation_context.cpp index 8f85235a3bb..51ccaa70943 100644 --- a/src/mongo/db/operation_context.cpp +++ b/src/mongo/db/operation_context.cpp @@ -214,6 +214,8 @@ bool opShouldFail(Client* client, const BSONObj& failPointInfo) { } // namespace Status OperationContext::checkForInterruptNoAssert() noexcept { + _numInterruptChecks.fetchAndAddRelaxed(1); + if (getClient()->getKilled() && !_isExecutingShutdown) { return Status(ErrorCodes::ClientMarkedKilled, "client has been killed"); } diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h index 9d303eea4ee..be766cb0b1b 100644 --- a/src/mongo/db/operation_context.h +++ b/src/mongo/db/operation_context.h @@ -742,6 +742,13 @@ public: return _killOpsExempt; } + /** + * Returns number of checkForInterrupts() done on this OperationContext. + */ + int64_t numInterruptChecks() const { + return _numInterruptChecks.loadRelaxed(); + } + /** * Set to prevent killOps from killing this opCtx even when an LSID is set. * You may only call this method prior to setting an LSID on this opCtx. @@ -950,6 +957,9 @@ private: // When the operation was marked as killed. AtomicWord _killTime{0}; + // Tracks total number of interrupt checks. + Atomic _numInterruptChecks{0}; + // Used to cancel all tokens obtained via getCancellationToken() when this OperationContext is // killed. CancellationSource _cancelSource; diff --git a/src/mongo/db/query/client_cursor/cursor_response.idl b/src/mongo/db/query/client_cursor/cursor_response.idl index 08819ef4746..4e1a16528cd 100644 --- a/src/mongo/db/query/client_cursor/cursor_response.idl +++ b/src/mongo/db/query/client_cursor/cursor_response.idl @@ -105,6 +105,11 @@ structs: type: long stability: unstable default: 0 + numInterruptChecks: + description: "Number of checkForInterrupt is call by a query operation." + type: long + stability: unstable + default: 0 ResponseCursorBase: description: "Common fields of initial and subsequent cursor responses." diff --git a/src/mongo/db/query/client_cursor/cursor_response_test.cpp b/src/mongo/db/query/client_cursor/cursor_response_test.cpp index 85e432391bb..20c02687343 100644 --- a/src/mongo/db/query/client_cursor/cursor_response_test.cpp +++ b/src/mongo/db/query/client_cursor/cursor_response_test.cpp @@ -63,7 +63,8 @@ static const BSONObj basicMetricsObj = fromjson(R"({ cpuNanos: {"$numberLong": "18"}, delinquentAcquisitions: {"$numberLong": "0"}, totalAcquisitionDelinquencyMillis: {"$numberLong": "0"}, - maxAcquisitionDelinquencyMillis: {"$numberLong": "0"} + maxAcquisitionDelinquencyMillis: {"$numberLong": "0"}, + numInterruptChecks: {"$numberLong": "0"} })"); static const std::string defaultNssStr = "db.coll"; @@ -317,6 +318,7 @@ TEST(CursorResponseTest, parseFromBSONCursorMetrics) { ASSERT_EQ(metrics.getDelinquentAcquisitions(), 0); ASSERT_EQ(metrics.getTotalAcquisitionDelinquencyMillis(), 0); ASSERT_EQ(metrics.getMaxAcquisitionDelinquencyMillis(), 0); + ASSERT_EQ(metrics.getNumInterruptChecks(), 0); } TEST(CursorResponseTest, parseFromBSONCursorMetricsWrongType) { @@ -966,6 +968,7 @@ TEST_F(CursorResponseBuilderTest, buildResponseWithAllKnownFields) { ASSERT_EQ(parsedMetrics->getDelinquentAcquisitions(), 0); ASSERT_EQ(parsedMetrics->getTotalAcquisitionDelinquencyMillis(), 0); ASSERT_EQ(parsedMetrics->getMaxAcquisitionDelinquencyMillis(), 0); + ASSERT_EQ(parsedMetrics->getNumInterruptChecks(), 0); ASSERT_TRUE(response.getPartialResultsReturned()); ASSERT_TRUE(response.getInvalidated()); diff --git a/src/mongo/db/query/query_stats/README.md b/src/mongo/db/query/query_stats/README.md index 47f76370077..e1e02fd1e9f 100644 --- a/src/mongo/db/query/query_stats/README.md +++ b/src/mongo/db/query/query_stats/README.md @@ -245,6 +245,8 @@ following way: acquisition overdue by a query operation, including getMores. - `metrics.maxAcquisitionDelinquencyMillis`: Maximum time in milliseconds that an execution ticket acquisition overdue by a query operation, including getMores. +- `metrics.numInterruptChecksPerSec`: Number of times checkForInterrupt is called per second by a + query operation, including getMores. #### Permissions diff --git a/src/mongo/db/query/query_stats/data_bearing_node_metrics.h b/src/mongo/db/query/query_stats/data_bearing_node_metrics.h index 298e1ba1e8a..b55a0eac3dd 100644 --- a/src/mongo/db/query/query_stats/data_bearing_node_metrics.h +++ b/src/mongo/db/query/query_stats/data_bearing_node_metrics.h @@ -53,6 +53,7 @@ struct DataBearingNodeMetrics { uint64_t delinquentAcquisitions{0}; Milliseconds totalAcquisitionDelinquencyMillis{0}; Milliseconds maxAcquisitionDelinquencyMillis{0}; + uint64_t numInterruptChecks = 0; bool hasSortStage : 1 = false; bool usedDisk : 1 = false; @@ -75,6 +76,7 @@ struct DataBearingNodeMetrics { maxAcquisitionDelinquencyMillis = Milliseconds{std::max(maxAcquisitionDelinquencyMillis.count(), other.maxAcquisitionDelinquencyMillis.count())}; + numInterruptChecks += other.numInterruptChecks; hasSortStage = hasSortStage || other.hasSortStage; usedDisk = usedDisk || other.usedDisk; fromMultiPlanner = fromMultiPlanner || other.fromMultiPlanner; @@ -103,6 +105,7 @@ struct DataBearingNodeMetrics { Milliseconds(metrics.getTotalAcquisitionDelinquencyMillis()); maxAcquisitionDelinquencyMillis = Milliseconds(std::max( maxAcquisitionDelinquencyMillis.count(), metrics.getMaxAcquisitionDelinquencyMillis())); + numInterruptChecks += metrics.getNumInterruptChecks(); hasSortStage = hasSortStage || metrics.getHasSortStage(); usedDisk = usedDisk || metrics.getUsedDisk(); fromMultiPlanner = fromMultiPlanner || metrics.getFromMultiPlanner(); diff --git a/src/mongo/db/query/query_stats/query_stats.cpp b/src/mongo/db/query/query_stats/query_stats.cpp index 7597adcb1ca..60cb9cec76c 100644 --- a/src/mongo/db/query/query_stats/query_stats.cpp +++ b/src/mongo/db/query/query_stats/query_stats.cpp @@ -273,6 +273,14 @@ void updateStatistics(const QueryStatsStore::Partition& proofOfLock, snapshot.totalAcquisitionDelinquencyMillis); toUpdate.maxAcquisitionDelinquencyMillis.aggregate(snapshot.maxAcquisitionDelinquencyMillis); + // Store the number of interrupt checks per second as a rate, this can give us a better sense of + // how often interrupts are being checked relative to the total execution time across multiple + // query runs. + auto secondCount = durationCount(Milliseconds{snapshot.workingTimeMillis}); + auto numInterruptChecksPerSec = + secondCount == 0 ? 0 : snapshot.numInterruptChecks / (static_cast(secondCount)); + toUpdate.numInterruptChecksPerSec.aggregate(numInterruptChecksPerSec); + toUpdate.hasSortStage.aggregate(snapshot.hasSortStage); toUpdate.usedDisk.aggregate(snapshot.usedDisk); toUpdate.fromMultiPlanner.aggregate(snapshot.fromMultiPlanner); @@ -447,6 +455,7 @@ QueryStatsSnapshot captureMetrics(const OperationContext* opCtx, metrics.delinquentAcquisitions.value_or(0), metrics.totalAcquisitionDelinquencyMillis.value_or(Milliseconds(0)).count(), metrics.maxAcquisitionDelinquencyMillis.value_or(Milliseconds(0)).count(), + metrics.numInterruptChecks.value_or(0), metrics.hasSortStage, metrics.usedDisk, metrics.fromMultiPlanner, diff --git a/src/mongo/db/query/query_stats/query_stats.h b/src/mongo/db/query/query_stats/query_stats.h index 5ffb9aacb08..453f271dddf 100644 --- a/src/mongo/db/query/query_stats/query_stats.h +++ b/src/mongo/db/query/query_stats/query_stats.h @@ -230,6 +230,8 @@ struct QueryStatsSnapshot { int64_t totalAcquisitionDelinquencyMillis; int64_t maxAcquisitionDelinquencyMillis; + uint64_t numInterruptChecks; + bool hasSortStage; bool usedDisk; bool fromMultiPlanner; diff --git a/src/mongo/db/query/query_stats/query_stats_entry.cpp b/src/mongo/db/query/query_stats/query_stats_entry.cpp index 6033ff8468c..71277d14ad7 100644 --- a/src/mongo/db/query/query_stats/query_stats_entry.cpp +++ b/src/mongo/db/query/query_stats/query_stats_entry.cpp @@ -55,6 +55,8 @@ BSONObj QueryStatsEntry::toBSON() const { totalAcquisitionDelinquencyMillis.appendTo(builder, "totalAcquisitionDelinquencyMillis"); maxAcquisitionDelinquencyMillis.appendTo(builder, "maxAcquisitionDelinquencyMillis"); + numInterruptChecksPerSec.appendTo(builder, "numInterruptChecksPerSec"); + hasSortStage.appendTo(builder, "hasSortStage"); usedDisk.appendTo(builder, "usedDisk"); fromMultiPlanner.appendTo(builder, "fromMultiPlanner"); diff --git a/src/mongo/db/query/query_stats/query_stats_entry.h b/src/mongo/db/query/query_stats/query_stats_entry.h index f54777db80b..e055b9bf7a3 100644 --- a/src/mongo/db/query/query_stats/query_stats_entry.h +++ b/src/mongo/db/query/query_stats/query_stats_entry.h @@ -125,6 +125,11 @@ struct QueryStatsEntry { AggregatedMetric totalAcquisitionDelinquencyMillis; AggregatedMetric maxAcquisitionDelinquencyMillis; + /** + * Aggregates the checkForInterrupt stats including getMore requests. + */ + AggregatedMetric numInterruptChecksPerSec; + /** * Counts the frequency of the boolean value hasSortStage. */ diff --git a/src/mongo/db/query/query_stats/query_stats_store_test.cpp b/src/mongo/db/query/query_stats/query_stats_store_test.cpp index 1810b597e26..1f880522de3 100644 --- a/src/mongo/db/query/query_stats/query_stats_store_test.cpp +++ b/src/mongo/db/query/query_stats/query_stats_store_test.cpp @@ -1577,6 +1577,7 @@ TEST_F(QueryStatsStoreTest, BasicDiskUsage) { .append("delinquentAcquisitions", emptyIntMetric) .append("totalAcquisitionDelinquencyMillis", emptyIntMetric) .append("maxAcquisitionDelinquencyMillis", emptyIntMetric) + .append("numInterruptChecksPerSec", emptyIntMetric) .append("hasSortStage", boolMetricBson(0, 0)) .append("usedDisk", boolMetricBson(0, 0)) .append("fromMultiPlanner", boolMetricBson(0, 0)) @@ -1615,6 +1616,7 @@ TEST_F(QueryStatsStoreTest, BasicDiskUsage) { .append("delinquentAcquisitions", emptyIntMetric) .append("totalAcquisitionDelinquencyMillis", emptyIntMetric) .append("maxAcquisitionDelinquencyMillis", emptyIntMetric) + .append("numInterruptChecksPerSec", emptyIntMetric) .append("hasSortStage", boolMetricBson(0, 1)) .append("usedDisk", boolMetricBson(1, 0)) .append("fromMultiPlanner", boolMetricBson(0, 0)) diff --git a/src/mongo/s/query/exec/async_results_merger_test.cpp b/src/mongo/s/query/exec/async_results_merger_test.cpp index a1373a56cc6..5d38f62a07c 100644 --- a/src/mongo/s/query/exec/async_results_merger_test.cpp +++ b/src/mongo/s/query/exec/async_results_merger_test.cpp @@ -3259,6 +3259,7 @@ TEST_F(AsyncResultsMergerTest, RemoteMetricsAggregatedLocally) { metrics.setDelinquentAcquisitions(3); metrics.setTotalAcquisitionDelinquencyMillis(100); metrics.setMaxAcquisitionDelinquencyMillis(80); + metrics.setNumInterruptChecks(3); scheduleResponse(id, {fromjson("{_id: 1}")}, std::move(metrics)); } @@ -3284,6 +3285,7 @@ TEST_F(AsyncResultsMergerTest, RemoteMetricsAggregatedLocally) { ASSERT_EQ(remoteMetrics.delinquentAcquisitions, 3); ASSERT_EQ(remoteMetrics.totalAcquisitionDelinquencyMillis, Milliseconds(100)); ASSERT_EQ(remoteMetrics.maxAcquisitionDelinquencyMillis, Milliseconds(80)); + ASSERT_EQ(remoteMetrics.numInterruptChecks, 3); } // Schedule a second response. @@ -3302,6 +3304,7 @@ TEST_F(AsyncResultsMergerTest, RemoteMetricsAggregatedLocally) { metrics.setDelinquentAcquisitions(2); metrics.setTotalAcquisitionDelinquencyMillis(150); metrics.setMaxAcquisitionDelinquencyMillis(120); + metrics.setNumInterruptChecks(2); scheduleResponse(CursorId(0), {fromjson("{_id: 2}")}, std::move(metrics)); } @@ -3325,6 +3328,7 @@ TEST_F(AsyncResultsMergerTest, RemoteMetricsAggregatedLocally) { ASSERT_EQ(remoteMetrics.delinquentAcquisitions, 5); ASSERT_EQ(remoteMetrics.totalAcquisitionDelinquencyMillis, Milliseconds(250)); ASSERT_EQ(remoteMetrics.maxAcquisitionDelinquencyMillis, Milliseconds(120)); + ASSERT_EQ(remoteMetrics.numInterruptChecks, 5); } { @@ -3341,6 +3345,7 @@ TEST_F(AsyncResultsMergerTest, RemoteMetricsAggregatedLocally) { ASSERT_EQ(remoteMetrics.delinquentAcquisitions, 0); ASSERT_EQ(remoteMetrics.totalAcquisitionDelinquencyMillis, Milliseconds(0)); ASSERT_EQ(remoteMetrics.maxAcquisitionDelinquencyMillis, Milliseconds(0)); + ASSERT_EQ(remoteMetrics.numInterruptChecks, 0); } // Read the EOF