From 097c20d21c6e735f179bd14eb30d963d5f2a7a82 Mon Sep 17 00:00:00 2001 From: nehakhatri5 Date: Fri, 7 Dec 2018 16:55:42 +1100 Subject: SERVER-38239 Added getOperationStatistics() API to fetch storage stats from WiredTiger (cherry picked from commit ba3894493a94ed3c18458f391ff181d57475f010) --- src/mongo/db/storage/recovery_unit.h | 9 +++ .../wiredtiger/wiredtiger_recovery_unit.cpp | 19 ++++- .../storage/wiredtiger/wiredtiger_recovery_unit.h | 2 + .../db/storage/wiredtiger/wiredtiger_util.cpp | 80 ++++++++++++++++++++++ src/mongo/db/storage/wiredtiger/wiredtiger_util.h | 9 +++ 5 files changed, 118 insertions(+), 1 deletion(-) diff --git a/src/mongo/db/storage/recovery_unit.h b/src/mongo/db/storage/recovery_unit.h index 331c68046be..1e2626c5951 100644 --- a/src/mongo/db/storage/recovery_unit.h +++ b/src/mongo/db/storage/recovery_unit.h @@ -214,6 +214,15 @@ public: } /** + * Fetches the storage level statistics. + */ + virtual BSONObj getOperationStatistics() const { + return {}; + } + + /** + * The ReadSource indicates which exteral or provided timestamp to read from for future + * transactions. * When no read timestamp is provided to the recovery unit, the ReadSource indicates which * external timestamp source to read from. */ diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp index ae5962ac3b5..692d79c6254 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp @@ -523,7 +523,24 @@ void WiredTigerRecoveryUnit::beginIdle() { } } -// --------------------- +BSONObj WiredTigerRecoveryUnit::getOperationStatistics() const { + BSONObjBuilder bob; + if (!_session) + return bob.obj(); + + WT_SESSION* s = _session->getSession(); + invariant(s); + + Status status = WiredTigerUtil::exportOperationStatsInfoToBSON( + s, "statistics:session", "statistics=(fast)", &bob); + if (!status.isOK()) { + bob.append("error", "unable to retrieve storage statistics"); + bob.append("code", static_cast(status.code())); + bob.append("reason", status.reason()); + } + + return bob.obj(); +} WiredTigerCursor::WiredTigerCursor(const std::string& uri, uint64_t tableId, diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h index e12ca57e49b..7338a32f0d8 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h @@ -110,6 +110,8 @@ public: _orderedCommit = orderedCommit; } + BSONObj getOperationStatistics() const override; + // ---- WT STUFF WiredTigerSession* getSession(); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp index 7c954df00ab..383b5186d8e 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp @@ -665,4 +665,84 @@ Status WiredTigerUtil::exportTableToBSON(WT_SESSION* session, return Status::OK(); } +Status WiredTigerUtil::exportOperationStatsInfoToBSON(WT_SESSION* session, + const std::string& uri, + const std::string& config, + BSONObjBuilder* bob) { + invariant(session); + invariant(bob); + + // Map the statistics to a name and type desired for user consumption. There are two types of + // operation statistics - data and wait. + enum class Section { DATA, WAIT }; + static std::map> statNameMap = { + {WT_STAT_SESSION_BYTES_READ, std::make_pair("bytesRead", Section::DATA)}, + {WT_STAT_SESSION_BYTES_WRITE, std::make_pair("bytesWritten", Section::DATA)}, + {WT_STAT_SESSION_LOCK_DHANDLE_WAIT, std::make_pair("handleLock", Section::WAIT)}, + {WT_STAT_SESSION_READ_TIME, std::make_pair("timeReadingMicros", Section::DATA)}, + {WT_STAT_SESSION_WRITE_TIME, std::make_pair("timeWritingMicros", Section::DATA)}, + {WT_STAT_SESSION_LOCK_SCHEMA_WAIT, std::make_pair("schemaLock", Section::WAIT)}, + {WT_STAT_SESSION_CACHE_TIME, std::make_pair("cache", Section::WAIT)}}; + + WT_CURSOR* c = nullptr; + const char* cursorConfig = config.empty() ? nullptr : config.c_str(); + int ret = session->open_cursor(session, uri.c_str(), nullptr, cursorConfig, &c); + if (ret != 0) { + return Status(ErrorCodes::CursorNotFound, + str::stream() << "unable to open cursor at URI " << uri << ". reason: " + << wiredtiger_strerror(ret)); + } + invariant(c); + ON_BLOCK_EXIT(c->close, c); + + BSONObjBuilder* dataSection = nullptr; + BSONObjBuilder* waitSection = nullptr; + const char* desc; + uint64_t value; + uint64_t key; + while (c->next(c) == 0 && c->get_key(c, &key) == 0) { + fassert(51035, c->get_value(c, &desc, nullptr, &value) == 0); + + StringData statName; + // Find the user consumable name for this statistic. + auto statIt = statNameMap.find(key); + invariant(statIt != statNameMap.end()); + statName = statIt->second.first; + + Section subs = statIt->second.second; + long long casted_val = _castStatisticsValue(value); + + // Add this statistic only if higher than zero. + if (casted_val > 0) { + // Gather the statistic into its own subsection in the BSONObj. + switch (subs) { + case Section::DATA: + if (!dataSection) + dataSection = new BSONObjBuilder(); + + dataSection->append(statName, casted_val); + break; + case Section::WAIT: + if (!waitSection) + waitSection = new BSONObjBuilder(); + + waitSection->append(statName, casted_val); + break; + default: + return Status(ErrorCodes::BadValue, + str::stream() << "Unexpected storage statistics type."); + } + } + } + + if (dataSection) + bob->append("data", dataSection->obj()); + if (waitSection) + bob->append("timeWaitingMicros", waitSection->obj()); + + // Reset the statistics so that the next fetch gives the recent values. + c->reset(c); + return Status::OK(); +} + } // namespace mongo diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_util.h b/src/mongo/db/storage/wiredtiger/wiredtiger_util.h index 4072dfc3c2e..93dbd9dbdbc 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_util.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_util.h @@ -148,6 +148,15 @@ public: const std::string& config, BSONObjBuilder* bob); + /** + * Fetches the operation statistics, converts those into a BSONObj and resets the statistics + * at the end. + */ + static Status exportOperationStatsInfoToBSON(WT_SESSION* s, + const std::string& uri, + const std::string& config, + BSONObjBuilder* bob); + /** * Gets entire metadata string for collection/index at URI with the provided session. */ -- cgit v1.2.1