summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKatherine Wu <katherine.wu@mongodb.com>2021-04-09 10:22:04 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-07 18:04:42 +0000
commitbce8de3a989d7b5aeb1c1145099298bd81a5c9bb (patch)
treecb5c45d4f3c8bcb0bb1746fc8bf681771c933465 /src/mongo
parentd8515fe5703df61776204777ba4d5336459ff8b0 (diff)
downloadmongo-bce8de3a989d7b5aeb1c1145099298bd81a5c9bb.tar.gz
SERVER-47603 Rewrite db.currentOp() shell helper in terms of $currentOp aggregation stage
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/curop.cpp5
-rw-r--r--src/mongo/shell/db.js72
2 files changed, 75 insertions, 2 deletions
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp
index 29e63a3a1e9..32dd1a531d4 100644
--- a/src/mongo/db/curop.cpp
+++ b/src/mongo/db/curop.cpp
@@ -674,6 +674,11 @@ void appendAsObjOrString(StringData name,
objToString[*maxSize - 3] = '.';
objToString[*maxSize - 2] = '.';
objToString[*maxSize - 1] = '.';
+ LOGV2_INFO(4760300,
+ "Gathering currentOp information, operation of size {size} exceeds the size "
+ "limit of {limit} and will be truncated.",
+ "size"_attr = objToString.size(),
+ "limit"_attr = *maxSize);
}
StringData truncation = StringData(objToString).substr(0, *maxSize);
diff --git a/src/mongo/shell/db.js b/src/mongo/shell/db.js
index bcdcea166a0..53a18150595 100644
--- a/src/mongo/shell/db.js
+++ b/src/mongo/shell/db.js
@@ -814,7 +814,31 @@ var commandUnsupported = function(res) {
};
DB.prototype.currentOp = function(arg) {
- var q = {};
+ // TODO CLOUDP-89361: The shell is connected to the Atlas Proxy, which currently does not
+ // support the $currentOp aggregation stage. Remove the legacy server command path once the
+ // proxy can support $currentOp.
+ if (this.serverStatus().hasOwnProperty("atlasVersion")) {
+ return this.currentOpLegacy(arg);
+ }
+
+ try {
+ const results = this.currentOpCursor(arg).toArray();
+ let res = {"inprog": results.length > 0 ? results : [], "ok": 1};
+ Object.defineProperty(res, "fsyncLock", {
+ get: function() {
+ throw Error(
+ "fsyncLock is no longer included in the currentOp shell helper, run db.runCommand({currentOp: 1}) instead.");
+ }
+ });
+ return res;
+ } catch (e) {
+ return {"ok": 0, "code": e.code, "errmsg": "Error executing $currentOp: " + e.message};
+ }
+};
+DB.prototype.currentOP = DB.prototype.currentOp;
+
+DB.prototype.currentOpLegacy = function(arg) {
+ let q = {};
if (arg) {
if (typeof (arg) == "object")
Object.extend(q, arg);
@@ -838,7 +862,51 @@ DB.prototype.currentOp = function(arg) {
}
return res;
};
-DB.prototype.currentOP = DB.prototype.currentOp;
+
+DB.prototype.currentOpCursor = function(arg) {
+ let q = {};
+ if (arg) {
+ if (typeof (arg) == "object")
+ Object.extend(q, arg);
+ else if (arg)
+ q["$all"] = true;
+ }
+
+ // Convert the incoming currentOp command into an equivalent aggregate command
+ // of the form {aggregate:1, pipeline: [{$currentOp: {idleConnections: $all, allUsers:
+ // !$ownOps, truncateOps: false}}, {$match: {<user-defined filter>}}], cursor:{}}.
+ let pipeline = [];
+
+ let currOpArgs = {};
+ let currOpStage = {"$currentOp": currOpArgs};
+ currOpArgs["allUsers"] = !q["$ownOps"];
+ currOpArgs["idleConnections"] = !!q["$all"];
+ currOpArgs["truncateOps"] = false;
+
+ pipeline.push(currOpStage);
+
+ let matchArgs = {};
+ let matchStage = {"$match": matchArgs};
+ for (const fieldname of Object.keys(q)) {
+ if (fieldname !== "$all" && fieldname !== "$ownOps" && fieldname !== "$truncateOps") {
+ matchArgs[fieldname] = q[fieldname];
+ }
+ }
+
+ pipeline.push(matchStage);
+
+ // The legacy db.currentOp() shell helper ignored any explicitly set read preference and used
+ // the default, with the ability to also run on secondaries. To preserve this behavior we will
+ // temporarily set the session's read preference to "primaryPreferred".
+ const session = this.getSession();
+ const readPreference = session.getOptions().getReadPreference();
+ try {
+ session.getOptions().setReadPreference({mode: "primaryPreferred"});
+ return this.getSiblingDB("admin").aggregate(pipeline);
+ } finally {
+ session.getOptions().setReadPreference(readPreference);
+ }
+};
DB.prototype.killOp = function(op) {
if (!op)