SERVER-127007 Add server status metric for path arrayness invalidation (#54071)

GitOrigin-RevId: 4ffd1618d653049063090c7f61bc2e9763a9ae65
This commit is contained in:
Evan Bergeron 2026-05-26 19:03:26 -04:00 committed by MongoDB Bot
parent ca9ea08b23
commit 005ea9599c
4 changed files with 20 additions and 0 deletions

View File

@ -40,6 +40,7 @@ function setupColl(name) {
const kKilledMsg = "non-array path became multikey during yield"; const kKilledMsg = "non-array path became multikey during yield";
function runPhases({runQuery, isWriteCmd}) { function runPhases({runQuery, isWriteCmd}) {
const before = db.adminCommand({serverStatus: 1}).metrics.query.pathArrayness.queriesFailedDueToInvalidation;
const fp = configureFailPoint(db, "pathArraynessYieldInvalidation", {}, {times: 1}); const fp = configureFailPoint(db, "pathArraynessYieldInvalidation", {}, {times: 1});
try { try {
// Verify query is killed with the path-arrayness invalidation message. // Verify query is killed with the path-arrayness invalidation message.
@ -55,6 +56,8 @@ function runPhases({runQuery, isWriteCmd}) {
} finally { } finally {
fp.off(); fp.off();
} }
const after = db.adminCommand({serverStatus: 1}).metrics.query.pathArrayness.queriesFailedDueToInvalidation;
assert.eq(after, before + 1, "expected invalidation counter to be incremented", {before, after});
} }
{ {

View File

@ -71,6 +71,9 @@ function runTest({testCase, setParameters, expect}) {
const fp = configureFailPoint(testDb, "setYieldAllLocksHang", {namespace: coll.getFullName()}); const fp = configureFailPoint(testDb, "setYieldAllLocksHang", {namespace: coll.getFullName()});
try { try {
const before = testDb.adminCommand({serverStatus: 1}).metrics.query.pathArrayness
.queriesFailedDueToInvalidation;
let awaitShell = startParallelShell( let awaitShell = startParallelShell(
funWithArgs( funWithArgs(
function (dbName, collName, pipeline, aggOptions, expect) { function (dbName, collName, pipeline, aggOptions, expect) {
@ -110,6 +113,14 @@ function runTest({testCase, setParameters, expect}) {
fp.off(); fp.off();
awaitShell(); awaitShell();
const after = testDb.adminCommand({serverStatus: 1}).metrics.query.pathArrayness.queriesFailedDueToInvalidation;
const expectedDelta = expect === "killed" ? 1 : 0;
assert.eq(after - before, expectedDelta, "expected invalidation counter change to be " + expectedDelta, {
before,
after,
expect,
});
} finally { } finally {
fp.off(); fp.off();
} }

View File

@ -43,6 +43,7 @@ mongo_cc_library(
"//src/mongo:base", "//src/mongo:base",
"//src/mongo/db:common", "//src/mongo/db:common",
"//src/mongo/db/commands/server_status:server_status_core", "//src/mongo/db/commands/server_status:server_status_core",
"//src/mongo/db/commands/server_status:server_status_metric",
"//src/mongo/db/pipeline:field_path", "//src/mongo/db/pipeline:field_path",
"//src/mongo/db/query/query_knobs:query_knob_configuration", "//src/mongo/db/query/query_knobs:query_knob_configuration",
"//src/mongo/db/query/query_settings", "//src/mongo/db/query/query_settings",

View File

@ -29,6 +29,7 @@
#include "mongo/db/query/compiler/metadata/path_arrayness.h" #include "mongo/db/query/compiler/metadata/path_arrayness.h"
#include "mongo/db/commands/server_status/server_status_metric.h"
#include "mongo/db/namespace_string.h" #include "mongo/db/namespace_string.h"
#include "mongo/db/pipeline/expression_context.h" #include "mongo/db/pipeline/expression_context.h"
#include "mongo/logv2/log.h" #include "mongo/logv2/log.h"
@ -44,6 +45,9 @@ MONGO_FAIL_POINT_DEFINE(pathArraynessYieldInvalidation);
namespace mongo { namespace mongo {
auto& pathArraynessQueriesFailedDueToInvalidation =
*MetricBuilder<Counter64>{"query.pathArrayness.queriesFailedDueToInvalidation"};
const PathArrayness& PathArrayness::emptyPathArrayness() { const PathArrayness& PathArrayness::emptyPathArrayness() {
static const PathArrayness kEmptyPathArrayness; static const PathArrayness kEmptyPathArrayness;
return kEmptyPathArrayness; return kEmptyPathArrayness;
@ -220,6 +224,7 @@ boost::optional<FieldPath> PathArrayness::getFirstInvalidatedPath(
void PathArraynessChecker::uassertIfInvalidated(const PathArrayness& current, void PathArraynessChecker::uassertIfInvalidated(const PathArrayness& current,
const NamespaceString& ns) { const NamespaceString& ns) {
if (auto invalidated = PathArrayness::getFirstInvalidatedPath(nonArrayPaths, current)) { if (auto invalidated = PathArrayness::getFirstInvalidatedPath(nonArrayPaths, current)) {
pathArraynessQueriesFailedDueToInvalidation.increment();
uasserted( uasserted(
ErrorCodes::QueryPlanKilled, ErrorCodes::QueryPlanKilled,
str::stream() << "query plan killed :: non-array path became multikey during yield: " str::stream() << "query plan killed :: non-array path became multikey during yield: "