mirror of https://github.com/mongodb/mongo
152 lines
5.1 KiB
JavaScript
152 lines
5.1 KiB
JavaScript
/**
|
|
* Loading this file overrides DB.prototype.{createCollection, getCollection},
|
|
* DBCollection.prototype.{drop, createIndex} to enable query analyzer.
|
|
* Some collections will be sharded so that query sampling can be tested both with and without
|
|
* sharding.
|
|
*/
|
|
|
|
import {denylistedNamespaces, ShardingOverrideCommon} from "jstests/libs/override_methods/shard_collection_util.js";
|
|
|
|
const kShardProbability = 0.5;
|
|
const kSamplesPerSecond = 1000; // per second.
|
|
|
|
// Save a reference to the original methods in the IIFE's scope.
|
|
// This scoping allows the original methods to be called by the overrides below.
|
|
let originalCreateCollection = DB.prototype.createCollection;
|
|
let originalGetCollection = DB.prototype.getCollection;
|
|
let originalDBCollectionDrop = DBCollection.prototype.drop;
|
|
|
|
function isUnsupportedNamespace(dbName, collName) {
|
|
const ns = dbName + "." + collName;
|
|
for (let denylistedNs of denylistedNamespaces) {
|
|
if (ns.match(denylistedNs)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function configureQueryAnalyzer({db, collName}) {
|
|
const dbName = db.getName();
|
|
const ns = dbName + "." + collName;
|
|
assert(!isUnsupportedNamespace(dbName, collName), {dbName, collName});
|
|
|
|
let result;
|
|
try {
|
|
result = db.adminCommand({configureQueryAnalyzer: ns, mode: "full", samplesPerSecond: kSamplesPerSecond});
|
|
} catch (e) {
|
|
jsTest.log.info("Failed to configure query analyzer", {ns, error: e});
|
|
if (!isNetworkError(e)) {
|
|
throw e;
|
|
}
|
|
}
|
|
if (!result.ok) {
|
|
if (
|
|
result.code === ErrorCodes.CommandNotFound ||
|
|
result.code === ErrorCodes.NamespaceNotFound ||
|
|
result.code === ErrorCodes.CommandNotSupportedOnView ||
|
|
result.code === ErrorCodes.IllegalOperation
|
|
) {
|
|
jsTest.log.info("Failed to configure query analyzer", {ns, result});
|
|
return;
|
|
}
|
|
assert.commandWorked(result);
|
|
}
|
|
}
|
|
|
|
DB.prototype.createCollection = function () {
|
|
const result = originalCreateCollection.apply(this, arguments);
|
|
|
|
if (!result.ok || arguments.length < 2 || arguments[1] == null || !isObject(arguments[1])) {
|
|
return result;
|
|
}
|
|
|
|
const dbName = this.getName();
|
|
const collName = arguments[0];
|
|
|
|
if (isUnsupportedNamespace(dbName, collName)) {
|
|
return result;
|
|
}
|
|
|
|
// Attempt to enable sharding on database and collection if not already done;
|
|
// only shard some of the time, so that query sampling is also tested on unsharded collections.
|
|
// But capped collections and views can't be sharded, so don't try to shard those.
|
|
if (Math.random() < kShardProbability && !arguments[1].capped && !arguments[1].viewOn) {
|
|
if (arguments[1].timeseries && arguments[1].timeseries.timeField) {
|
|
const timeField = arguments[1]["timeseries"]["timeField"];
|
|
ShardingOverrideCommon.shardCollectionWithSpec({
|
|
db: this,
|
|
collName,
|
|
shardKey: {[timeField]: 1},
|
|
timeseriesSpec: arguments[1]["timeseries"],
|
|
});
|
|
} else {
|
|
ShardingOverrideCommon.shardCollection(originalGetCollection.apply(this, [collName]));
|
|
}
|
|
}
|
|
configureQueryAnalyzer({db: this, collName});
|
|
|
|
return result;
|
|
};
|
|
|
|
DB.prototype.getCollection = function () {
|
|
const collection = originalGetCollection.apply(this, arguments);
|
|
|
|
const dbName = this.getName();
|
|
const collName = collection.getName();
|
|
|
|
if (isUnsupportedNamespace(dbName, collName)) {
|
|
return collection;
|
|
}
|
|
|
|
const collStats = this.runCommand({collStats: collName});
|
|
// If the collection is already sharded or is non-empty, do not try to create or shard it.
|
|
if (collStats.sharded || collStats.count > 0) {
|
|
return collection;
|
|
}
|
|
|
|
if (TestData.implicitlyShardOnCreateCollectionOnly) {
|
|
// Don't shard or create the collection.
|
|
return collection;
|
|
}
|
|
|
|
const result = originalCreateCollection.apply(this, [collName]);
|
|
|
|
if (!result.ok) return collection;
|
|
|
|
// Only shard some of the time, so that query sampling is also tested on unsharded collections.
|
|
if (Math.random() < kShardProbability) {
|
|
ShardingOverrideCommon.shardCollection(collection);
|
|
}
|
|
configureQueryAnalyzer({db: collection.getDB(), collName: collName});
|
|
|
|
return collection;
|
|
};
|
|
|
|
DBCollection.prototype.drop = function () {
|
|
const result = originalDBCollectionDrop.apply(this, arguments);
|
|
|
|
if (!result || TestData.implicitlyShardOnCreateCollectionOnly) {
|
|
// Don't shard or create the collection.
|
|
return result;
|
|
}
|
|
|
|
const db = this.getDB();
|
|
const dbName = db.getName();
|
|
const collName = this.getName();
|
|
|
|
if (isUnsupportedNamespace(dbName, collName)) {
|
|
return result;
|
|
}
|
|
|
|
assert.commandWorked(db.createCollection(collName));
|
|
|
|
// Only shard some of the time, so that query sampling is also tested on unsharded collections.
|
|
if (Math.random() < kShardProbability) {
|
|
ShardingOverrideCommon.shardCollection(this);
|
|
}
|
|
configureQueryAnalyzer({db: db, collName: collName});
|
|
|
|
return result;
|
|
};
|