0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00
mongodb/jstests/noPassthrough/server_read_concern_metrics.js

365 lines
18 KiB
JavaScript

// Tests readConcern level metrics in the serverStatus output.
// @tags: [uses_transactions, requires_majority_read_concern]
(function() {
"use strict";
// Verifies that the server status response has the fields that we expect.
function verifyServerStatusFields(serverStatusResponse) {
assert(serverStatusResponse.hasOwnProperty("opReadConcernCounters"),
"Expected the serverStatus response to have a 'opReadConcernCounters' field\n" +
tojson(serverStatusResponse));
assert(
serverStatusResponse.opReadConcernCounters.hasOwnProperty("available"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'available' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
assert(
serverStatusResponse.opReadConcernCounters.hasOwnProperty("linearizable"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'linearizable' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
assert(serverStatusResponse.opReadConcernCounters.hasOwnProperty("local"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'local' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
assert(serverStatusResponse.opReadConcernCounters.hasOwnProperty("majority"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'majority' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
assert(serverStatusResponse.opReadConcernCounters.hasOwnProperty("snapshot"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'snapshot' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
assert(serverStatusResponse.opReadConcernCounters.hasOwnProperty("none"),
"The 'opReadConcernCounters' field in serverStatus did not have the 'none' field\n" +
tojson(serverStatusResponse.opReadConcernCounters));
}
// 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 +
", initialStats: " + tojson(initialStats) + ", newStats: " + tojson(newStats));
}
const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
const primary = rst.getPrimary();
const dbName = "test";
const collName = "server_read_concern_metrics";
const testDB = primary.getDB(dbName);
const testColl = testDB[collName];
const sessionOptions = {
causalConsistency: false
};
const session = testDB.getMongo().startSession(sessionOptions);
const sessionDb = session.getDatabase(dbName);
const sessionColl = sessionDb[collName];
testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
assert.commandWorked(testColl.insert({_id: 0}));
// Run an initial transaction to get config.transactions state into memory.
session.startTransaction();
assert.eq(sessionColl.find().itcount(), 1);
assert.commandWorked(session.abortTransaction_forTesting());
function getServerStatus(conn) {
// Don't return defaultRWConcern because it may trigger a refresh of the read write concern
// defaults, which unexpectedly increases the opReadConcernCounters.
return assert.commandWorked(conn.adminCommand({serverStatus: 1, defaultRWConcern: false}));
}
// Get initial serverStatus.
let serverStatus = getServerStatus(testDB);
verifyServerStatusFields(serverStatus);
// Run a find with no readConcern.
assert.eq(testColl.find().itcount(), 1);
let newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 1);
serverStatus = newStatus;
// Run a find with a readConcern with no level.
assert.commandWorked(
testDB.runCommand({find: collName, readConcern: {afterClusterTime: Timestamp(1, 1)}}));
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 1);
serverStatus = newStatus;
// Run a legacy query.
primary.forceReadMode("legacy");
assert.eq(testColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 1);
primary.forceReadMode("commands");
serverStatus = newStatus;
// Run a find with a readConcern level available.
assert.eq(testColl.find().readConcern("available").itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// Run a find with a readConcern level linearizable.
assert.eq(testColl.find().readConcern("linearizable").itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// Run a find with a readConcern level local.
assert.eq(testColl.find().readConcern("local").itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// Run a find with a readConcern level majority.
assert.eq(testColl.find().readConcern("majority").itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// Run a find in a transaction with readConcern level snapshot.
session.startTransaction({readConcern: {level: "snapshot"}});
assert.eq(sessionColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
assert.commandWorked(session.abortTransaction_forTesting());
serverStatus = newStatus;
// Run a find in a transaction with no specified readConcern level.
session.startTransaction();
assert.eq(sessionColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 1);
assert.commandWorked(session.abortTransaction_forTesting());
serverStatus = newStatus;
// Run a find in a transaction with readConcern level local.
session.startTransaction({readConcern: {level: "local"}});
assert.eq(sessionColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
assert.commandWorked(session.abortTransaction_forTesting());
serverStatus = newStatus;
// Run a find in a transaction with readConcern level majority.
session.startTransaction({readConcern: {level: "majority"}});
assert.eq(sessionColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// Run a second find in the same transaction. It will inherit the readConcern from the
// transaction.
assert.eq(sessionColl.find().itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 1);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
assert.commandWorked(session.abortTransaction_forTesting());
serverStatus = newStatus;
// Aggregation does not count toward readConcern metrics. Aggregation is counted as a 'command'
// in the 'opCounters' serverStatus section, and we only track the readConcern of queries
// tracked in 'opCounters.query'.
assert.eq(testColl.aggregate([]).itcount(), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// The count command does not count toward readConcern metrics. The count command is counted as
// a 'command' in the 'opCounters' serverStatus section, and we only track the readConcern of
// queries tracked in 'opCounters.query'.
assert.eq(testColl.count({_id: 0}), 1);
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
serverStatus = newStatus;
// getMore does not count toward readConcern metrics. getMore inherits the readConcern of the
// originating command. It is not counted in 'opCounters.query'.
let res = assert.commandWorked(testDB.runCommand({find: collName, batchSize: 0}));
serverStatus = getServerStatus(testDB);
assert.commandWorked(testDB.runCommand({getMore: res.cursor.id, collection: collName}));
newStatus = getServerStatus(testDB);
verifyServerStatusFields(newStatus);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "available", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "linearizable", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "local", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "majority", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "snapshot", 0);
verifyServerStatusChange(
serverStatus.opReadConcernCounters, newStatus.opReadConcernCounters, "none", 0);
session.endSession();
rst.stopSet();
}());