diff options
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/transaction_metrics_observer.cpp | 171 | ||||
-rw-r--r-- | src/mongo/db/transaction_metrics_observer.h | 112 | ||||
-rw-r--r-- | src/mongo/db/transaction_participant.cpp | 142 | ||||
-rw-r--r-- | src/mongo/db/transaction_participant.h | 9 | ||||
-rw-r--r-- | src/mongo/db/transaction_participant_test.cpp | 414 |
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()); } /* |