diff options
-rw-r--r-- | jstests/auth/lib/commands_lib.js | 1 | ||||
-rw-r--r-- | jstests/noPassthrough/aggregate_operation_metrics.js | 17 | ||||
-rw-r--r-- | jstests/noPassthrough/index_build_operation_metrics.js | 18 | ||||
-rw-r--r-- | jstests/noPassthrough/ttl_operation_metrics.js | 8 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_operation_metrics.cpp | 5 |
5 files changed, 35 insertions, 14 deletions
diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index 5d333e9188b..268c2640fe0 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -5989,6 +5989,7 @@ var authCommandsLib = { privileges: [ {resource: {cluster: true}, actions: ["operationMetrics"]}, ], + expectFail: true, }, ] }, diff --git a/jstests/noPassthrough/aggregate_operation_metrics.js b/jstests/noPassthrough/aggregate_operation_metrics.js index 62533397cf7..61095041c86 100644 --- a/jstests/noPassthrough/aggregate_operation_metrics.js +++ b/jstests/noPassthrough/aggregate_operation_metrics.js @@ -63,9 +63,24 @@ let getServerStatusMetrics = (db) => { return ss.resourceConsumption; }; +const primary = rst.getPrimary(); + +// $operationMetrics may only be run against the admin database and in a 'collectionless' form. +assert.commandFailedWithCode(primary.getDB('invalid').runCommand({ + aggregate: 1, + pipeline: [{$operationMetrics: {}}], + cursor: {}, +}), + ErrorCodes.InvalidNamespace); +assert.commandFailedWithCode(primary.getDB('admin').runCommand({ + aggregate: 'test', + pipeline: [{$operationMetrics: {}}], + cursor: {}, +}), + ErrorCodes.InvalidNamespace); + // Perform very basic reads and writes on two different databases. const db1Name = 'db1'; -const primary = rst.getPrimary(); const db1 = primary.getDB(db1Name); assert.commandWorked(db1.coll1.insert({a: 1})); assert.commandWorked(db1.coll2.insert({a: 1})); diff --git a/jstests/noPassthrough/index_build_operation_metrics.js b/jstests/noPassthrough/index_build_operation_metrics.js index e15e2f1bd45..6a13dbc4fd8 100644 --- a/jstests/noPassthrough/index_build_operation_metrics.js +++ b/jstests/noPassthrough/index_build_operation_metrics.js @@ -26,8 +26,8 @@ const secondaryDB = secondary.getDB(dbName); const nDocs = 100; -const clearMetrics = (db) => { - db.aggregate([{$operationMetrics: {clearMetrics: true}}]); +const clearMetrics = (conn) => { + conn.getDB('admin').aggregate([{$operationMetrics: {clearMetrics: true}}]); }; // Get aggregated metrics keyed by database name. @@ -60,7 +60,7 @@ assert.commandWorked(primaryDB.createCollection(collName)); * primary node. */ (function loadCollection() { - clearMetrics(primaryDB); + clearMetrics(primary); let bulk = primaryDB[collName].initializeUnorderedBulkOp(); for (let i = 0; i < nDocs; i++) { @@ -92,7 +92,7 @@ assert.commandWorked(primaryDB.createCollection(collName)); * Build an index. Expect that metrics are reasonable and only reported on the primary node. */ (function buildIndex() { - clearMetrics(primaryDB); + clearMetrics(primary); assert.commandWorked(primaryDB[collName].createIndex({a: 1})); assertMetrics(primary, (metrics) => { @@ -134,7 +134,7 @@ assert.commandWorked(primaryDB[collName].dropIndex({a: 1})); * Build an index. Expect that metrics are reasonable and only reported on the primary node. */ (function buildUniqueIndex() { - clearMetrics(primaryDB); + clearMetrics(primary); assert.commandWorked(primaryDB[collName].createIndex({a: 1}, {unique: true})); assertMetrics(primary, (metrics) => { @@ -180,7 +180,7 @@ assert.commandWorked(primaryDB[collName].dropIndex({a: 1})); // Insert a document at the end that makes the index non-unique. assert.commandWorked(primaryDB[collName].insert({a: (nDocs - 1)})); - clearMetrics(primaryDB); + clearMetrics(primary); assert.commandFailedWithCode(primaryDB[collName].createIndex({a: 1}, {unique: true}), ErrorCodes.DuplicateKey); @@ -222,7 +222,7 @@ assert.commandWorked(primaryDB[collName].dropIndex({a: 1})); * and reports read metrics. */ (function buildIndexInterrupt() { - clearMetrics(primaryDB); + clearMetrics(primary); // Hang the index build after kicking off the build on the primary, but before scanning the // collection. @@ -298,8 +298,8 @@ assert.commandWorked(primaryDB[collName].dropIndex({a: 1})); * The the stepped-down node should not collect anything. */ (function buildIndexWithStepDown() { - clearMetrics(primaryDB); - clearMetrics(secondaryDB); + clearMetrics(primary); + clearMetrics(secondary); // Hang the index build after kicking off the build on the secondary, but before scanning the // collection. diff --git a/jstests/noPassthrough/ttl_operation_metrics.js b/jstests/noPassthrough/ttl_operation_metrics.js index 42de17ff0ed..4b57fe9481f 100644 --- a/jstests/noPassthrough/ttl_operation_metrics.js +++ b/jstests/noPassthrough/ttl_operation_metrics.js @@ -31,8 +31,8 @@ const secondary = rst.getSecondary(); const primaryDB = primary.getDB(dbName); const secondaryDB = secondary.getDB(dbName); -const clearMetrics = (db) => { - db.aggregate([{$operationMetrics: {clearMetrics: true}}]); +const clearMetrics = (conn) => { + conn.getDB('admin').aggregate([{$operationMetrics: {clearMetrics: true}}]); }; // Get aggregated metrics keyed by database name. @@ -73,7 +73,7 @@ assert.commandWorked(primaryDB[collName].createIndex({x: 1}, {expireAfterSeconds let pauseTtl = configureFailPoint(primary, 'hangTTLMonitorWithLock'); pauseTtl.wait(); -clearMetrics(primaryDB); +clearMetrics(primary); let now = new Date(); let later = new Date(now.getTime() + 1000 * 60 * 60); @@ -90,7 +90,7 @@ assertMetrics(primary, (metrics) => { }); // Clear metrics and wait for a TTL pass to delete the documents. -clearMetrics(primaryDB); +clearMetrics(primary); pauseTtl.off(); waitForTtlPass(primaryDB); diff --git a/src/mongo/db/pipeline/document_source_operation_metrics.cpp b/src/mongo/db/pipeline/document_source_operation_metrics.cpp index d694b651f16..c2037bc2e12 100644 --- a/src/mongo/db/pipeline/document_source_operation_metrics.cpp +++ b/src/mongo/db/pipeline/document_source_operation_metrics.cpp @@ -88,6 +88,11 @@ intrusive_ptr<DocumentSource> DocumentSourceOperationMetrics::createFromBson( "The aggregateOperationResourceConsumption server parameter is not set"); } + const NamespaceString& nss = pExpCtx->ns; + uassert(ErrorCodes::InvalidNamespace, + "$operationMetrics must be run against the 'admin' database with {aggregate: 1}", + nss.db() == NamespaceString::kAdminDb && nss.isCollectionlessAggregateNS()); + uassert(ErrorCodes::BadValue, "The $operationMetrics stage specification must be an object", elem.type() == Object); |