summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorIrina Yatsenko <irina.yatsenko@mongodb.com>2021-04-29 23:42:13 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-12 18:36:03 +0000
commit265ba00b96161463bc2a6d8640098d3ac4e4b70a (patch)
tree819a268613c34917b85c8b1ac530c2d05934039b /src/mongo
parent1c7969556696ff8bce4b213c3d85598d0961cd2b (diff)
downloadmongo-265ba00b96161463bc2a6d8640098d3ac4e4b70a.tar.gz
SERVER-50286 Indicate in logs whether an operation involves a view
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/curop.cpp61
-rw-r--r--src/mongo/db/curop.h18
-rw-r--r--src/mongo/db/views/view_catalog.cpp11
3 files changed, 90 insertions, 0 deletions
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp
index 32dd1a531d4..20bc4610e65 100644
--- a/src/mongo/db/curop.cpp
+++ b/src/mongo/db/curop.cpp
@@ -882,6 +882,10 @@ string OpDebug::report(OperationContext* opCtx, const SingleThreadedLockStats* l
s << " dataThroughputAverage: " << *dataThroughputAverage << " MB/sec";
}
+ if (!resolvedViews.empty()) {
+ s << " resolvedViews: " << getResolvedViewsInfo();
+ }
+
OPDEBUG_TOSTRING_HELP(nShards);
OPDEBUG_TOSTRING_HELP(cursorid);
if (mongotCursorId) {
@@ -1061,6 +1065,10 @@ void OpDebug::report(OperationContext* opCtx,
pAttrs->add("dataThroughputAverageMBPerSec", *dataThroughputAverage);
}
+ if (!resolvedViews.empty()) {
+ pAttrs->add("resolvedViews", getResolvedViewsInfo());
+ }
+
OPDEBUG_TOATTR_HELP(nShards);
OPDEBUG_TOATTR_HELP(cursorid);
if (mongotCursorId) {
@@ -1205,6 +1213,10 @@ void OpDebug::append(OperationContext* opCtx,
appendAsObjOrString("originatingCommand", originatingCommand, appendMaxElementSize, &b);
}
+ if (!resolvedViews.empty()) {
+ appendResolvedViewsInfo(b);
+ }
+
OPDEBUG_APPEND_NUMBER(b, nShards);
OPDEBUG_APPEND_NUMBER(b, cursorid);
if (mongotCursorId) {
@@ -1667,6 +1679,55 @@ BSONObj OpDebug::makeMongotDebugStatsObject() const {
return cursorBuilder.obj();
}
+void OpDebug::addResolvedViews(const std::vector<NamespaceString>& namespaces,
+ const std::vector<BSONObj>& pipeline) {
+ if (namespaces.empty())
+ return;
+
+ if (resolvedViews.find(namespaces.front()) == resolvedViews.end()) {
+ resolvedViews[namespaces.front()] = std::make_pair(namespaces, pipeline);
+ }
+}
+
+static void appendResolvedViewsInfoImpl(
+ BSONArrayBuilder& resolvedViewsArr,
+ const std::map<NamespaceString, std::pair<std::vector<NamespaceString>, std::vector<BSONObj>>>&
+ resolvedViews) {
+ for (const auto& kv : resolvedViews) {
+ const NamespaceString& viewNss = kv.first;
+ const std::vector<NamespaceString>& dependencies = kv.second.first;
+ const std::vector<BSONObj>& pipeline = kv.second.second;
+
+ BSONObjBuilder aView;
+ aView.append("viewNamespace", viewNss.ns());
+
+ BSONArrayBuilder dependenciesArr(aView.subarrayStart("dependencyChain"));
+ for (const auto& nss : dependencies) {
+ dependenciesArr.append(nss.coll().toString());
+ }
+ dependenciesArr.doneFast();
+
+ BSONArrayBuilder pipelineArr(aView.subarrayStart("resolvedPipeline"));
+ for (const auto& stage : pipeline) {
+ pipelineArr.append(stage);
+ }
+ pipelineArr.doneFast();
+
+ resolvedViewsArr.append(redact(aView.done()));
+ }
+}
+
+BSONArray OpDebug::getResolvedViewsInfo() const {
+ BSONArrayBuilder resolvedViewsArr;
+ appendResolvedViewsInfoImpl(resolvedViewsArr, this->resolvedViews);
+ return resolvedViewsArr.arr();
+}
+
+void OpDebug::appendResolvedViewsInfo(BSONObjBuilder& builder) const {
+ BSONArrayBuilder resolvedViewsArr(builder.subarrayStart("resolvedViews"));
+ appendResolvedViewsInfoImpl(resolvedViewsArr, this->resolvedViews);
+ resolvedViewsArr.doneFast();
+}
namespace {
diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h
index 44530fcfbfd..aab0d9fad30 100644
--- a/src/mongo/db/curop.h
+++ b/src/mongo/db/curop.h
@@ -201,6 +201,18 @@ public:
*/
BSONObj makeMongotDebugStatsObject() const;
+ /**
+ * Accumulate resolved views.
+ */
+ void addResolvedViews(const std::vector<NamespaceString>& namespaces,
+ const std::vector<BSONObj>& pipeline);
+
+ /**
+ * Get or append the array with resolved views' info.
+ */
+ BSONArray getResolvedViewsInfo() const;
+ void appendResolvedViewsInfo(BSONObjBuilder& builder) const;
+
// -------------------
// basic options
@@ -279,6 +291,12 @@ public:
// Whether this is an oplog getMore operation for replication oplog fetching.
bool isReplOplogGetMore{false};
+
+ // Maps namespace of a resolved view to its dependency chain and the fully unrolled pipeline. To
+ // make log line deterministic and easier to test, use ordered map. As we don't expect many
+ // resolved views per query, a hash map would unlikely provide any benefits.
+ std::map<NamespaceString, std::pair<std::vector<NamespaceString>, std::vector<BSONObj>>>
+ resolvedViews;
};
/**
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index de708b34df2..d74e9148350 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -43,6 +43,7 @@
#include "mongo/db/audit.h"
#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/database.h"
+#include "mongo/db/curop.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/pipeline/aggregate_command_gen.h"
@@ -695,6 +696,8 @@ StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
// 'resolvedNss'.
std::shared_ptr<ViewDefinition> lastViewDefinition;
+ std::vector<NamespaceString> dependencyChain{nss};
+
int depth = 0;
for (; depth < ViewGraph::kMaxViewDepth; depth++) {
auto view =
@@ -710,6 +713,10 @@ StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
str::stream() << "View pipeline exceeds maximum size; maximum size is "
<< ViewGraph::kMaxViewPipelineSizeBytes};
}
+
+ auto curOp = CurOp::get(opCtx);
+ curOp->debug().addResolvedViews(dependencyChain, resolvedPipeline);
+
return StatusWith<ResolvedView>(
{*resolvedNss,
std::move(resolvedPipeline),
@@ -717,6 +724,7 @@ StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
}
resolvedNss = &view->viewOn();
+ dependencyChain.push_back(*resolvedNss);
if (!collation) {
collation = view->defaultCollator() ? view->defaultCollator()->getSpec().toBSON()
: CollationSpec::kSimpleSpec;
@@ -728,6 +736,9 @@ StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
// If the first stage is a $collStats, then we return early with the viewOn namespace.
if (toPrepend.size() > 0 && !toPrepend[0]["$collStats"].eoo()) {
+ auto curOp = CurOp::get(opCtx);
+ curOp->debug().addResolvedViews(dependencyChain, resolvedPipeline);
+
return StatusWith<ResolvedView>(
{*resolvedNss, std::move(resolvedPipeline), std::move(collation.get())});
}