diff options
author | Irina Yatsenko <irina.yatsenko@mongodb.com> | 2021-04-29 23:42:13 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-12 18:36:03 +0000 |
commit | 265ba00b96161463bc2a6d8640098d3ac4e4b70a (patch) | |
tree | 819a268613c34917b85c8b1ac530c2d05934039b /src/mongo/db | |
parent | 1c7969556696ff8bce4b213c3d85598d0961cd2b (diff) | |
download | mongo-265ba00b96161463bc2a6d8640098d3ac4e4b70a.tar.gz |
SERVER-50286 Indicate in logs whether an operation involves a view
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/curop.cpp | 61 | ||||
-rw-r--r-- | src/mongo/db/curop.h | 18 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog.cpp | 11 |
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())}); } |