summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/server_transaction_metrics.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthrough/server_transaction_metrics.js')
-rw-r--r--jstests/noPassthrough/server_transaction_metrics.js406
1 files changed, 194 insertions, 212 deletions
diff --git a/jstests/noPassthrough/server_transaction_metrics.js b/jstests/noPassthrough/server_transaction_metrics.js
index 4bd3c02c9d5..402e72da964 100644
--- a/jstests/noPassthrough/server_transaction_metrics.js
+++ b/jstests/noPassthrough/server_transaction_metrics.js
@@ -1,220 +1,202 @@
// Tests multi-document transactions metrics in the serverStatus output.
// @tags: [uses_transactions]
(function() {
- "use strict";
-
- // Verifies that the server status response has the fields that we expect.
- function verifyServerStatusFields(serverStatusResponse) {
- assert(serverStatusResponse.hasOwnProperty("transactions"),
- "Expected the serverStatus response to have a 'transactions' field\n" +
- tojson(serverStatusResponse));
- assert(serverStatusResponse.transactions.hasOwnProperty("currentActive"),
- "The 'transactions' field in serverStatus did not have the 'currentActive' field\n" +
- tojson(serverStatusResponse.transactions));
- assert(
- serverStatusResponse.transactions.hasOwnProperty("currentInactive"),
- "The 'transactions' field in serverStatus did not have the 'currentInactive' field\n" +
- tojson(serverStatusResponse.transactions));
- assert(serverStatusResponse.transactions.hasOwnProperty("currentOpen"),
- "The 'transactions' field in serverStatus did not have the 'currentOpen' field\n" +
- tojson(serverStatusResponse.transactions));
- assert(serverStatusResponse.transactions.hasOwnProperty("totalAborted"),
- "The 'transactions' field in serverStatus did not have the 'totalAborted' field\n" +
- tojson(serverStatusResponse.transactions));
- assert(
- serverStatusResponse.transactions.hasOwnProperty("totalCommitted"),
- "The 'transactions' field in serverStatus did not have the 'totalCommitted' field\n" +
- tojson(serverStatusResponse.transactions));
- assert(serverStatusResponse.transactions.hasOwnProperty("totalStarted"),
- "The 'transactions' field in serverStatus did not have the 'totalStarted' field\n" +
- tojson(serverStatusResponse.transactions));
- }
-
- // Verifies that the given value of the server status response is incremented in the way
- // we expect.
- function verifyServerStatusChange(initialStats, newStats, valueName, expectedIncrement) {
- assert.eq(initialStats[valueName] + expectedIncrement,
- newStats[valueName],
- "expected " + valueName + " to increase by " + expectedIncrement);
- }
-
- // Set up the replica set.
- const rst = new ReplSetTest({nodes: 1});
- rst.startSet();
- rst.initiate();
- const primary = rst.getPrimary();
-
- // Set up the test database.
- const dbName = "test";
- const collName = "server_transactions_metrics";
- const testDB = primary.getDB(dbName);
- const adminDB = rst.getPrimary().getDB('admin');
- testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
- assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));
-
- // Start the session.
- const sessionOptions = {causalConsistency: false};
- const session = testDB.getMongo().startSession(sessionOptions);
- const sessionDb = session.getDatabase(dbName);
+"use strict";
+
+// Verifies that the server status response has the fields that we expect.
+function verifyServerStatusFields(serverStatusResponse) {
+ assert(serverStatusResponse.hasOwnProperty("transactions"),
+ "Expected the serverStatus response to have a 'transactions' field\n" +
+ tojson(serverStatusResponse));
+ assert(serverStatusResponse.transactions.hasOwnProperty("currentActive"),
+ "The 'transactions' field in serverStatus did not have the 'currentActive' field\n" +
+ tojson(serverStatusResponse.transactions));
+ assert(serverStatusResponse.transactions.hasOwnProperty("currentInactive"),
+ "The 'transactions' field in serverStatus did not have the 'currentInactive' field\n" +
+ tojson(serverStatusResponse.transactions));
+ assert(serverStatusResponse.transactions.hasOwnProperty("currentOpen"),
+ "The 'transactions' field in serverStatus did not have the 'currentOpen' field\n" +
+ tojson(serverStatusResponse.transactions));
+ assert(serverStatusResponse.transactions.hasOwnProperty("totalAborted"),
+ "The 'transactions' field in serverStatus did not have the 'totalAborted' field\n" +
+ tojson(serverStatusResponse.transactions));
+ assert(serverStatusResponse.transactions.hasOwnProperty("totalCommitted"),
+ "The 'transactions' field in serverStatus did not have the 'totalCommitted' field\n" +
+ tojson(serverStatusResponse.transactions));
+ assert(serverStatusResponse.transactions.hasOwnProperty("totalStarted"),
+ "The 'transactions' field in serverStatus did not have the 'totalStarted' field\n" +
+ tojson(serverStatusResponse.transactions));
+}
+
+// Verifies that the given value of the server status response is incremented in the way
+// we expect.
+function verifyServerStatusChange(initialStats, newStats, valueName, expectedIncrement) {
+ assert.eq(initialStats[valueName] + expectedIncrement,
+ newStats[valueName],
+ "expected " + valueName + " to increase by " + expectedIncrement);
+}
+
+// Set up the replica set.
+const rst = new ReplSetTest({nodes: 1});
+rst.startSet();
+rst.initiate();
+const primary = rst.getPrimary();
+
+// Set up the test database.
+const dbName = "test";
+const collName = "server_transactions_metrics";
+const testDB = primary.getDB(dbName);
+const adminDB = rst.getPrimary().getDB('admin');
+testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
+assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}}));
+
+// Start the session.
+const sessionOptions = {
+ causalConsistency: false
+};
+const session = testDB.getMongo().startSession(sessionOptions);
+const sessionDb = session.getDatabase(dbName);
+const sessionColl = sessionDb[collName];
+
+// Get state of server status before the transaction.
+let initialStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(initialStatus);
+
+// This transaction will commit.
+jsTest.log("Start a transaction and then commit it.");
+
+// Compare server status after starting a transaction with the server status before.
+session.startTransaction();
+assert.commandWorked(sessionColl.insert({_id: "insert-1"}));
+
+let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+// Verify that the open transaction counter is incremented while inside the transaction.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
+// Verify that when not running an operation, the transaction is inactive.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
+
+// Compare server status after the transaction commit with the server status before.
+assert.commandWorked(session.commitTransaction_forTesting());
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 1);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
+// Verify that current open counter is decremented on commit.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
+// Verify that both active and inactive are 0 on commit.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
+
+// This transaction will abort.
+jsTest.log("Start a transaction and then abort it.");
+
+// Compare server status after starting a transaction with the server status before.
+session.startTransaction();
+assert.commandWorked(sessionColl.insert({_id: "insert-2"}));
+
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+// Verify that the open transaction counter is incremented while inside the transaction.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
+// Verify that when not running an operation, the transaction is inactive.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
+
+// Compare server status after the transaction abort with the server status before.
+assert.commandWorked(session.abortTransaction_forTesting());
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 2);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 1);
+// Verify that current open counter is decremented on abort.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
+// Verify that both active and inactive are 0 on abort.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
+
+// This transaction will abort due to a duplicate key insert.
+jsTest.log("Start a transaction that will abort on a duplicated key error.");
+
+// Compare server status after starting a transaction with the server status before.
+session.startTransaction();
+// Inserting a new document will work fine, and the transaction starts.
+assert.commandWorked(sessionColl.insert({_id: "insert-3"}));
+
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+// Verify that the open transaction counter is incremented while inside the transaction.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
+// Verify that when not running an operation, the transaction is inactive.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
+
+// Compare server status after the transaction abort with the server status before.
+// The duplicated insert will fail, causing the transaction to abort.
+assert.commandFailedWithCode(sessionColl.insert({_id: "insert-3"}), ErrorCodes.DuplicateKey);
+// Ensure that the transaction was aborted on failure.
+assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 3);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 2);
+// Verify that current open counter is decremented on abort caused by an error.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
+// Verify that both active and inactive are 0 on abort.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
+
+// Hang the transaction on a failpoint in the middle of an operation to check active and
+// inactive counters while operation is running inside a transaction.
+jsTest.log("Start a transaction that will hang in the middle of an operation due to a fail point.");
+assert.commandWorked(
+ testDB.adminCommand({configureFailPoint: 'hangDuringBatchUpdate', mode: 'alwaysOn'}));
+
+const transactionFn = function() {
+ const collName = 'server_transactions_metrics';
+ const session = db.getMongo().startSession({causalConsistency: false});
+ const sessionDb = session.getDatabase('test');
const sessionColl = sessionDb[collName];
- // Get state of server status before the transaction.
- let initialStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(initialStatus);
-
- // This transaction will commit.
- jsTest.log("Start a transaction and then commit it.");
-
- // Compare server status after starting a transaction with the server status before.
- session.startTransaction();
- assert.commandWorked(sessionColl.insert({_id: "insert-1"}));
-
- let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- // Verify that the open transaction counter is incremented while inside the transaction.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
- // Verify that when not running an operation, the transaction is inactive.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
-
- // Compare server status after the transaction commit with the server status before.
+ session.startTransaction({readConcern: {level: 'snapshot'}});
+ assert.commandWorked(sessionColl.update({}, {"update-1": 2}));
assert.commandWorked(session.commitTransaction_forTesting());
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 1);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
- // Verify that current open counter is decremented on commit.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
- // Verify that both active and inactive are 0 on commit.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
-
- // This transaction will abort.
- jsTest.log("Start a transaction and then abort it.");
-
- // Compare server status after starting a transaction with the server status before.
- session.startTransaction();
- assert.commandWorked(sessionColl.insert({_id: "insert-2"}));
-
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- // Verify that the open transaction counter is incremented while inside the transaction.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
- // Verify that when not running an operation, the transaction is inactive.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
-
- // Compare server status after the transaction abort with the server status before.
- assert.commandWorked(session.abortTransaction_forTesting());
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 2);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 1);
- // Verify that current open counter is decremented on abort.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
- // Verify that both active and inactive are 0 on abort.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
-
- // This transaction will abort due to a duplicate key insert.
- jsTest.log("Start a transaction that will abort on a duplicated key error.");
-
- // Compare server status after starting a transaction with the server status before.
- session.startTransaction();
- // Inserting a new document will work fine, and the transaction starts.
- assert.commandWorked(sessionColl.insert({_id: "insert-3"}));
-
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- // Verify that the open transaction counter is incremented while inside the transaction.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
- // Verify that when not running an operation, the transaction is inactive.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 1);
-
- // Compare server status after the transaction abort with the server status before.
- // The duplicated insert will fail, causing the transaction to abort.
- assert.commandFailedWithCode(sessionColl.insert({_id: "insert-3"}), ErrorCodes.DuplicateKey);
- // Ensure that the transaction was aborted on failure.
- assert.commandFailedWithCode(session.commitTransaction_forTesting(),
- ErrorCodes.NoSuchTransaction);
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 3);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "totalCommitted", 1);
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 2);
- // Verify that current open counter is decremented on abort caused by an error.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
- // Verify that both active and inactive are 0 on abort.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
-
- // Hang the transaction on a failpoint in the middle of an operation to check active and
- // inactive counters while operation is running inside a transaction.
- jsTest.log(
- "Start a transaction that will hang in the middle of an operation due to a fail point.");
- assert.commandWorked(
- testDB.adminCommand({configureFailPoint: 'hangDuringBatchUpdate', mode: 'alwaysOn'}));
-
- const transactionFn = function() {
- const collName = 'server_transactions_metrics';
- const session = db.getMongo().startSession({causalConsistency: false});
- const sessionDb = session.getDatabase('test');
- const sessionColl = sessionDb[collName];
-
- session.startTransaction({readConcern: {level: 'snapshot'}});
- assert.commandWorked(sessionColl.update({}, {"update-1": 2}));
- assert.commandWorked(session.commitTransaction_forTesting());
+};
+const transactionProcess = startParallelShell(transactionFn, primary.port);
+
+// Keep running currentOp() until we see the transaction subdocument.
+assert.soon(function() {
+ const transactionFilter = {
+ active: true,
+ 'lsid': {$exists: true},
+ 'transaction.parameters.txnNumber': {$eq: 0}
};
- const transactionProcess = startParallelShell(transactionFn, primary.port);
-
- // Keep running currentOp() until we see the transaction subdocument.
- assert.soon(function() {
- const transactionFilter =
- {active: true, 'lsid': {$exists: true}, 'transaction.parameters.txnNumber': {$eq: 0}};
- return 1 === adminDB.aggregate([{$currentOp: {}}, {$match: transactionFilter}]).itcount();
- });
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- // Verify that the open transaction counter is incremented while inside the transaction.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
- // Verify that the metrics show that the transaction is active while inside the operation.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 1);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
-
- // Now the transaction can proceed.
- assert.commandWorked(
- testDB.adminCommand({configureFailPoint: 'hangDuringBatchUpdate', mode: 'off'}));
- transactionProcess();
- newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
- verifyServerStatusFields(newStatus);
- // Verify that current open counter is decremented on commit.
- verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
- // Verify that both active and inactive are 0 after the transaction finishes.
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentActive", 0);
- verifyServerStatusChange(
- initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
-
- // End the session and stop the replica set.
- session.endSession();
- rst.stopSet();
+ return 1 === adminDB.aggregate([{$currentOp: {}}, {$match: transactionFilter}]).itcount();
+});
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+// Verify that the open transaction counter is incremented while inside the transaction.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1);
+// Verify that the metrics show that the transaction is active while inside the operation.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 1);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
+
+// Now the transaction can proceed.
+assert.commandWorked(
+ testDB.adminCommand({configureFailPoint: 'hangDuringBatchUpdate', mode: 'off'}));
+transactionProcess();
+newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1}));
+verifyServerStatusFields(newStatus);
+// Verify that current open counter is decremented on commit.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0);
+// Verify that both active and inactive are 0 after the transaction finishes.
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentActive", 0);
+verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentInactive", 0);
+
+// End the session and stop the replica set.
+session.endSession();
+rst.stopSet();
}());