summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2022-10-28 17:43:48 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-28 18:46:08 +0000
commitd4530b274115a59bd15aacdb1a521f74fcb6fcb9 (patch)
treed9159f663ee87924bb3701e741668318c2c5b144
parent29077e6df5fb4a3574330f80bd4d1fb62d0b6485 (diff)
downloadmongo-d4530b274115a59bd15aacdb1a521f74fcb6fcb9.tar.gz
SERVER-70830 Unit test `WiredTigerOperationStats`
-rw-r--r--src/mongo/db/storage/recovery_unit.h32
-rw-r--r--src/mongo/db/storage/storage_stats.h57
-rw-r--r--src/mongo/db/storage/wiredtiger/SConscript2
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.cpp139
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h55
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats_test.cpp217
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp115
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h35
-rw-r--r--src/mongo/db/transaction/transaction_metrics_observer.cpp2
9 files changed, 474 insertions, 180 deletions
diff --git a/src/mongo/db/storage/recovery_unit.h b/src/mongo/db/storage/recovery_unit.h
index 20c49c637d3..9e173d632e7 100644
--- a/src/mongo/db/storage/recovery_unit.h
+++ b/src/mongo/db/storage/recovery_unit.h
@@ -37,6 +37,7 @@
#include "mongo/bson/timestamp.h"
#include "mongo/db/repl/read_concern_level.h"
#include "mongo/db/storage/snapshot.h"
+#include "mongo/db/storage/storage_stats.h"
#include "mongo/util/decorable.h"
namespace mongo {
@@ -76,37 +77,6 @@ enum class PrepareConflictBehavior {
};
/**
- * Storage statistics management class, with interfaces to provide the statistics in the BSON format
- * and an operator to add the statistics values.
- */
-class StorageStats {
- StorageStats(const StorageStats&) = delete;
- StorageStats& operator=(const StorageStats&) = delete;
-
-public:
- StorageStats() = default;
-
- virtual ~StorageStats(){};
-
- /**
- * Provides the storage statistics in the form of a BSONObj.
- */
- virtual BSONObj toBSON() = 0;
-
- /**
- * Add the statistics values.
- */
- virtual StorageStats& operator+=(const StorageStats&) = 0;
-
- /**
- * Provides the ability to create an instance of this class outside of the storage integration
- * layer.
- */
- virtual std::shared_ptr<StorageStats> getCopy() = 0;
-};
-
-
-/**
* A RecoveryUnit is responsible for ensuring that data is persisted.
* All on-disk information must be mutated through this interface.
*/
diff --git a/src/mongo/db/storage/storage_stats.h b/src/mongo/db/storage/storage_stats.h
new file mode 100644
index 00000000000..b0afd2ba16d
--- /dev/null
+++ b/src/mongo/db/storage/storage_stats.h
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/bson/bsonobj.h"
+
+namespace mongo {
+
+/**
+ * Manages statistics from the storage engine, allowing addition of statistics and serialization to
+ * BSON.
+ */
+class StorageStats {
+public:
+ StorageStats() = default;
+
+ StorageStats(const StorageStats&) = delete;
+ StorageStats(StorageStats&&) = delete;
+ StorageStats& operator=(const StorageStats&) = delete;
+
+ virtual ~StorageStats() = default;
+
+ virtual BSONObj toBSON() const = 0;
+
+ virtual std::shared_ptr<StorageStats> clone() const = 0;
+
+ virtual StorageStats& operator+=(const StorageStats&) = 0;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript
index 68a76639ed5..638cf0b933c 100644
--- a/src/mongo/db/storage/wiredtiger/SConscript
+++ b/src/mongo/db/storage/wiredtiger/SConscript
@@ -37,6 +37,7 @@ wtEnv.Library(
'wiredtiger_index.cpp',
'wiredtiger_index_util.cpp',
'wiredtiger_kv_engine.cpp',
+ 'wiredtiger_operation_stats.cpp',
'wiredtiger_oplog_manager.cpp',
'wiredtiger_parameters.cpp',
'wiredtiger_prepare_conflict.cpp',
@@ -133,6 +134,7 @@ wtEnv.CppUnitTest(
'wiredtiger_init_test.cpp',
'wiredtiger_c_api_test.cpp',
'wiredtiger_kv_engine_test.cpp',
+ 'wiredtiger_operation_stats_test.cpp',
'wiredtiger_recovery_unit_test.cpp',
'wiredtiger_session_cache_test.cpp',
'wiredtiger_util_test.cpp',
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.cpp
new file mode 100644
index 00000000000..ebf3842e7bc
--- /dev/null
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.cpp
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h"
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
+
+namespace mongo {
+namespace {
+
+enum class StatType { kData, kWait };
+
+struct StatInfo {
+ StringData name;
+ StatType type;
+};
+
+stdx::unordered_map<int, StatInfo> statInfo = {
+ {WT_STAT_SESSION_BYTES_READ, {"bytesRead"_sd, StatType::kData}},
+ {WT_STAT_SESSION_BYTES_WRITE, {"bytesWritten"_sd, StatType::kData}},
+ {WT_STAT_SESSION_LOCK_DHANDLE_WAIT, {"handleLock"_sd, StatType::kWait}},
+ {WT_STAT_SESSION_READ_TIME, {"timeReadingMicros"_sd, StatType::kData}},
+ {WT_STAT_SESSION_WRITE_TIME, {"timeWritingMicros"_sd, StatType::kData}},
+ {WT_STAT_SESSION_LOCK_SCHEMA_WAIT, {"schemaLock"_sd, StatType::kWait}},
+ {WT_STAT_SESSION_CACHE_TIME, {"cache"_sd, StatType::kWait}}};
+
+} // namespace
+
+WiredTigerOperationStats::WiredTigerOperationStats(WT_SESSION* session) {
+ invariant(session);
+
+ WT_CURSOR* c;
+ uassert(ErrorCodes::CursorNotFound,
+ "Unable to open statistics cursor",
+ !session->open_cursor(session, "statistics:session", nullptr, "statistics=(fast)", &c));
+
+ ScopeGuard guard{[c] { c->close(c); }};
+
+ int32_t key;
+ uint64_t value;
+ while (c->next(c) == 0 && c->get_key(c, &key) == 0) {
+ fassert(51035, c->get_value(c, nullptr, nullptr, &value) == 0);
+ _stats[key] = WiredTigerUtil::castStatisticsValue<long long>(value);
+ }
+
+ // Reset the statistics so that the next fetch gives the recent values.
+ invariantWTOK(c->reset(c), c->session);
+}
+
+BSONObj WiredTigerOperationStats::toBSON() const {
+ boost::optional<BSONObjBuilder> dataSection;
+ boost::optional<BSONObjBuilder> waitSection;
+
+ for (auto&& [stat, value] : _stats) {
+ if (value == 0) {
+ continue;
+ }
+
+ auto it = statInfo.find(stat);
+ if (it == statInfo.end()) {
+ continue;
+ }
+ auto&& [name, type] = it->second;
+
+ auto appendToSection = [name = name,
+ value = value](boost::optional<BSONObjBuilder>& section) {
+ if (!section) {
+ section.emplace();
+ }
+ section->append(name, value);
+ };
+
+ switch (type) {
+ case StatType::kData:
+ appendToSection(dataSection);
+ break;
+ case StatType::kWait:
+ appendToSection(waitSection);
+ break;
+ }
+ }
+
+ BSONObjBuilder builder;
+ if (dataSection) {
+ builder.append("data", dataSection->obj());
+ }
+ if (waitSection) {
+ builder.append("timeWaitingMicros", waitSection->obj());
+ }
+
+ return builder.obj();
+}
+
+std::shared_ptr<StorageStats> WiredTigerOperationStats::clone() const {
+ auto copy = std::make_shared<WiredTigerOperationStats>();
+ *copy += *this;
+ return copy;
+}
+
+WiredTigerOperationStats& WiredTigerOperationStats::operator+=(
+ const WiredTigerOperationStats& other) {
+ for (auto&& [stat, value] : other._stats) {
+ _stats[stat] += value;
+ }
+ return *this;
+}
+
+StorageStats& WiredTigerOperationStats::operator+=(const StorageStats& other) {
+ return *this += checked_cast<const WiredTigerOperationStats&>(other);
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h
new file mode 100644
index 00000000000..581303e30b8
--- /dev/null
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <wiredtiger.h>
+
+#include "mongo/db/storage/storage_stats.h"
+
+namespace mongo {
+
+class WiredTigerOperationStats final : public StorageStats {
+public:
+ WiredTigerOperationStats() = default;
+ WiredTigerOperationStats(WT_SESSION* session);
+
+ BSONObj toBSON() const final;
+
+ std::shared_ptr<StorageStats> clone() const final;
+
+ StorageStats& operator+=(const StorageStats&) final;
+
+ WiredTigerOperationStats& operator+=(const WiredTigerOperationStats&);
+
+private:
+ std::map<int, long long> _stats;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats_test.cpp
new file mode 100644
index 00000000000..2494b49923f
--- /dev/null
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_operation_stats_test.cpp
@@ -0,0 +1,217 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h"
+#include "mongo/unittest/temp_dir.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+namespace {
+
+#define ASSERT_WT_OK(result) ASSERT_EQ(result, 0) << wiredtiger_strerror(result)
+
+class WiredTigerOperationStatsTest : public unittest::Test {
+protected:
+ void setUp() override {
+ ASSERT_WT_OK(
+ wiredtiger_open(_path.path().c_str(), nullptr, "create,statistics=(fast),", &_conn));
+ ASSERT_WT_OK(_conn->open_session(_conn, nullptr, "isolation=snapshot", &_session));
+ ASSERT_WT_OK(_session->create(
+ _session, _uri.c_str(), "type=file,key_format=q,value_format=u,log=(enabled=false)"));
+ }
+
+ void tearDown() override {
+ ASSERT_EQ(_conn->close(_conn, nullptr), 0);
+ }
+
+ /**
+ * Writes the given data using WT. Causes the bytesWritten and timeWritingMicros stats to be
+ * incremented.
+ */
+ void write(const std::string& data) {
+ ASSERT_WT_OK(_session->begin_transaction(_session, nullptr));
+
+ WT_CURSOR* cursor;
+ ASSERT_WT_OK(_session->open_cursor(_session, _uri.c_str(), nullptr, nullptr, &cursor));
+
+ cursor->set_key(cursor, _key++);
+
+ WT_ITEM item{data.data(), data.size()};
+ cursor->set_value(cursor, &item);
+
+ ASSERT_WT_OK(cursor->insert(cursor));
+ ASSERT_WT_OK(cursor->close(cursor));
+ ASSERT_WT_OK(_session->commit_transaction(_session, nullptr));
+ ASSERT_WT_OK(_session->checkpoint(_session, nullptr));
+ }
+
+ /**
+ * Reads all of the previously written data from WT. Causes the bytesRead and timeReadingMicros
+ * stats to be incremented.
+ */
+ void read() {
+ tearDown();
+ setUp();
+
+ ASSERT_WT_OK(_session->begin_transaction(_session, nullptr));
+
+ WT_CURSOR* cursor;
+ ASSERT_WT_OK(_session->open_cursor(_session, _uri.c_str(), nullptr, nullptr, &cursor));
+
+ for (int64_t i = 0; i < _key; ++i) {
+ cursor->set_key(cursor, i);
+ ASSERT_WT_OK(cursor->search(cursor));
+
+ WT_ITEM value;
+ ASSERT_WT_OK(cursor->get_value(cursor, &value));
+ }
+
+ ASSERT_WT_OK(cursor->close(cursor));
+ ASSERT_WT_OK(_session->commit_transaction(_session, nullptr));
+ }
+
+ unittest::TempDir _path{"wiredtiger_operation_stats_test"};
+ std::string _uri{"table:wiredtiger_operation_stats_test"};
+ WT_CONNECTION* _conn;
+ WT_SESSION* _session;
+ int64_t _key = 0;
+};
+
+TEST_F(WiredTigerOperationStatsTest, Empty) {
+ ASSERT_BSONOBJ_EQ(WiredTigerOperationStats{_session}.toBSON(), BSONObj{});
+}
+
+TEST_F(WiredTigerOperationStatsTest, Write) {
+ write("a");
+
+ auto statsObj = WiredTigerOperationStats{_session}.toBSON();
+
+ auto dataSection = statsObj["data"];
+ ASSERT_EQ(dataSection.type(), BSONType::Object) << statsObj;
+
+ ASSERT(dataSection["bytesWritten"]) << statsObj;
+ ASSERT(dataSection["timeWritingMicros"]) << statsObj;
+ for (auto&& [name, value] : dataSection.Obj()) {
+ ASSERT_EQ(value.type(), BSONType::NumberLong) << statsObj;
+ ASSERT_GT(value.numberLong(), 0) << statsObj;
+ }
+}
+
+TEST_F(WiredTigerOperationStatsTest, Read) {
+ write("a");
+ read();
+
+ auto statsObj = WiredTigerOperationStats{_session}.toBSON();
+
+ auto dataSection = statsObj["data"];
+ ASSERT_EQ(dataSection.type(), BSONType::Object) << statsObj;
+
+ ASSERT(dataSection["bytesRead"]) << statsObj;
+ ASSERT(dataSection["timeReadingMicros"]) << statsObj;
+ for (auto&& [name, value] : dataSection.Obj()) {
+ ASSERT_EQ(value.type(), BSONType::NumberLong) << statsObj;
+ ASSERT_GT(value.numberLong(), 0) << statsObj;
+ }
+}
+
+TEST_F(WiredTigerOperationStatsTest, Large) {
+ auto remaining = static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 1;
+ while (remaining > 0) {
+ std::string data(1024 * 1024, 'a');
+ remaining -= data.size();
+ write(data);
+ }
+
+ auto statsObj = WiredTigerOperationStats{_session}.toBSON();
+ ASSERT_GT(statsObj["data"]["bytesWritten"].Long(), std::numeric_limits<uint32_t>::max())
+ << statsObj;
+
+ read();
+
+ statsObj = WiredTigerOperationStats{_session}.toBSON();
+ ASSERT_GT(statsObj["data"]["bytesRead"].Long(), std::numeric_limits<uint32_t>::max())
+ << statsObj;
+}
+
+TEST_F(WiredTigerOperationStatsTest, Add) {
+ std::vector<std::unique_ptr<WiredTigerOperationStats>> stats;
+
+ write("a");
+ stats.push_back(std::make_unique<WiredTigerOperationStats>(_session));
+
+ read();
+ stats.push_back(std::make_unique<WiredTigerOperationStats>(_session));
+
+ write("aa");
+ stats.push_back(std::make_unique<WiredTigerOperationStats>(_session));
+
+ read();
+ stats.push_back(std::make_unique<WiredTigerOperationStats>(_session));
+
+ long long bytesWritten = 0;
+ long long timeWritingMicros = 0;
+ long long bytesRead = 0;
+ long long timeReadingMicros = 0;
+
+ WiredTigerOperationStats combined;
+
+ for (auto&& op : stats) {
+ auto statsObj = op->toBSON();
+
+ bytesWritten += statsObj["data"]["bytesWritten"].numberLong();
+ timeWritingMicros += statsObj["data"]["timeWritingMicros"].numberLong();
+ bytesRead += statsObj["data"]["bytesRead"].numberLong();
+ timeReadingMicros += statsObj["data"]["timeReadingMicros"].numberLong();
+
+ combined += *op;
+ }
+
+ auto combinedObj = combined.toBSON();
+ auto dataSection = combinedObj["data"];
+ ASSERT_EQ(dataSection.type(), BSONType::Object) << combinedObj;
+ ASSERT_EQ(dataSection["bytesWritten"].Long(), bytesWritten) << combinedObj;
+ ASSERT_EQ(dataSection["timeWritingMicros"].Long(), timeWritingMicros) << combinedObj;
+ ASSERT_EQ(dataSection["bytesRead"].Long(), bytesRead) << combinedObj;
+ ASSERT_EQ(dataSection["timeReadingMicros"].Long(), timeReadingMicros) << combinedObj;
+}
+
+TEST_F(WiredTigerOperationStatsTest, Clone) {
+ write("a");
+
+ WiredTigerOperationStats stats{_session};
+ auto clone = stats.clone();
+
+ ASSERT_BSONOBJ_EQ(stats.toBSON(), clone->toBSON());
+
+ stats += *clone;
+ ASSERT_BSONOBJ_NE(stats.toBSON(), clone->toBSON());
+}
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp
index 1f4d9d567b7..26f91072bbd 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/server_options.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_begin_transaction_block.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_kv_engine.h"
+#include "mongo/db/storage/wiredtiger/wiredtiger_operation_stats.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_prepare_conflict.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_session_cache.h"
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
@@ -82,107 +83,6 @@ void handleWriteContextForDebugging(WiredTigerRecoveryUnit& ru, Timestamp& ts) {
AtomicWord<std::int64_t> snapshotTooOldErrorCount{0};
-using Section = WiredTigerOperationStats::Section;
-
-std::map<int, std::pair<StringData, Section>> WiredTigerOperationStats::_statNameMap = {
- {WT_STAT_SESSION_BYTES_READ, std::make_pair("bytesRead"_sd, Section::DATA)},
- {WT_STAT_SESSION_BYTES_WRITE, std::make_pair("bytesWritten"_sd, Section::DATA)},
- {WT_STAT_SESSION_LOCK_DHANDLE_WAIT, std::make_pair("handleLock"_sd, Section::WAIT)},
- {WT_STAT_SESSION_READ_TIME, std::make_pair("timeReadingMicros"_sd, Section::DATA)},
- {WT_STAT_SESSION_WRITE_TIME, std::make_pair("timeWritingMicros"_sd, Section::DATA)},
- {WT_STAT_SESSION_LOCK_SCHEMA_WAIT, std::make_pair("schemaLock"_sd, Section::WAIT)},
- {WT_STAT_SESSION_CACHE_TIME, std::make_pair("cache"_sd, Section::WAIT)}};
-
-std::shared_ptr<StorageStats> WiredTigerOperationStats::getCopy() {
- std::shared_ptr<WiredTigerOperationStats> copy = std::make_shared<WiredTigerOperationStats>();
- *copy += *this;
- return copy;
-}
-
-void WiredTigerOperationStats::fetchStats(WT_SESSION* session,
- const std::string& uri,
- const std::string& config) {
- invariant(session);
-
- 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);
- uassert(ErrorCodes::CursorNotFound, "Unable to open statistics cursor", ret == 0);
-
- invariant(c);
- ON_BLOCK_EXIT([&] { c->close(c); });
-
- const char* desc;
- uint64_t value;
- int32_t key;
- while (c->next(c) == 0 && c->get_key(c, &key) == 0) {
- fassert(51035, c->get_value(c, &desc, nullptr, &value) == 0);
- _stats[key] = WiredTigerUtil::castStatisticsValue<long long>(value);
- }
-
- // Reset the statistics so that the next fetch gives the recent values.
- invariantWTOK(c->reset(c), c->session);
-}
-
-BSONObj WiredTigerOperationStats::toBSON() {
- BSONObjBuilder bob;
- std::unique_ptr<BSONObjBuilder> dataSection;
- std::unique_ptr<BSONObjBuilder> waitSection;
-
- for (auto const& stat : _stats) {
- // Find the user consumable name for this statistic.
- auto statIt = _statNameMap.find(stat.first);
-
- // Ignore the session statistic that is not reported for the slow operations.
- if (statIt == _statNameMap.end())
- continue;
-
- auto statName = statIt->second.first;
- Section subs = statIt->second.second;
- long long val = stat.second;
- // Add this statistic only if higher than zero.
- if (val > 0) {
- // Gather the statistic into its own subsection in the BSONObj.
- switch (subs) {
- case Section::DATA:
- if (!dataSection)
- dataSection = std::make_unique<BSONObjBuilder>();
-
- dataSection->append(statName, val);
- break;
- case Section::WAIT:
- if (!waitSection)
- waitSection = std::make_unique<BSONObjBuilder>();
-
- waitSection->append(statName, val);
- break;
- default:
- MONGO_UNREACHABLE;
- }
- }
- }
-
- if (dataSection)
- bob.append("data", dataSection->obj());
- if (waitSection)
- bob.append("timeWaitingMicros", waitSection->obj());
-
- return bob.obj();
-}
-
-WiredTigerOperationStats& WiredTigerOperationStats::operator+=(
- const WiredTigerOperationStats& other) {
- for (auto const& otherStat : other._stats) {
- _stats[otherStat.first] += otherStat.second;
- }
- return (*this);
-}
-
-StorageStats& WiredTigerOperationStats::operator+=(const StorageStats& other) {
- *this += checked_cast<const WiredTigerOperationStats&>(other);
- return (*this);
-}
-
WiredTigerRecoveryUnit::WiredTigerRecoveryUnit(WiredTigerSessionCache* sc)
: WiredTigerRecoveryUnit(sc, sc->getKVEngine()->getOplogManager()) {}
@@ -996,18 +896,7 @@ void WiredTigerRecoveryUnit::beginIdle() {
}
std::shared_ptr<StorageStats> WiredTigerRecoveryUnit::getOperationStatistics() const {
- std::shared_ptr<WiredTigerOperationStats> statsPtr(nullptr);
-
- if (!_session)
- return statsPtr;
-
- WT_SESSION* s = _session->getSession();
- invariant(s);
-
- statsPtr = std::make_shared<WiredTigerOperationStats>();
- statsPtr->fetchStats(s, "statistics:session", "statistics=(fast)");
-
- return statsPtr;
+ return _session ? std::make_shared<WiredTigerOperationStats>(_session->getSession()) : nullptr;
}
void WiredTigerRecoveryUnit::setCatalogConflictingTimestamp(Timestamp timestamp) {
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
index 26102686dbd..2d38888dc90 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.h
@@ -56,41 +56,6 @@ extern AtomicWord<std::int64_t> snapshotTooOldErrorCount;
class BSONObjBuilder;
-class WiredTigerOperationStats final : public StorageStats {
-public:
- /**
- * There are two types of statistics provided by WiredTiger engine - data and wait.
- */
- enum class Section { DATA, WAIT };
-
- BSONObj toBSON() final;
-
- StorageStats& operator+=(const StorageStats&) final;
-
- WiredTigerOperationStats& operator+=(const WiredTigerOperationStats&);
-
- /**
- * Fetches an operation's storage statistics from WiredTiger engine.
- */
- void fetchStats(WT_SESSION*, const std::string&, const std::string&);
-
- std::shared_ptr<StorageStats> getCopy() final;
-
-private:
- /**
- * Each statistic in WiredTiger has an integer key, which this map associates with a section
- * (either DATA or WAIT) and user-readable name.
- */
- static std::map<int, std::pair<StringData, Section>> _statNameMap;
-
- /**
- * Stores the value for each statistic returned by a WiredTiger cursor. Each statistic is
- * associated with an integer key, which can be mapped to a name and section using the
- * '_statNameMap'.
- */
- std::map<int, long long> _stats;
-};
-
class WiredTigerRecoveryUnit final : public RecoveryUnit {
public:
WiredTigerRecoveryUnit(WiredTigerSessionCache* sc);
diff --git a/src/mongo/db/transaction/transaction_metrics_observer.cpp b/src/mongo/db/transaction/transaction_metrics_observer.cpp
index 0a503e3b135..7a6544a1b3b 100644
--- a/src/mongo/db/transaction/transaction_metrics_observer.cpp
+++ b/src/mongo/db/transaction/transaction_metrics_observer.cpp
@@ -188,7 +188,7 @@ void TransactionMetricsObserver::onTransactionOperation(OperationContext* opCtx,
if (storageStats) {
CurOp::get(opCtx)->debug().storageStats = storageStats;
if (!_singleTransactionStats.getOpDebug()->storageStats) {
- _singleTransactionStats.getOpDebug()->storageStats = storageStats->getCopy();
+ _singleTransactionStats.getOpDebug()->storageStats = storageStats->clone();
} else {
*_singleTransactionStats.getOpDebug()->storageStats += *storageStats;
}