diff options
Diffstat (limited to 'src/mongo/db/curop.cpp')
| -rw-r--r-- | src/mongo/db/curop.cpp | 146 |
1 files changed, 119 insertions, 27 deletions
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index af19498253a..23fd1495598 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -51,6 +51,9 @@ #include "mongo/db/profile_filter.h" #include "mongo/db/query/getmore_command_gen.h" #include "mongo/db/query/plan_summary_stats.h" +#include "mongo/db/query/query_stats/query_stats.h" +#include "mongo/db/stats/timer_stats.h" +#include "mongo/db/storage/storage_engine_parameters_gen.h" #include "mongo/logv2/log.h" #include "mongo/rpc/metadata/client_metadata.h" #include "mongo/rpc/metadata/impersonated_user_metadata.h" @@ -60,7 +63,6 @@ #include "mongo/util/net/socket_utils.h" #include "mongo/util/str.h" #include "mongo/util/system_tick_source.h" -#include <mongo/db/stats/timer_stats.h> namespace mongo { @@ -322,6 +324,18 @@ void CurOp::setGenericOpRequestDetails(OperationContext* opCtx, _ns = nss.ns(); } +void CurOp::setEndOfOpMetrics(long long nreturned) { + _debug.additiveMetrics.nreturned = nreturned; + // A non-none queryStatsInfo.keyHash indicates the current query is being tracked for queryStats + // and therefore the executionTime needs to be recorded as part of that effort. executionTime is + // set with the final executionTime in completeAndLogOperation, but for query stats collection + // we want it set before incrementing cursor metrics using OpDebug's AdditiveMetrics. The value + // set here will be overwritten later in completeAndLogOperation. + if (_debug.queryStatsInfo.keyHash) { + _debug.additiveMetrics.executionTime = elapsedTimeExcludingPauses(); + } +} + void CurOp::setMessage_inlock(StringData message) { if (_progressMeter.isActive()) { LOGV2_ERROR(20527, @@ -418,9 +432,10 @@ bool CurOp::completeAndLogOperation(OperationContext* opCtx, // Obtain the total execution time of this operation. done(); - _debug.executionTime = duration_cast<Microseconds>(elapsedTimeExcludingPauses()); - - const auto executionTimeMillis = durationCount<Milliseconds>(_debug.executionTime); + _debug.additiveMetrics.executionTime = + duration_cast<Microseconds>(elapsedTimeExcludingPauses()); + const auto executionTimeMillis = + durationCount<Milliseconds>(*_debug.additiveMetrics.executionTime); if (_debug.isReplOplogGetMore) { oplogGetMoreStats.recordMillis(executionTimeMillis); @@ -822,6 +837,10 @@ void OpDebug::report(OperationContext* opCtx, pAttrs->addDeepCopy("planSummary", curop.getPlanSummary().toString()); } + if (planningTime > Microseconds::zero()) { + pAttrs->add("planningTimeMicros", durationCount<Microseconds>(planningTime)); + } + if (prepareConflictDurationMillis > Milliseconds::zero()) { pAttrs->add("prepareConflictDuration", prepareConflictDurationMillis); } @@ -860,6 +879,7 @@ void OpDebug::report(OperationContext* opCtx, pAttrs->add("replanReason", redact(*replanReason)); } OPDEBUG_TOATTR_HELP_OPTIONAL("nMatched", additiveMetrics.nMatched); + OPDEBUG_TOATTR_HELP_OPTIONAL("nBatches", additiveMetrics.nBatches); OPDEBUG_TOATTR_HELP_OPTIONAL("nModified", additiveMetrics.nModified); OPDEBUG_TOATTR_HELP_OPTIONAL("ninserted", additiveMetrics.ninserted); OPDEBUG_TOATTR_HELP_OPTIONAL("ndeleted", additiveMetrics.ndeleted); @@ -874,7 +894,7 @@ void OpDebug::report(OperationContext* opCtx, additiveMetrics.temporarilyUnavailableErrors); pAttrs->add("numYields", curop.numYields()); - OPDEBUG_TOATTR_HELP(nreturned); + OPDEBUG_TOATTR_HELP_OPTIONAL("nreturned", additiveMetrics.nreturned); if (queryHash) { pAttrs->addDeepCopy("queryHash", zeroPaddedHex(*queryHash)); @@ -965,7 +985,16 @@ void OpDebug::report(OperationContext* opCtx, pAttrs->add("remoteOpWaitMillis", durationCount<Milliseconds>(*remoteOpWaitTime)); } - pAttrs->add("durationMillis", durationCount<Milliseconds>(executionTime)); + // durationMillis should always be present for any operation + pAttrs->add( + "durationMillis", + durationCount<Milliseconds>(additiveMetrics.executionTime.value_or(Microseconds{0}))); +} + +void OpDebug::reportStorageStats(logv2::DynamicAttributes* pAttrs) const { + if (storageStats) { + pAttrs->add("storage", storageStats->toBSON()); + } } #define OPDEBUG_APPEND_NUMBER2(b, x, y) \ @@ -1026,6 +1055,7 @@ void OpDebug::append(OperationContext* opCtx, b.append("replanReason", *replanReason); } OPDEBUG_APPEND_OPTIONAL(b, "nMatched", additiveMetrics.nMatched); + OPDEBUG_APPEND_OPTIONAL(b, "nBatches", additiveMetrics.nBatches); OPDEBUG_APPEND_OPTIONAL(b, "nModified", additiveMetrics.nModified); OPDEBUG_APPEND_OPTIONAL(b, "ninserted", additiveMetrics.ninserted); OPDEBUG_APPEND_OPTIONAL(b, "ndeleted", additiveMetrics.ndeleted); @@ -1043,7 +1073,7 @@ void OpDebug::append(OperationContext* opCtx, OPDEBUG_APPEND_OPTIONAL(b, "dataThroughputAverage", dataThroughputAverage); b.appendNumber("numYield", curop.numYields()); - OPDEBUG_APPEND_NUMBER(b, nreturned); + OPDEBUG_APPEND_OPTIONAL(b, "nreturned", additiveMetrics.nreturned); if (queryHash) { b.append("queryHash", zeroPaddedHex(*queryHash)); @@ -1117,7 +1147,10 @@ void OpDebug::append(OperationContext* opCtx, b.append("remoteOpWaitMillis", durationCount<Milliseconds>(*remoteOpWaitTime)); } - b.appendNumber("millis", durationCount<Milliseconds>(executionTime)); + // millis should always be present for any operation + b.appendNumber( + "millis", + durationCount<Milliseconds>(additiveMetrics.executionTime.value_or(Microseconds{0}))); if (!curop.getPlanSummary().empty()) { b.append("planSummary", curop.getPlanSummary()); @@ -1128,6 +1161,10 @@ void OpDebug::append(OperationContext* opCtx, durationCount<Microseconds>(totalOplogSlotDurationMicros)); } + if (planningTime > Microseconds::zero()) { + b.appendNumber("planningTimeMicros", durationCount<Microseconds>(planningTime)); + } + if (!execStats.isEmpty()) { b.append("execStats", std::move(execStats)); } @@ -1279,6 +1316,9 @@ std::function<BSONObj(ProfileFilter::Args)> OpDebug::appendStaged(StringSet requ addIfNeeded("nMatched", [](auto field, auto args, auto& b) { OPDEBUG_APPEND_OPTIONAL(b, field, args.op.additiveMetrics.nMatched); }); + addIfNeeded("nBatches", [](auto field, auto args, auto& b) { + OPDEBUG_APPEND_OPTIONAL(b, field, args.op.additiveMetrics.nBatches); + }); addIfNeeded("nModified", [](auto field, auto args, auto& b) { OPDEBUG_APPEND_OPTIONAL(b, field, args.op.additiveMetrics.nModified); }); @@ -1322,7 +1362,7 @@ std::function<BSONObj(ProfileFilter::Args)> OpDebug::appendStaged(StringSet requ b.appendNumber(field, args.curop.numYields()); }); addIfNeeded("nreturned", [](auto field, auto args, auto& b) { - OPDEBUG_APPEND_NUMBER2(b, field, args.op.nreturned); + OPDEBUG_APPEND_OPTIONAL(b, field, args.op.additiveMetrics.nreturned); }); addIfNeeded("queryHash", [](auto field, auto args, auto& b) { @@ -1426,10 +1466,14 @@ std::function<BSONObj(ProfileFilter::Args)> OpDebug::appendStaged(StringSet requ // the profiler (OpDebug::append) and the log file (OpDebug::report), so for the profile filter // we support both names. addIfNeeded("millis", [](auto field, auto args, auto& b) { - b.appendNumber(field, durationCount<Milliseconds>(args.op.executionTime)); + b.appendNumber(field, + durationCount<Milliseconds>( + args.op.additiveMetrics.executionTime.value_or(Microseconds{0}))); }); addIfNeeded("durationMillis", [](auto field, auto args, auto& b) { - b.appendNumber(field, durationCount<Milliseconds>(args.op.executionTime)); + b.appendNumber(field, + durationCount<Milliseconds>( + args.op.additiveMetrics.executionTime.value_or(Microseconds{0}))); }); addIfNeeded("planSummary", [](auto field, auto args, auto& b) { @@ -1445,6 +1489,10 @@ std::function<BSONObj(ProfileFilter::Args)> OpDebug::appendStaged(StringSet requ } }); + addIfNeeded("planningTimeMicros", [](auto field, auto args, auto& b) { + b.appendNumber(field, durationCount<Microseconds>(args.op.planningTime)); + }); + addIfNeeded("execStats", [](auto field, auto args, auto& b) { if (!args.op.execStats.isEmpty()) { b.append(field, args.op.execStats); @@ -1572,12 +1620,12 @@ void OpDebug::appendResolvedViewsInfo(BSONObjBuilder& builder) const { namespace { /** - * Adds two boost::optional long longs together. Returns boost::none if both 'lhs' and 'rhs' are - * uninitialized, or the sum of 'lhs' and 'rhs' if they are both initialized. Returns 'lhs' if only - * 'rhs' is uninitialized and vice-versa. + * Adds two boost::optionals of the same type with an operator+() together. Returns boost::none if + * both 'lhs' and 'rhs' are uninitialized, or the sum of 'lhs' and 'rhs' if they are both + * initialized. Returns 'lhs' if only 'rhs' is uninitialized and vice-versa. */ -boost::optional<long long> addOptionalLongs(const boost::optional<long long>& lhs, - const boost::optional<long long>& rhs) { +template <typename T> +boost::optional<T> addOptionals(const boost::optional<T>& lhs, const boost::optional<T>& rhs) { if (!rhs) { return lhs; } @@ -1586,24 +1634,29 @@ boost::optional<long long> addOptionalLongs(const boost::optional<long long>& lh } // namespace void OpDebug::AdditiveMetrics::add(const AdditiveMetrics& otherMetrics) { - keysExamined = addOptionalLongs(keysExamined, otherMetrics.keysExamined); - docsExamined = addOptionalLongs(docsExamined, otherMetrics.docsExamined); - nMatched = addOptionalLongs(nMatched, otherMetrics.nMatched); - nModified = addOptionalLongs(nModified, otherMetrics.nModified); - ninserted = addOptionalLongs(ninserted, otherMetrics.ninserted); - ndeleted = addOptionalLongs(ndeleted, otherMetrics.ndeleted); - nUpserted = addOptionalLongs(nUpserted, otherMetrics.nUpserted); - keysInserted = addOptionalLongs(keysInserted, otherMetrics.keysInserted); - keysDeleted = addOptionalLongs(keysDeleted, otherMetrics.keysDeleted); + keysExamined = addOptionals(keysExamined, otherMetrics.keysExamined); + docsExamined = addOptionals(docsExamined, otherMetrics.docsExamined); + nMatched = addOptionals(nMatched, otherMetrics.nMatched); + nreturned = addOptionals(nreturned, otherMetrics.nreturned); + nBatches = addOptionals(nBatches, otherMetrics.nBatches); + nModified = addOptionals(nModified, otherMetrics.nModified); + ninserted = addOptionals(ninserted, otherMetrics.ninserted); + ndeleted = addOptionals(ndeleted, otherMetrics.ndeleted); + nUpserted = addOptionals(nUpserted, otherMetrics.nUpserted); + keysInserted = addOptionals(keysInserted, otherMetrics.keysInserted); + keysDeleted = addOptionals(keysDeleted, otherMetrics.keysDeleted); prepareReadConflicts.fetchAndAdd(otherMetrics.prepareReadConflicts.load()); writeConflicts.fetchAndAdd(otherMetrics.writeConflicts.load()); temporarilyUnavailableErrors.fetchAndAdd(otherMetrics.temporarilyUnavailableErrors.load()); + executionTime = addOptionals(executionTime, otherMetrics.executionTime); } void OpDebug::AdditiveMetrics::reset() { keysExamined = boost::none; docsExamined = boost::none; nMatched = boost::none; + nreturned = boost::none; + nBatches = boost::none; nModified = boost::none; ninserted = boost::none; ndeleted = boost::none; @@ -1613,17 +1666,20 @@ void OpDebug::AdditiveMetrics::reset() { prepareReadConflicts.store(0); writeConflicts.store(0); temporarilyUnavailableErrors.store(0); + executionTime = boost::none; } bool OpDebug::AdditiveMetrics::equals(const AdditiveMetrics& otherMetrics) const { return keysExamined == otherMetrics.keysExamined && docsExamined == otherMetrics.docsExamined && - nMatched == otherMetrics.nMatched && nModified == otherMetrics.nModified && + nMatched == otherMetrics.nMatched && nreturned == otherMetrics.nreturned && + nBatches == otherMetrics.nBatches && nModified == otherMetrics.nModified && ninserted == otherMetrics.ninserted && ndeleted == otherMetrics.ndeleted && nUpserted == otherMetrics.nUpserted && keysInserted == otherMetrics.keysInserted && keysDeleted == otherMetrics.keysDeleted && prepareReadConflicts.load() == otherMetrics.prepareReadConflicts.load() && writeConflicts.load() == otherMetrics.writeConflicts.load() && - temporarilyUnavailableErrors.load() == otherMetrics.temporarilyUnavailableErrors.load(); + temporarilyUnavailableErrors.load() == otherMetrics.temporarilyUnavailableErrors.load() && + executionTime == otherMetrics.executionTime; } void OpDebug::AdditiveMetrics::incrementWriteConflicts(long long n) { @@ -1648,6 +1704,20 @@ void OpDebug::AdditiveMetrics::incrementKeysDeleted(long long n) { *keysDeleted += n; } +void OpDebug::AdditiveMetrics::incrementNreturned(long long n) { + if (!nreturned) { + nreturned = 0; + } + *nreturned += n; +} + +void OpDebug::AdditiveMetrics::incrementNBatches() { + if (!nBatches) { + nBatches = 0; + } + ++(*nBatches); +} + void OpDebug::AdditiveMetrics::incrementNinserted(long long n) { if (!ninserted) { ninserted = 0; @@ -1662,6 +1732,13 @@ void OpDebug::AdditiveMetrics::incrementNUpserted(long long n) { *nUpserted += n; } +void OpDebug::AdditiveMetrics::incrementExecutionTime(Microseconds n) { + if (!executionTime) { + executionTime = Microseconds{0}; + } + *executionTime += n; +} + void OpDebug::AdditiveMetrics::incrementPrepareReadConflicts(long long n) { prepareReadConflicts.fetchAndAdd(n); } @@ -1672,6 +1749,8 @@ string OpDebug::AdditiveMetrics::report() const { OPDEBUG_TOSTRING_HELP_OPTIONAL("keysExamined", keysExamined); OPDEBUG_TOSTRING_HELP_OPTIONAL("docsExamined", docsExamined); OPDEBUG_TOSTRING_HELP_OPTIONAL("nMatched", nMatched); + OPDEBUG_TOSTRING_HELP_OPTIONAL("nreturned", nreturned); + OPDEBUG_TOSTRING_HELP_OPTIONAL("nBatches", nBatches); OPDEBUG_TOSTRING_HELP_OPTIONAL("nModified", nModified); OPDEBUG_TOSTRING_HELP_OPTIONAL("ninserted", ninserted); OPDEBUG_TOSTRING_HELP_OPTIONAL("ndeleted", ndeleted); @@ -1681,6 +1760,9 @@ string OpDebug::AdditiveMetrics::report() const { OPDEBUG_TOSTRING_HELP_ATOMIC("prepareReadConflicts", prepareReadConflicts); OPDEBUG_TOSTRING_HELP_ATOMIC("writeConflicts", writeConflicts); OPDEBUG_TOSTRING_HELP_ATOMIC("temporarilyUnavailableErrors", temporarilyUnavailableErrors); + if (executionTime) { + s << " durationMillis:" << durationCount<Milliseconds>(*executionTime); + } return s.str(); } @@ -1689,6 +1771,8 @@ void OpDebug::AdditiveMetrics::report(logv2::DynamicAttributes* pAttrs) const { OPDEBUG_TOATTR_HELP_OPTIONAL("keysExamined", keysExamined); OPDEBUG_TOATTR_HELP_OPTIONAL("docsExamined", docsExamined); OPDEBUG_TOATTR_HELP_OPTIONAL("nMatched", nMatched); + OPDEBUG_TOATTR_HELP_OPTIONAL("nreturned", nreturned); + OPDEBUG_TOATTR_HELP_OPTIONAL("nBatches", nBatches); OPDEBUG_TOATTR_HELP_OPTIONAL("nModified", nModified); OPDEBUG_TOATTR_HELP_OPTIONAL("ninserted", ninserted); OPDEBUG_TOATTR_HELP_OPTIONAL("ndeleted", ndeleted); @@ -1698,6 +1782,9 @@ void OpDebug::AdditiveMetrics::report(logv2::DynamicAttributes* pAttrs) const { OPDEBUG_TOATTR_HELP_ATOMIC("prepareReadConflicts", prepareReadConflicts); OPDEBUG_TOATTR_HELP_ATOMIC("writeConflicts", writeConflicts); OPDEBUG_TOATTR_HELP_ATOMIC("temporarilyUnavailableErrors", temporarilyUnavailableErrors); + if (executionTime) { + pAttrs->add("durationMillis", durationCount<Milliseconds>(*executionTime)); + } } BSONObj OpDebug::AdditiveMetrics::reportBSON() const { @@ -1705,6 +1792,8 @@ BSONObj OpDebug::AdditiveMetrics::reportBSON() const { OPDEBUG_APPEND_OPTIONAL(b, "keysExamined", keysExamined); OPDEBUG_APPEND_OPTIONAL(b, "docsExamined", docsExamined); OPDEBUG_APPEND_OPTIONAL(b, "nMatched", nMatched); + OPDEBUG_APPEND_OPTIONAL(b, "nreturned", nreturned); + OPDEBUG_APPEND_OPTIONAL(b, "nBatches", nBatches); OPDEBUG_APPEND_OPTIONAL(b, "nModified", nModified); OPDEBUG_APPEND_OPTIONAL(b, "ninserted", ninserted); OPDEBUG_APPEND_OPTIONAL(b, "ndeleted", ndeleted); @@ -1714,6 +1803,9 @@ BSONObj OpDebug::AdditiveMetrics::reportBSON() const { OPDEBUG_APPEND_ATOMIC(b, "prepareReadConflicts", prepareReadConflicts); OPDEBUG_APPEND_ATOMIC(b, "writeConflicts", writeConflicts); OPDEBUG_APPEND_ATOMIC(b, "temporarilyUnavailableErrors", temporarilyUnavailableErrors); + if (executionTime) { + b.appendNumber("durationMillis", durationCount<Milliseconds>(*executionTime)); + } return b.obj(); } |
