summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/transaction_metrics_observer.cpp171
-rw-r--r--src/mongo/db/transaction_metrics_observer.h112
-rw-r--r--src/mongo/db/transaction_participant.cpp142
-rw-r--r--src/mongo/db/transaction_participant.h9
-rw-r--r--src/mongo/db/transaction_participant_test.cpp414
6 files changed, 535 insertions, 314 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index cd44408e1ad..a44af50681b 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -628,6 +628,7 @@ env.Library(
'single_transaction_stats.cpp',
'transaction_coordinator.cpp',
'transaction_coordinator_commands_impl.cpp',
+ 'transaction_metrics_observer.cpp',
'transaction_participant.cpp',
'transaction_history_iterator.cpp',
env.Idlc('session_txn_record.idl')[0],
diff --git a/src/mongo/db/transaction_metrics_observer.cpp b/src/mongo/db/transaction_metrics_observer.cpp
new file mode 100644
index 00000000000..57143824bbb
--- /dev/null
+++ b/src/mongo/db/transaction_metrics_observer.cpp
@@ -0,0 +1,171 @@
+/**
+ * Copyright (C) 2018 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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/platform/basic.h"
+
+#include "mongo/db/transaction_metrics_observer.h"
+
+#include "mongo/db/server_transactions_metrics.h"
+#include "mongo/db/transaction_participant.h"
+
+namespace mongo {
+
+void TransactionMetricsObserver::onStart(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime) {
+ //
+ // Per transaction metrics.
+ //
+ _singleTransactionStats.setStartTime(curTime);
+
+ //
+ // Server wide transactions metrics.
+ //
+ serverTransactionsMetrics->incrementTotalStarted();
+ serverTransactionsMetrics->incrementCurrentOpen();
+ serverTransactionsMetrics->incrementCurrentInactive();
+}
+
+void TransactionMetricsObserver::onStash(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime) {
+ //
+ // Per transaction metrics.
+ //
+ // The transaction operation may be trying to stash its resources when it has already been
+ // aborted by another thread, so we check that the transaction is active before setting it as
+ // inactive.
+ if (_singleTransactionStats.isActive()) {
+ _singleTransactionStats.setInactive(curTime);
+ }
+
+ //
+ // Server wide transactions metrics.
+ //
+ // We accept possible slight inaccuracies in these counters from non-atomicity.
+ serverTransactionsMetrics->decrementCurrentActive();
+ serverTransactionsMetrics->incrementCurrentInactive();
+}
+
+void TransactionMetricsObserver::onUnstash(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime) {
+ //
+ // Per transaction metrics.
+ //
+ _singleTransactionStats.setActive(curTime);
+
+ //
+ // Server wide transactions metrics.
+ //
+ // We accept possible slight inaccuracies in these counters from non-atomicity.
+ serverTransactionsMetrics->incrementCurrentActive();
+ serverTransactionsMetrics->decrementCurrentInactive();
+}
+
+void TransactionMetricsObserver::onCommit(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top) {
+ //
+ // Per transaction metrics.
+ //
+ // After the transaction has been committed, we must update the end time and mark it as
+ // inactive. We use the same "now" time to prevent skew in the time-related metrics.
+ _singleTransactionStats.setEndTime(curTime);
+ // The transaction operation may have already been aborted by another thread, so we check that
+ // the transaction is active before setting it as inactive.
+ if (_singleTransactionStats.isActive()) {
+ _singleTransactionStats.setInactive(curTime);
+ }
+
+ //
+ // Server wide transactions metrics.
+ //
+ serverTransactionsMetrics->incrementTotalCommitted();
+ serverTransactionsMetrics->decrementCurrentOpen();
+ serverTransactionsMetrics->decrementCurrentActive();
+
+ top->incrementGlobalTransactionLatencyStats(_singleTransactionStats.getDuration(curTime));
+}
+
+void TransactionMetricsObserver::onAbortActive(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top) {
+ _onAbort(serverTransactionsMetrics, curTime, top);
+ //
+ // Per transaction metrics.
+ //
+ // The transaction operation may have already been aborted by another thread, so we check that
+ // the transaction is active before setting it as inactive.
+ if (_singleTransactionStats.isActive()) {
+ _singleTransactionStats.setInactive(curTime);
+ }
+
+ //
+ // Server wide transactions metrics.
+ //
+ serverTransactionsMetrics->decrementCurrentActive();
+}
+
+void TransactionMetricsObserver::onAbortInactive(
+ ServerTransactionsMetrics* serverTransactionsMetrics, unsigned long long curTime, Top* top) {
+ _onAbort(serverTransactionsMetrics, curTime, top);
+
+ //
+ // Server wide transactions metrics.
+ //
+ serverTransactionsMetrics->decrementCurrentInactive();
+}
+
+void TransactionMetricsObserver::onTransactionOperation(Client* client,
+ OpDebug::AdditiveMetrics additiveMetrics) {
+ // Add the latest operation stats to the aggregate OpDebug::AdditiveMetrics object stored in the
+ // SingleTransactionStats instance on the TransactionMetricsObserver.
+ _singleTransactionStats.getOpDebug()->additiveMetrics.add(additiveMetrics);
+
+ // Update the LastClientInfo object stored in the SingleTransactionStats instance on the
+ // TransactionMetricsObserver with this Client's information. This is the last client that ran a
+ // transaction operation on the txnParticipant.
+ _singleTransactionStats.updateLastClientInfo(client);
+}
+
+void TransactionMetricsObserver::_onAbort(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top) {
+ //
+ // Per transaction metrics.
+ //
+ _singleTransactionStats.setEndTime(curTime);
+
+ //
+ // Server wide transactions metrics.
+ //
+ serverTransactionsMetrics->incrementTotalAborted();
+ serverTransactionsMetrics->decrementCurrentOpen();
+
+ top->incrementGlobalTransactionLatencyStats(_singleTransactionStats.getDuration(curTime));
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/transaction_metrics_observer.h b/src/mongo/db/transaction_metrics_observer.h
new file mode 100644
index 00000000000..a420f02d14a
--- /dev/null
+++ b/src/mongo/db/transaction_metrics_observer.h
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2018 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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/db/curop.h"
+#include "mongo/db/server_transactions_metrics.h"
+#include "mongo/db/single_transaction_stats.h"
+#include "mongo/db/stats/top.h"
+
+namespace mongo {
+
+/**
+ * Updates transaction metrics (per-transaction metrics and server-wide transactions metrics) upon
+ * the appropriate transaction event.
+ */
+class TransactionMetricsObserver {
+
+public:
+ /**
+ * Updates relevant metrics when a transaction begins.
+ */
+ void onStart(ServerTransactionsMetrics* serverTransactionMetrics, unsigned long long curTime);
+
+ /**
+ * Updates relevant metrics when a transaction stashes its resources.
+ */
+ void onStash(ServerTransactionsMetrics* serverTransactionMetrics, unsigned long long curTime);
+
+ /**
+ * Updates relevant metrics when a transaction unstashes its resources.
+ */
+ void onUnstash(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime);
+
+ /**
+ * Updates relevant metrics when a transaction commits.
+ */
+ void onCommit(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top);
+
+ /**
+ * Updates relevant metrics when an active transaction aborts.
+ */
+ void onAbortActive(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top);
+
+ /**
+ * Updates relevant metrics when an inactive transaction aborts.
+ */
+ void onAbortInactive(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top);
+
+ /**
+ * Updates relevant metrics when an operation running on the transaction completes. An operation
+ * may be a read/write operation, or an abort/commit command.
+ */
+ void onTransactionOperation(Client* client, OpDebug::AdditiveMetrics additiveMetrics);
+
+ /**
+ * Returns the SingleTransactionStats object stored in this TransactionMetricsObserver instance.
+ */
+ SingleTransactionStats getSingleTransactionStats() const {
+ return _singleTransactionStats;
+ }
+
+ /**
+ * Resets the SingleTransactionStats object stored in this TransactionMetricsObserver instance.
+ */
+ void resetSingleTransactionStats() {
+ _singleTransactionStats = SingleTransactionStats();
+ }
+
+private:
+ // Updates relevant metrics for any generic transaction abort.
+ void _onAbort(ServerTransactionsMetrics* serverTransactionsMetrics,
+ unsigned long long curTime,
+ Top* top);
+
+ // Tracks metrics for a single multi-document transaction.
+ SingleTransactionStats _singleTransactionStats;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp
index 50812cf4c8e..d3480a14327 100644
--- a/src/mongo/db/transaction_participant.cpp
+++ b/src/mongo/db/transaction_participant.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/session.h"
#include "mongo/db/session_catalog.h"
#include "mongo/db/stats/fill_locker_info.h"
-#include "mongo/db/stats/top.h"
#include "mongo/util/fail_point_service.h"
#include "mongo/util/log.h"
#include "mongo/util/net/socket_utils.h"
@@ -208,17 +207,13 @@ void TransactionParticipant::_beginMultiDocumentTransaction(WithLock wl, TxnNumb
_txnState.transitionTo(wl, TransactionState::kInProgress);
- // Tracks various transactions metrics.
- _singleTransactionStats.setStartTime(curTimeMicros64());
- _transactionExpireDate =
- Date_t::fromMillisSinceEpoch(_singleTransactionStats.getStartTime() / 1000) +
+ // Start tracking various transactions metrics.
+ auto curTime = curTimeMicros64();
+ _transactionMetricsObserver.onStart(ServerTransactionsMetrics::get(getGlobalServiceContext()),
+ curTime);
+ _transactionExpireDate = Date_t::fromMillisSinceEpoch(curTime / 1000) +
stdx::chrono::seconds{transactionLifetimeLimitSeconds.load()};
- ServerTransactionsMetrics::get(getGlobalServiceContext())->incrementTotalStarted();
- // The transaction is considered open here and stays inactive until its first unstash event.
- ServerTransactionsMetrics::get(getGlobalServiceContext())->incrementCurrentOpen();
- ServerTransactionsMetrics::get(getGlobalServiceContext())->incrementCurrentInactive();
-
invariant(_transactionOperations.empty());
}
@@ -393,26 +388,12 @@ TransactionParticipant::SideTransactionBlock::~SideTransactionBlock() {
void TransactionParticipant::_stashActiveTransaction(WithLock, OperationContext* opCtx) {
invariant(_activeTxnNumber == opCtx->getTxnNumber());
- if (_singleTransactionStats.isActive()) {
- _singleTransactionStats.setInactive(curTimeMicros64());
- }
-
- // Add the latest operation stats to the aggregate OpDebug object stored in the
- // SingleTransactionStats instance on the Session.
- _singleTransactionStats.getOpDebug()->additiveMetrics.add(
- CurOp::get(opCtx)->debug().additiveMetrics);
+ _transactionMetricsObserver.onStash(ServerTransactionsMetrics::get(opCtx), curTimeMicros64());
+ _transactionMetricsObserver.onTransactionOperation(opCtx->getClient(),
+ CurOp::get(opCtx)->debug().additiveMetrics);
invariant(!_txnResourceStash);
_txnResourceStash = TxnResources(opCtx);
-
- // We accept possible slight inaccuracies in these counters from non-atomicity.
- ServerTransactionsMetrics::get(opCtx)->decrementCurrentActive();
- ServerTransactionsMetrics::get(opCtx)->incrementCurrentInactive();
-
- // Update the LastClientInfo object stored in the SingleTransactionStats instance on the Session
- // with this Client's information. This is the last client that ran a transaction operation on
- // the Session.
- _singleTransactionStats.updateLastClientInfo(opCtx->getClient());
}
@@ -491,13 +472,8 @@ void TransactionParticipant::unstashTransactionResources(OperationContext* opCtx
readConcernArgs.isEmpty());
_txnResourceStash->release(opCtx);
_txnResourceStash = boost::none;
- // Set the starting active time for this transaction.
- if (_txnState.isInProgress(lk)) {
- _singleTransactionStats.setActive(curTimeMicros64());
- }
- // We accept possible slight inaccuracies in these counters from non-atomicity.
- ServerTransactionsMetrics::get(opCtx)->incrementCurrentActive();
- ServerTransactionsMetrics::get(opCtx)->decrementCurrentInactive();
+ _transactionMetricsObserver.onUnstash(ServerTransactionsMetrics::get(opCtx),
+ curTimeMicros64());
return;
}
@@ -513,11 +489,9 @@ void TransactionParticipant::unstashTransactionResources(OperationContext* opCtx
// Stashed transaction resources do not exist for this in-progress multi-document
// transaction. Set up the transaction resources on the opCtx.
opCtx->setWriteUnitOfWork(std::make_unique<WriteUnitOfWork>(opCtx));
- ServerTransactionsMetrics::get(getGlobalServiceContext())->incrementCurrentActive();
- ServerTransactionsMetrics::get(getGlobalServiceContext())->decrementCurrentInactive();
- // Set the starting active time for this transaction.
- _singleTransactionStats.setActive(curTimeMicros64());
+ _transactionMetricsObserver.onUnstash(ServerTransactionsMetrics::get(opCtx),
+ curTimeMicros64());
// If maxTransactionLockRequestTimeoutMillis is set, then we will ensure no
// future lock request waits longer than maxTransactionLockRequestTimeoutMillis
@@ -740,28 +714,11 @@ void TransactionParticipant::_commitTransaction(stdx::unique_lock<stdx::mutex> l
_txnState.transitionTo(lk, TransactionState::kCommitted);
- // After the transaction has been committed, we must update the end time and mark it as
- // inactive.
- const auto now = curTimeMicros64();
- _singleTransactionStats.setEndTime(now);
- if (_singleTransactionStats.isActive()) {
- _singleTransactionStats.setInactive(now);
- }
-
- ServerTransactionsMetrics::get(opCtx)->incrementTotalCommitted();
- ServerTransactionsMetrics::get(opCtx)->decrementCurrentOpen();
- ServerTransactionsMetrics::get(getGlobalServiceContext())->decrementCurrentActive();
- Top::get(getGlobalServiceContext())
- .incrementGlobalTransactionLatencyStats(_singleTransactionStats.getDuration(now));
-
- // Add the latest operation stats to the aggregate OpDebug object stored in the
- // SingleTransactionStats instance on the Session.
- _singleTransactionStats.getOpDebug()->additiveMetrics.add(
- CurOp::get(opCtx)->debug().additiveMetrics);
-
- // Update the LastClientInfo object stored in the SingleTransactionStats instance on the Session
- // with this Client's information.
- _singleTransactionStats.updateLastClientInfo(opCtx->getClient());
+ const auto curTime = curTimeMicros64();
+ _transactionMetricsObserver.onCommit(
+ ServerTransactionsMetrics::get(opCtx), curTime, &Top::get(getGlobalServiceContext()));
+ _transactionMetricsObserver.onTransactionOperation(opCtx->getClient(),
+ CurOp::get(opCtx)->debug().additiveMetrics);
// Log the transaction if its duration is longer than the slowMS command threshold.
_logSlowTransaction(lk,
@@ -834,14 +791,8 @@ void TransactionParticipant::_abortActiveTransaction(WithLock lock,
invariant(!_txnResourceStash);
if (!_txnState.isNone(lock)) {
- // Add the latest operation stats to the aggregate OpDebug object stored in the
- // SingleTransactionStats instance on the Session.
- _singleTransactionStats.getOpDebug()->additiveMetrics.add(
- CurOp::get(opCtx)->debug().additiveMetrics);
-
- // Update the LastClientInfo object stored in the SingleTransactionStats instance on the
- // Session with this Client's information.
- _singleTransactionStats.updateLastClientInfo(opCtx->getClient());
+ _transactionMetricsObserver.onTransactionOperation(
+ opCtx->getClient(), CurOp::get(opCtx)->debug().additiveMetrics);
}
// Only abort the transaction in session if it's in expected states.
@@ -881,28 +832,24 @@ void TransactionParticipant::_abortActiveTransaction(WithLock lock,
}
void TransactionParticipant::_abortTransactionOnSession(WithLock wl) {
- const auto now = curTimeMicros64();
- if (!_txnState.isNone(wl)) {
- _singleTransactionStats.setEndTime(now);
- // The transaction has aborted, so we mark it as inactive.
- if (_singleTransactionStats.isActive()) {
- _singleTransactionStats.setInactive(now);
- }
- }
-
+ const auto curTime = curTimeMicros64();
// If the transaction is stashed, then we have aborted an inactive transaction.
if (_txnResourceStash) {
// The transaction is stashed, so we abort the inactive transaction on session.
+ _transactionMetricsObserver.onAbortInactive(
+ ServerTransactionsMetrics::get(getGlobalServiceContext()),
+ curTime,
+ &Top::get(getGlobalServiceContext()));
_logSlowTransaction(wl,
&(_txnResourceStash->locker()->getLockerInfo())->stats,
TransactionState::kAborted,
_txnResourceStash->getReadConcernArgs());
_txnResourceStash = boost::none;
- ServerTransactionsMetrics::get(getGlobalServiceContext())->decrementCurrentInactive();
} else {
- // Transaction resource has been unstashed and transferred into an active opCtx, which will
- // clean it up.
- ServerTransactionsMetrics::get(getGlobalServiceContext())->decrementCurrentActive();
+ _transactionMetricsObserver.onAbortActive(
+ ServerTransactionsMetrics::get(getGlobalServiceContext()),
+ curTime,
+ &Top::get(getGlobalServiceContext()));
}
_transactionOperationBytes = 0;
@@ -911,12 +858,6 @@ void TransactionParticipant::_abortTransactionOnSession(WithLock wl) {
_speculativeTransactionReadOpTime = repl::OpTime();
_getSession()->unlockTxnNumber();
-
- ServerTransactionsMetrics::get(getGlobalServiceContext())->incrementTotalAborted();
- ServerTransactionsMetrics::get(getGlobalServiceContext())->decrementCurrentOpen();
-
- Top::get(getGlobalServiceContext())
- .incrementGlobalTransactionLatencyStats(_singleTransactionStats.getDuration(now));
}
void TransactionParticipant::_cleanUpTxnResourceOnOpCtx(WithLock wl, OperationContext* opCtx) {
@@ -1000,7 +941,8 @@ void TransactionParticipant::reportStashedState(BSONObjBuilder* builder) const {
builder->append("host", getHostNameCachedAndPort());
builder->append("desc", "inactive transaction");
- auto lastClientInfo = _singleTransactionStats.getLastClientInfo();
+ auto lastClientInfo =
+ _transactionMetricsObserver.getSingleTransactionStats().getLastClientInfo();
builder->append("client", lastClientInfo.clientHostAndPort);
builder->append("connectionId", lastClientInfo.connectionId);
builder->append("appName", lastClientInfo.appName);
@@ -1150,19 +1092,21 @@ void TransactionParticipant::_reportTransactionStats(WithLock wl,
parametersBuilder.done();
builder->append("readTimestamp", _speculativeTransactionReadOpTime.getTimestamp());
+
+ auto singleTransactionStats = _transactionMetricsObserver.getSingleTransactionStats();
builder->append("startWallClockTime",
dateToISOStringLocal(Date_t::fromMillisSinceEpoch(
- _singleTransactionStats.getStartTime() / 1000)));
+ singleTransactionStats.getStartTime() / 1000)));
// We use the same "now" time so that the following time metrics are consistent with each other.
auto curTime = curTimeMicros64();
builder->append("timeOpenMicros",
- static_cast<long long>(_singleTransactionStats.getDuration(curTime)));
+ static_cast<long long>(singleTransactionStats.getDuration(curTime)));
auto timeActive =
- durationCount<Microseconds>(_singleTransactionStats.getTimeActiveMicros(curTime));
+ durationCount<Microseconds>(singleTransactionStats.getTimeActiveMicros(curTime));
auto timeInactive =
- durationCount<Microseconds>(_singleTransactionStats.getTimeInactiveMicros(curTime));
+ durationCount<Microseconds>(singleTransactionStats.getTimeInactiveMicros(curTime));
builder->append("timeActiveMicros", timeActive);
builder->append("timeInactiveMicros", timeInactive);
@@ -1278,7 +1222,9 @@ std::string TransactionParticipant::_transactionInfoForLog(
s << " readTimestamp:" << _speculativeTransactionReadOpTime.getTimestamp().toString() << ",";
- s << _singleTransactionStats.getOpDebug()->additiveMetrics.report();
+ auto singleTransactionStats = _transactionMetricsObserver.getSingleTransactionStats();
+
+ s << singleTransactionStats.getOpDebug()->additiveMetrics.report();
std::string terminationCauseString =
terminationCause == TransactionState::kCommitted ? "committed" : "aborted";
@@ -1286,9 +1232,9 @@ std::string TransactionParticipant::_transactionInfoForLog(
auto curTime = curTimeMicros64();
s << " timeActiveMicros:"
- << durationCount<Microseconds>(_singleTransactionStats.getTimeActiveMicros(curTime));
+ << durationCount<Microseconds>(singleTransactionStats.getTimeActiveMicros(curTime));
s << " timeInactiveMicros:"
- << durationCount<Microseconds>(_singleTransactionStats.getTimeInactiveMicros(curTime));
+ << durationCount<Microseconds>(singleTransactionStats.getTimeInactiveMicros(curTime));
// Number of yields is always 0 in multi-document transactions, but it is included mainly to
// match the format with other slow operation logging messages.
@@ -1301,7 +1247,7 @@ std::string TransactionParticipant::_transactionInfoForLog(
// Total duration of the transaction.
s << " "
- << Milliseconds{static_cast<long long>(_singleTransactionStats.getDuration(curTime)) / 1000};
+ << Milliseconds{static_cast<long long>(singleTransactionStats.getDuration(curTime)) / 1000};
return s.str();
}
@@ -1313,7 +1259,7 @@ void TransactionParticipant::_logSlowTransaction(WithLock wl,
// Only log multi-document transactions.
if (!_txnState.isNone(wl)) {
// Log the transaction if its duration is longer than the slowMS command threshold.
- if (_singleTransactionStats.getDuration(curTimeMicros64()) >
+ if (_transactionMetricsObserver.getSingleTransactionStats().getDuration(curTimeMicros64()) >
serverGlobalParams.slowMS * 1000ULL) {
log(logger::LogComponent::kTransaction)
<< "transaction "
@@ -1341,7 +1287,7 @@ void TransactionParticipant::_setNewTxnNumber(WithLock wl, const TxnNumber& txnN
_activeTxnNumber = txnNumber;
_txnState.transitionTo(wl, TransactionState::kNone);
- _singleTransactionStats = SingleTransactionStats();
+ _transactionMetricsObserver.resetSingleTransactionStats();
_speculativeTransactionReadOpTime = repl::OpTime();
_multikeyPathInfo.clear();
_autoCommit = boost::none;
diff --git a/src/mongo/db/transaction_participant.h b/src/mongo/db/transaction_participant.h
index 7dbef532bad..ae5ad91db63 100644
--- a/src/mongo/db/transaction_participant.h
+++ b/src/mongo/db/transaction_participant.h
@@ -41,6 +41,7 @@
#include "mongo/db/session.h"
#include "mongo/db/single_transaction_stats.h"
#include "mongo/db/storage/recovery_unit.h"
+#include "mongo/db/transaction_metrics_observer.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/concurrency/with_lock.h"
#include "mongo/util/decorable.h"
@@ -281,7 +282,7 @@ public:
}
SingleTransactionStats getSingleTransactionStats() const {
- return _singleTransactionStats;
+ return _transactionMetricsObserver.getSingleTransactionStats();
}
repl::OpTime getSpeculativeTransactionReadOpTimeForTest() const {
@@ -623,11 +624,11 @@ private:
std::vector<MultikeyPathInfo> _multikeyPathInfo;
- // Tracks metrics for a single multi-document transaction.
- SingleTransactionStats _singleTransactionStats;
-
// Remembers the refresh count this object has read from Session.
long long _lastStateRefreshCount{0};
+
+ // Tracks and updates transaction metrics upon the appropriate transaction event.
+ TransactionMetricsObserver _transactionMetricsObserver;
};
inline StringBuilder& operator<<(StringBuilder& sb,
diff --git a/src/mongo/db/transaction_participant_test.cpp b/src/mongo/db/transaction_participant_test.cpp
index 6270ece60e0..9d96444e6f1 100644
--- a/src/mongo/db/transaction_participant_test.cpp
+++ b/src/mongo/db/transaction_participant_test.cpp
@@ -1300,190 +1300,6 @@ TEST_F(TxnParticipantTest, TransactionTooLargeWhileBuilding) {
ErrorCodes::TransactionTooLarge);
}
-TEST_F(TxnParticipantTest, IncrementTotalStartedUponStartTransaction) {
- unsigned long long beforeTransactionStart =
- ServerTransactionsMetrics::get(opCtx())->getTotalStarted();
-
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
-
- // Tests that the total transactions started counter is incremented by 1 when a new transaction
- // is started.
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalStarted(),
- beforeTransactionStart + 1U);
-}
-
-TEST_F(TxnParticipantTest, IncrementTotalCommittedOnCommit) {
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "commitTransaction");
-
- unsigned long long beforeCommitCount =
- ServerTransactionsMetrics::get(opCtx())->getTotalCommitted();
-
- txnParticipant->commitUnpreparedTransaction(opCtx());
-
- // Assert that the committed counter is incremented by 1.
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalCommitted(), beforeCommitCount + 1U);
-}
-
-TEST_F(TxnParticipantTest, IncrementTotalAbortedUponAbort) {
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
-
- unsigned long long beforeAbortCount =
- ServerTransactionsMetrics::get(opCtx())->getTotalAborted();
-
- txnParticipant->abortArbitraryTransaction();
-
- // Assert that the aborted counter is incremented by 1.
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalAborted(), beforeAbortCount + 1U);
-}
-
-TEST_F(TxnParticipantTest, TrackTotalOpenTransactionsWithAbort) {
- unsigned long long beforeTransactionStart =
- ServerTransactionsMetrics::get(opCtx())->getCurrentOpen();
-
- // Tests that starting a transaction increments the open transactions counter by 1.
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
- beforeTransactionStart + 1U);
-
- // Tests that stashing the transaction resources does not affect the open transactions counter.
- { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
- txnParticipant->stashTransactionResources(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
- beforeTransactionStart + 1U);
-
- // Tests that aborting a transaction decrements the open transactions counter by 1.
- txnParticipant->abortArbitraryTransaction();
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(), beforeTransactionStart);
-}
-
-TEST_F(TxnParticipantTest, TrackTotalOpenTransactionsWithCommit) {
- unsigned long long beforeTransactionStart =
- ServerTransactionsMetrics::get(opCtx())->getCurrentOpen();
-
- // Tests that starting a transaction increments the open transactions counter by 1.
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
- beforeTransactionStart + 1U);
-
- // Tests that stashing the transaction resources does not affect the open transactions counter.
- { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
- txnParticipant->stashTransactionResources(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
- beforeTransactionStart + 1U);
-
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
-
- // Tests that committing a transaction decrements the open transactions counter by 1.
- txnParticipant->commitUnpreparedTransaction(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(), beforeTransactionStart);
-}
-
-TEST_F(TxnParticipantTest, TrackTotalActiveAndInactiveTransactionsWithCommit) {
- unsigned long long beforeActiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
- unsigned long long beforeInactiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
-
- // Starting the transaction should put it into an inactive state.
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
- beforeInactiveCounter + 1);
-
- // Tests that the first unstash increments the active counter and decrements the inactive
- // counter.
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
- beforeActiveCounter + 1U);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-
- // Tests that stashing the transaction resources decrements active counter and increments
- // inactive counter.
- { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
- txnParticipant->stashTransactionResources(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
- beforeInactiveCounter + 1U);
-
- // Tests that the second unstash increments the active counter and decrements the inactive
- // counter.
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
- beforeActiveCounter + 1U);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-
- // Tests that committing a transaction decrements the active counter only.
- txnParticipant->commitUnpreparedTransaction(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-}
-
-TEST_F(TxnParticipantTest, TrackTotalActiveAndInactiveTransactionsWithStashedAbort) {
- unsigned long long beforeActiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
- unsigned long long beforeInactiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
-
- // Starting the transaction should put it into an inactive state.
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
- beforeInactiveCounter + 1);
-
- // Tests that the first unstash increments the active counter and decrements the inactive
- // counter.
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
- beforeActiveCounter + 1U);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-
- // Tests that stashing the transaction resources decrements active counter and increments
- // inactive counter.
- { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
- txnParticipant->stashTransactionResources(opCtx());
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
- beforeInactiveCounter + 1U);
-
- // Tests that aborting a stashed transaction decrements the inactive counter only.
- txnParticipant->abortArbitraryTransaction();
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-}
-
-TEST_F(TxnParticipantTest, TrackTotalActiveAndInactiveTransactionsWithUnstashedAbort) {
- unsigned long long beforeActiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
- unsigned long long beforeInactiveCounter =
- ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
-
- // Starting the transaction should put it into an inactive state.
- OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
- beforeInactiveCounter + 1);
-
- // Tests that the first unstash increments the active counter and decrements the inactive
- // counter.
- auto txnParticipant = TransactionParticipant::get(opCtx());
- txnParticipant->unstashTransactionResources(opCtx(), "insert");
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
- beforeActiveCounter + 1U);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-
- // Tests that aborting a stashed transaction decrements the active counter only.
- txnParticipant->abortArbitraryTransaction();
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
- ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
-}
-
TEST_F(TxnParticipantTest, StashInNestedSessionIsANoop) {
OperationContextSessionMongod outerScopedSession(opCtx(), true, false, true);
Locker* originalLocker = opCtx()->lockState();
@@ -1730,6 +1546,190 @@ TEST_F(ConfigTxnParticipantTest, CannotSpecifyStartTransactionOnStartedRetryable
*/
class TransactionsMetricsTest : public TxnParticipantTest {};
+TEST_F(TransactionsMetricsTest, IncrementTotalStartedUponStartTransaction) {
+ unsigned long long beforeTransactionStart =
+ ServerTransactionsMetrics::get(opCtx())->getTotalStarted();
+
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+
+ // Tests that the total transactions started counter is incremented by 1 when a new transaction
+ // is started.
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalStarted(),
+ beforeTransactionStart + 1U);
+}
+
+TEST_F(TransactionsMetricsTest, IncrementTotalCommittedOnCommit) {
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "commitTransaction");
+
+ unsigned long long beforeCommitCount =
+ ServerTransactionsMetrics::get(opCtx())->getTotalCommitted();
+
+ txnParticipant->commitUnpreparedTransaction(opCtx());
+
+ // Assert that the committed counter is incremented by 1.
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalCommitted(), beforeCommitCount + 1U);
+}
+
+TEST_F(TransactionsMetricsTest, IncrementTotalAbortedUponAbort) {
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+
+ unsigned long long beforeAbortCount =
+ ServerTransactionsMetrics::get(opCtx())->getTotalAborted();
+
+ txnParticipant->abortArbitraryTransaction();
+
+ // Assert that the aborted counter is incremented by 1.
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getTotalAborted(), beforeAbortCount + 1U);
+}
+
+TEST_F(TransactionsMetricsTest, TrackTotalOpenTransactionsWithAbort) {
+ unsigned long long beforeTransactionStart =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentOpen();
+
+ // Tests that starting a transaction increments the open transactions counter by 1.
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
+ beforeTransactionStart + 1U);
+
+ // Tests that stashing the transaction resources does not affect the open transactions counter.
+ { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
+ txnParticipant->stashTransactionResources(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
+ beforeTransactionStart + 1U);
+
+ // Tests that aborting a transaction decrements the open transactions counter by 1.
+ txnParticipant->abortArbitraryTransaction();
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(), beforeTransactionStart);
+}
+
+TEST_F(TransactionsMetricsTest, TrackTotalOpenTransactionsWithCommit) {
+ unsigned long long beforeTransactionStart =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentOpen();
+
+ // Tests that starting a transaction increments the open transactions counter by 1.
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
+ beforeTransactionStart + 1U);
+
+ // Tests that stashing the transaction resources does not affect the open transactions counter.
+ { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
+ txnParticipant->stashTransactionResources(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(),
+ beforeTransactionStart + 1U);
+
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+
+ // Tests that committing a transaction decrements the open transactions counter by 1.
+ txnParticipant->commitUnpreparedTransaction(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentOpen(), beforeTransactionStart);
+}
+
+TEST_F(TransactionsMetricsTest, TrackTotalActiveAndInactiveTransactionsWithCommit) {
+ unsigned long long beforeActiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
+ unsigned long long beforeInactiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
+
+ // Starting the transaction should put it into an inactive state.
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
+ beforeInactiveCounter + 1);
+
+ // Tests that the first unstash increments the active counter and decrements the inactive
+ // counter.
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
+ beforeActiveCounter + 1U);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+
+ // Tests that stashing the transaction resources decrements active counter and increments
+ // inactive counter.
+ { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
+ txnParticipant->stashTransactionResources(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
+ beforeInactiveCounter + 1U);
+
+ // Tests that the second unstash increments the active counter and decrements the inactive
+ // counter.
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
+ beforeActiveCounter + 1U);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+
+ // Tests that committing a transaction decrements the active counter only.
+ txnParticipant->commitUnpreparedTransaction(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+}
+
+TEST_F(TransactionsMetricsTest, TrackTotalActiveAndInactiveTransactionsWithStashedAbort) {
+ unsigned long long beforeActiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
+ unsigned long long beforeInactiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
+
+ // Starting the transaction should put it into an inactive state.
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
+ beforeInactiveCounter + 1);
+
+ // Tests that the first unstash increments the active counter and decrements the inactive
+ // counter.
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
+ beforeActiveCounter + 1U);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+
+ // Tests that stashing the transaction resources decrements active counter and increments
+ // inactive counter.
+ { Lock::GlobalLock lk(opCtx(), MODE_IX, Date_t::now(), Lock::InterruptBehavior::kThrow); }
+ txnParticipant->stashTransactionResources(opCtx());
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
+ beforeInactiveCounter + 1U);
+
+ // Tests that aborting a stashed transaction decrements the inactive counter only.
+ txnParticipant->abortArbitraryTransaction();
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+}
+
+TEST_F(TransactionsMetricsTest, TrackTotalActiveAndInactiveTransactionsWithUnstashedAbort) {
+ unsigned long long beforeActiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentActive();
+ unsigned long long beforeInactiveCounter =
+ ServerTransactionsMetrics::get(opCtx())->getCurrentInactive();
+
+ // Starting the transaction should put it into an inactive state.
+ OperationContextSessionMongod opCtxSession(opCtx(), true, false, true);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(),
+ beforeInactiveCounter + 1);
+
+ // Tests that the first unstash increments the active counter and decrements the inactive
+ // counter.
+ auto txnParticipant = TransactionParticipant::get(opCtx());
+ txnParticipant->unstashTransactionResources(opCtx(), "insert");
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(),
+ beforeActiveCounter + 1U);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+
+ // Tests that aborting a stashed transaction decrements the active counter only.
+ txnParticipant->abortArbitraryTransaction();
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentActive(), beforeActiveCounter);
+ ASSERT_EQ(ServerTransactionsMetrics::get(opCtx())->getCurrentInactive(), beforeInactiveCounter);
+}
+
TEST_F(TransactionsMetricsTest, SingleTransactionStatsStartTimeShouldBeSetUponTransactionStart) {
// Save the time before the transaction is created.
unsigned long long timeBeforeTxn = curTimeMicros64();
@@ -1763,7 +1763,6 @@ TEST_F(TransactionsMetricsTest, SingleTransactionStatsDurationShouldBeSetUponCom
ASSERT_GTE(txnParticipant->getSingleTransactionStats().getDuration(curTimeMicros64()),
timeBeforeTxnCommit - timeAfterTxnStart);
-
ASSERT_LTE(txnParticipant->getSingleTransactionStats().getDuration(curTimeMicros64()),
timeAfterTxnCommit - timeBeforeTxnStart);
}
@@ -1784,7 +1783,6 @@ TEST_F(TransactionsMetricsTest, SingleTransactionStatsDurationShouldBeSetUponAbo
ASSERT_GTE(txnParticipant->getSingleTransactionStats().getDuration(curTimeMicros64()),
timeBeforeTxnAbort - timeAfterTxnStart);
-
ASSERT_LTE(txnParticipant->getSingleTransactionStats().getDuration(curTimeMicros64()),
timeAfterTxnAbort - timeBeforeTxnStart);
}
@@ -2275,13 +2273,11 @@ TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponStash) {
txnParticipant->stashTransactionResources(opCtx());
// LastClientInfo should have been set.
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().clientHostAndPort,
- "");
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().connectionId, 0);
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().appName, "appName");
- ASSERT_BSONOBJ_EQ(
- txnParticipant->getSingleTransactionStats().getLastClientInfo().clientMetadata,
- obj.getField("client").Obj());
+ auto lastClientInfo = txnParticipant->getSingleTransactionStats().getLastClientInfo();
+ ASSERT_EQ(lastClientInfo.clientHostAndPort, "");
+ ASSERT_EQ(lastClientInfo.connectionId, 0);
+ ASSERT_EQ(lastClientInfo.appName, "appName");
+ ASSERT_BSONOBJ_EQ(lastClientInfo.clientMetadata, obj.getField("client").Obj());
// Create another ClientMetadata object.
auto newObj = constructClientMetadata("newAppName");
@@ -2293,11 +2289,9 @@ TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponStash) {
txnParticipant->stashTransactionResources(opCtx());
// LastClientInfo's clientMetadata should have been updated to the new ClientMetadata object.
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().appName,
- "newAppName");
- ASSERT_BSONOBJ_EQ(
- txnParticipant->getSingleTransactionStats().getLastClientInfo().clientMetadata,
- newObj.getField("client").Obj());
+ lastClientInfo = txnParticipant->getSingleTransactionStats().getLastClientInfo();
+ ASSERT_EQ(lastClientInfo.appName, "newAppName");
+ ASSERT_BSONOBJ_EQ(lastClientInfo.clientMetadata, newObj.getField("client").Obj());
}
TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponCommit) {
@@ -2316,13 +2310,11 @@ TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponCommit) {
txnParticipant->commitUnpreparedTransaction(opCtx());
// LastClientInfo should have been set.
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().clientHostAndPort,
- "");
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().connectionId, 0);
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().appName, "appName");
- ASSERT_BSONOBJ_EQ(
- txnParticipant->getSingleTransactionStats().getLastClientInfo().clientMetadata,
- obj.getField("client").Obj());
+ auto lastClientInfo = txnParticipant->getSingleTransactionStats().getLastClientInfo();
+ ASSERT_EQ(lastClientInfo.clientHostAndPort, "");
+ ASSERT_EQ(lastClientInfo.connectionId, 0);
+ ASSERT_EQ(lastClientInfo.appName, "appName");
+ ASSERT_BSONOBJ_EQ(lastClientInfo.clientMetadata, obj.getField("client").Obj());
}
TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponAbort) {
@@ -2340,13 +2332,11 @@ TEST_F(TransactionsMetricsTest, LastClientInfoShouldUpdateUponAbort) {
txnParticipant->abortActiveTransaction(opCtx());
// LastClientInfo should have been set.
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().clientHostAndPort,
- "");
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().connectionId, 0);
- ASSERT_EQ(txnParticipant->getSingleTransactionStats().getLastClientInfo().appName, "appName");
- ASSERT_BSONOBJ_EQ(
- txnParticipant->getSingleTransactionStats().getLastClientInfo().clientMetadata,
- obj.getField("client").Obj());
+ auto lastClientInfo = txnParticipant->getSingleTransactionStats().getLastClientInfo();
+ ASSERT_EQ(lastClientInfo.clientHostAndPort, "");
+ ASSERT_EQ(lastClientInfo.connectionId, 0);
+ ASSERT_EQ(lastClientInfo.appName, "appName");
+ ASSERT_BSONOBJ_EQ(lastClientInfo.clientMetadata, obj.getField("client").Obj());
}
/*