summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2021-11-18 17:16:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-08 19:08:18 +0000
commit7ba62a29745f518e2a7b37c75b7a067813e0bcac (patch)
treedca4a8ecad23d9f5dcf4509a9a7eb7f98bbc688a
parentf33c1dac76e2799d50b3453eaf14d771dc9646ab (diff)
downloadmongo-7ba62a29745f518e2a7b37c75b7a067813e0bcac.tar.gz
SERVER-61532 Expose opcounters to detect constraint violations
(cherry picked from commit 5f8a8c70d017bb424748a49ca31df01b2309e000)
-rw-r--r--jstests/replsets/opcounters_repl.js4
-rw-r--r--src/mongo/db/repl/oplog_applier_impl_test.cpp73
-rw-r--r--src/mongo/db/stats/counters.cpp24
3 files changed, 92 insertions, 9 deletions
diff --git a/jstests/replsets/opcounters_repl.js b/jstests/replsets/opcounters_repl.js
index 7ba6d802b89..ec870ee71e6 100644
--- a/jstests/replsets/opcounters_repl.js
+++ b/jstests/replsets/opcounters_repl.js
@@ -42,6 +42,10 @@ function getOpCountersDiff(cmdFn) {
const primaryOpCountersAfter = getOpCounters(primary);
const secondaryOpCountersReplAfter = getOpCountersRepl(secondary);
+ assert(!primaryOpCountersAfter.hasOwnProperty("constraintsRelaxed"), primaryOpCountersAfter);
+ assert(!secondaryOpCountersReplAfter.hasOwnProperty("constraintsRelaxed"),
+ secondaryOpCountersReplAfter);
+
// Calculate the diff
let primaryDiff = {};
let secondaryDiff = {};
diff --git a/src/mongo/db/repl/oplog_applier_impl_test.cpp b/src/mongo/db/repl/oplog_applier_impl_test.cpp
index eef15241e05..961efddf581 100644
--- a/src/mongo/db/repl/oplog_applier_impl_test.cpp
+++ b/src/mongo/db/repl/oplog_applier_impl_test.cpp
@@ -128,7 +128,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, {});
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
- ASSERT_EQ(1, replOpCounters.getDeleteFromMissingNamespace()->load() - prevDeleteFromMissing);
+ auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
+ ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
+
+ ASSERT_EQ(postDeleteFromMissing,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("deleteFromMissingNamespace")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -159,7 +166,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, kUuid);
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
- ASSERT_EQ(1, replOpCounters.getDeleteFromMissingNamespace()->load() - prevDeleteFromMissing);
+ auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
+ ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
+
+ ASSERT_EQ(postDeleteFromMissing,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("deleteFromMissingNamespace")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -197,7 +211,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
int prevDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
ASSERT_FALSE(collectionExists(_opCtx.get(), nss));
- ASSERT_EQ(1, replOpCounters.getDeleteFromMissingNamespace()->load() - prevDeleteFromMissing);
+ auto postDeleteFromMissing = replOpCounters.getDeleteFromMissingNamespace()->load();
+ ASSERT_EQ(1, postDeleteFromMissing - prevDeleteFromMissing);
+
+ ASSERT_EQ(postDeleteFromMissing,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("deleteFromMissingNamespace")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -226,7 +247,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
auto op = makeOplogEntry(OpTypeEnum::kDelete, nss, {});
int prevDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
- ASSERT_EQ(1, replOpCounters.getDeleteWasEmpty()->load() - prevDeleteWasEmpty);
+ auto postDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
+ ASSERT_EQ(1, postDeleteWasEmpty - prevDeleteWasEmpty);
+
+ ASSERT_EQ(postDeleteWasEmpty,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("deleteWasEmpty")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -255,7 +283,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
auto op = makeOplogEntry(OpTypeEnum::kInsert, nss, uuid);
int prevInsertOnExistingDoc = replOpCounters.getInsertOnExistingDoc()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
- ASSERT_EQ(1, replOpCounters.getInsertOnExistingDoc()->load() - prevInsertOnExistingDoc);
+ auto postInsertOnExistingDoc = replOpCounters.getInsertOnExistingDoc()->load();
+ ASSERT_EQ(1, postInsertOnExistingDoc - prevInsertOnExistingDoc);
+
+ ASSERT_EQ(postInsertOnExistingDoc,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("insertOnExistingDoc")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -275,7 +310,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
repl::OpTypeEnum::kUpdate, nss, uuid, BSON("$set" << BSON("a" << 1)), BSON("_id" << 0));
int prevUpdateOnMissingDoc = replOpCounters.getUpdateOnMissingDoc()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, true);
- ASSERT_EQ(1, replOpCounters.getUpdateOnMissingDoc()->load() - prevUpdateOnMissingDoc);
+ auto postUpdateOnMissingDoc = replOpCounters.getUpdateOnMissingDoc()->load();
+ ASSERT_EQ(1, postUpdateOnMissingDoc - prevUpdateOnMissingDoc);
+
+ ASSERT_EQ(postUpdateOnMissingDoc,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("updateOnMissingDoc")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -308,7 +350,14 @@ TEST_F(OplogApplierImplTestDisableSteadyStateConstraints,
auto op = makeOplogEntry(OpTypeEnum::kDelete, otherNss, options.uuid);
int prevDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
_testApplyOplogEntryOrGroupedInsertsCrudOperation(ErrorCodes::OK, op, false);
- ASSERT_EQ(1, replOpCounters.getDeleteWasEmpty()->load() - prevDeleteWasEmpty);
+ auto postDeleteWasEmpty = replOpCounters.getDeleteWasEmpty()->load();
+ ASSERT_EQ(1, postDeleteWasEmpty - prevDeleteWasEmpty);
+
+ ASSERT_EQ(postDeleteWasEmpty,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("deleteWasEmpty")
+ .Long());
}
TEST_F(OplogApplierImplTestEnableSteadyStateConstraints,
@@ -3189,7 +3238,14 @@ TEST_F(IdempotencyTestDisableSteadyStateConstraints, AcceptableErrorsRecordedInS
int prevAcceptableError = replOpCounters.getAcceptableErrorInCommand()->load();
ASSERT_OK(runOpSteadyState(emptyCappedOp));
- ASSERT_EQ(1, replOpCounters.getAcceptableErrorInCommand()->load() - prevAcceptableError);
+ auto postAcceptableError = replOpCounters.getAcceptableErrorInCommand()->load();
+ ASSERT_EQ(1, postAcceptableError - prevAcceptableError);
+
+ ASSERT_EQ(postAcceptableError,
+ replOpCounters.getObj()
+ .getObjectField("constraintsRelaxed")
+ .getField("acceptableErrorInCommand")
+ .Long());
}
TEST_F(IdempotencyTestEnableSteadyStateConstraints,
@@ -3825,7 +3881,6 @@ TEST_F(IdempotencyTestTxns, CommitPreparedTransactionIgnoresNamespaceNotFoundErr
ASSERT_OK(ReplicationCoordinator::get(getGlobalServiceContext())
->setFollowerMode(MemberState::RS_RECOVERING));
-
testOpsAreIdempotent({prepareOp, commitOp});
// The op should have thrown a NamespaceNotFound error, which should have been ignored, so the
diff --git a/src/mongo/db/stats/counters.cpp b/src/mongo/db/stats/counters.cpp
index 2f9b070b888..e64b3f8bfac 100644
--- a/src/mongo/db/stats/counters.cpp
+++ b/src/mongo/db/stats/counters.cpp
@@ -62,6 +62,12 @@ void OpCounters::_checkWrap(CacheAligned<AtomicWord<long long>> OpCounters::*cou
_deleteDeprecated.store(0);
_getmoreDeprecated.store(0);
_killcursorsDeprecated.store(0);
+
+ _insertOnExistingDoc.store(0);
+ _updateOnMissingDoc.store(0);
+ _deleteWasEmpty.store(0);
+ _deleteFromMissingNamespace.store(0);
+ _acceptableErrorInCommand.store(0);
}
}
@@ -94,6 +100,24 @@ BSONObj OpCounters::getObj() const {
d.append("killcursors", killcursorsDep);
}
+ // Append counters for constraint relaxations, only if they exist.
+ auto insertOnExistingDoc = _insertOnExistingDoc.loadRelaxed();
+ auto updateOnMissingDoc = _updateOnMissingDoc.loadRelaxed();
+ auto deleteWasEmpty = _deleteWasEmpty.loadRelaxed();
+ auto deleteFromMissingNamespace = _deleteFromMissingNamespace.loadRelaxed();
+ auto acceptableErrorInCommand = _acceptableErrorInCommand.loadRelaxed();
+ auto totalRelaxed = insertOnExistingDoc + updateOnMissingDoc + deleteWasEmpty +
+ deleteFromMissingNamespace + acceptableErrorInCommand;
+
+ if (totalRelaxed > 0) {
+ BSONObjBuilder d(b.subobjStart("constraintsRelaxed"));
+ d.append("insertOnExistingDoc", insertOnExistingDoc);
+ d.append("updateOnMissingDoc", updateOnMissingDoc);
+ d.append("deleteWasEmpty", deleteWasEmpty);
+ d.append("deleteFromMissingNamespace", deleteFromMissingNamespace);
+ d.append("acceptableErrorInCommand", acceptableErrorInCommand);
+ }
+
return b.obj();
}