summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2019-11-01 22:00:41 +0000
committerevergreen <evergreen@mongodb.com>2019-11-01 22:00:41 +0000
commit7692bc0ed90792bd74d45fd8a1070baecdc4f9eb (patch)
treecac01e72f5164ec9619db4bc1f13841445edfaeb /src/mongo
parente5340534df81238e454ce7d3afbb7883115f2c53 (diff)
downloadmongo-7692bc0ed90792bd74d45fd8a1070baecdc4f9eb.tar.gz
SERVER-40372 Track transaction size
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/server_transactions_metrics.cpp17
-rw-r--r--src/mongo/db/server_transactions_metrics.h10
-rw-r--r--src/mongo/db/transaction_metrics_observer.cpp12
-rw-r--r--src/mongo/db/transaction_metrics_observer.h7
-rw-r--r--src/mongo/db/transaction_participant.cpp19
-rw-r--r--src/mongo/db/transaction_participant.h4
-rw-r--r--src/mongo/db/transactions_stats.idl17
-rw-r--r--src/mongo/shell/session.js34
8 files changed, 100 insertions, 20 deletions
diff --git a/src/mongo/db/server_transactions_metrics.cpp b/src/mongo/db/server_transactions_metrics.cpp
index 1daa320782d..a51ecc0345c 100644
--- a/src/mongo/db/server_transactions_metrics.cpp
+++ b/src/mongo/db/server_transactions_metrics.cpp
@@ -149,6 +149,18 @@ void ServerTransactionsMetrics::decrementCurrentPrepared() {
_currentPrepared.fetchAndSubtract(1);
}
+void ServerTransactionsMetrics::updateLastTransaction(size_t operationCount,
+ size_t oplogOperationBytes,
+ BSONObj writeConcern) {
+ stdx::lock_guard<Latch> lg(_mutex);
+ if (!_lastCommittedTransaction) {
+ _lastCommittedTransaction = LastCommittedTransaction();
+ }
+ _lastCommittedTransaction->setOperationCount(operationCount);
+ _lastCommittedTransaction->setOplogOperationBytes(oplogOperationBytes);
+ _lastCommittedTransaction->setWriteConcern(std::move(writeConcern));
+}
+
void ServerTransactionsMetrics::updateStats(TransactionsStats* stats) {
stats->setCurrentActive(_currentActive.load());
stats->setCurrentInactive(_currentInactive.load());
@@ -160,6 +172,11 @@ void ServerTransactionsMetrics::updateStats(TransactionsStats* stats) {
stats->setTotalPreparedThenCommitted(_totalPreparedThenCommitted.load());
stats->setTotalPreparedThenAborted(_totalPreparedThenAborted.load());
stats->setCurrentPrepared(_currentPrepared.load());
+
+ stdx::lock_guard<Latch> lg(_mutex);
+ if (_lastCommittedTransaction) {
+ stats->setLastCommittedTransaction(*_lastCommittedTransaction);
+ }
}
namespace {
diff --git a/src/mongo/db/server_transactions_metrics.h b/src/mongo/db/server_transactions_metrics.h
index 250b2c41931..78523e5fa36 100644
--- a/src/mongo/db/server_transactions_metrics.h
+++ b/src/mongo/db/server_transactions_metrics.h
@@ -36,6 +36,7 @@
#include "mongo/db/repl/optime.h"
#include "mongo/db/service_context.h"
#include "mongo/db/transactions_stats_gen.h"
+#include "mongo/platform/mutex.h"
#include "mongo/util/concurrency/with_lock.h"
namespace mongo {
@@ -87,6 +88,10 @@ public:
void incrementCurrentPrepared();
void decrementCurrentPrepared();
+ void updateLastTransaction(size_t operationCount,
+ size_t oplogOperationBytes,
+ BSONObj writeConcern);
+
/**
* Appends the accumulated stats to a transactions stats object.
*/
@@ -122,6 +127,11 @@ private:
// The current number of transactions in the prepared state.
AtomicWord<unsigned long long> _currentPrepared{0};
+
+ // Protects member variables below.
+ mutable Mutex _mutex = MONGO_MAKE_LATCH("ServerTransactionsMetrics::_mutex");
+
+ boost::optional<LastCommittedTransaction> _lastCommittedTransaction;
};
} // namespace mongo
diff --git a/src/mongo/db/transaction_metrics_observer.cpp b/src/mongo/db/transaction_metrics_observer.cpp
index e1b36d971bd..24bc70d6dea 100644
--- a/src/mongo/db/transaction_metrics_observer.cpp
+++ b/src/mongo/db/transaction_metrics_observer.cpp
@@ -92,9 +92,12 @@ void TransactionMetricsObserver::onUnstash(ServerTransactionsMetrics* serverTran
serverTransactionsMetrics->decrementCurrentInactive();
}
-void TransactionMetricsObserver::onCommit(ServerTransactionsMetrics* serverTransactionsMetrics,
+void TransactionMetricsObserver::onCommit(OperationContext* opCtx,
+ ServerTransactionsMetrics* serverTransactionsMetrics,
TickSource* tickSource,
- Top* top) {
+ Top* top,
+ size_t operationCount,
+ size_t oplogOperationBytes) {
//
// Per transaction metrics.
//
@@ -118,6 +121,11 @@ void TransactionMetricsObserver::onCommit(ServerTransactionsMetrics* serverTrans
serverTransactionsMetrics->decrementCurrentPrepared();
}
+ serverTransactionsMetrics->updateLastTransaction(
+ operationCount,
+ oplogOperationBytes,
+ opCtx->getWriteConcern().usedDefault ? BSONObj() : opCtx->getWriteConcern().toBSON());
+
auto duration =
durationCount<Microseconds>(_singleTransactionStats.getDuration(tickSource, curTick));
top->incrementGlobalTransactionLatencyStats(static_cast<uint64_t>(duration));
diff --git a/src/mongo/db/transaction_metrics_observer.h b/src/mongo/db/transaction_metrics_observer.h
index 634792198c0..c985beb7af0 100644
--- a/src/mongo/db/transaction_metrics_observer.h
+++ b/src/mongo/db/transaction_metrics_observer.h
@@ -70,9 +70,12 @@ public:
/**
* Updates relevant metrics when a transaction commits.
*/
- void onCommit(ServerTransactionsMetrics* serverTransactionsMetrics,
+ void onCommit(OperationContext* opCtx,
+ ServerTransactionsMetrics* serverTransactionsMetrics,
TickSource* tickSource,
- Top* top);
+ Top* top,
+ size_t operationCount,
+ size_t oplogOperationBytes);
/**
* Updates relevant metrics when a transaction aborts.
diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp
index 65613550dc8..01d378e2d88 100644
--- a/src/mongo/db/transaction_participant.cpp
+++ b/src/mongo/db/transaction_participant.cpp
@@ -1239,13 +1239,15 @@ void TransactionParticipant::Participant::commitUnpreparedTransaction(OperationC
auto wc = opCtx->getWriteConcern();
auto needsNoopWrite = txnOps.empty() && !opCtx->getWriteConcern().usedDefault;
+ const size_t operationCount = p().transactionOperations.size();
+ const size_t oplogOperationBytes = p().transactionOperationBytes;
clearOperationsInMemory(opCtx);
try {
// Once committing we cannot throw an exception.
UninterruptibleLockGuard noInterrupt(opCtx->lockState());
_commitStorageTransaction(opCtx);
- _finishCommitTransaction(opCtx);
+ _finishCommitTransaction(opCtx, operationCount, oplogOperationBytes);
} catch (...) {
// It is illegal for committing a transaction to fail for any reason, other than an
// invalid command, so we crash instead.
@@ -1367,9 +1369,11 @@ void TransactionParticipant::Participant::commitPreparedTransaction(
opObserver->onPreparedTransactionCommit(
opCtx, commitOplogSlot, commitTimestamp, retrieveCompletedTransactionOperations(opCtx));
+ const size_t operationCount = p().transactionOperations.size();
+ const size_t oplogOperationBytes = p().transactionOperationBytes;
clearOperationsInMemory(opCtx);
- _finishCommitTransaction(opCtx);
+ _finishCommitTransaction(opCtx, operationCount, oplogOperationBytes);
} catch (...) {
// It is illegal for committing a prepared transaction to fail for any reason, other than an
// invalid command, so we crash instead.
@@ -1400,15 +1404,20 @@ void TransactionParticipant::Participant::_commitStorageTransaction(OperationCon
std::terminate();
}
-void TransactionParticipant::Participant::_finishCommitTransaction(OperationContext* opCtx) {
+void TransactionParticipant::Participant::_finishCommitTransaction(OperationContext* opCtx,
+ size_t operationCount,
+ size_t oplogOperationBytes) {
{
auto tickSource = opCtx->getServiceContext()->getTickSource();
stdx::lock_guard<Client> lk(*opCtx->getClient());
o(lk).txnState.transitionTo(TransactionState::kCommitted);
- o(lk).transactionMetricsObserver.onCommit(ServerTransactionsMetrics::get(opCtx),
+ o(lk).transactionMetricsObserver.onCommit(opCtx,
+ ServerTransactionsMetrics::get(opCtx),
tickSource,
- &Top::get(getGlobalServiceContext()));
+ &Top::get(getGlobalServiceContext()),
+ operationCount,
+ oplogOperationBytes);
o(lk).transactionMetricsObserver.onTransactionOperation(
opCtx, CurOp::get(opCtx)->debug().additiveMetrics, o().txnState.isPrepared());
}
diff --git a/src/mongo/db/transaction_participant.h b/src/mongo/db/transaction_participant.h
index ccad3a30085..a2dece48562 100644
--- a/src/mongo/db/transaction_participant.h
+++ b/src/mongo/db/transaction_participant.h
@@ -642,7 +642,9 @@ public:
// Finishes committing the multi-document transaction after the storage-transaction has been
// committed, the oplog entry has been inserted into the oplog, and the transactions table
// has been updated.
- void _finishCommitTransaction(OperationContext* opCtx);
+ void _finishCommitTransaction(OperationContext* opCtx,
+ size_t operationCount,
+ size_t oplogOperationBytes);
// Commits the storage-transaction on the OperationContext.
//
diff --git a/src/mongo/db/transactions_stats.idl b/src/mongo/db/transactions_stats.idl
index c2a269d4a79..eb55df77a74 100644
--- a/src/mongo/db/transactions_stats.idl
+++ b/src/mongo/db/transactions_stats.idl
@@ -39,6 +39,20 @@ imports:
structs:
+ LastCommittedTransaction:
+ description: "A struct representing the server status subsection on
+ the last committed transaction"
+ strict: true
+ fields:
+ operationCount:
+ type: long
+ default: 0
+ oplogOperationBytes:
+ type: long
+ default: 0
+ writeConcern:
+ type: object
+
TransactionsStats:
description: "A struct representing the section of the server status
command with information about transactions"
@@ -83,3 +97,6 @@ structs:
currentPrepared:
type: long
default: 0
+ lastCommittedTransaction:
+ type: LastCommittedTransaction
+ optional: true
diff --git a/src/mongo/shell/session.js b/src/mongo/shell/session.js
index 0f6eb11323a..4be01d2895e 100644
--- a/src/mongo/shell/session.js
+++ b/src/mongo/shell/session.js
@@ -718,6 +718,20 @@ var {
return endTransaction("abortTransaction", driverSession);
};
+ this.getTxnWriteConcern = function getTxnWriteConcern(driverSession) {
+ // If a writeConcern is not specified from the default transaction options, it will be
+ // inherited from the session.
+ let writeConcern = undefined;
+ const sessionAwareClient = driverSession._getSessionAwareClient();
+ if (sessionAwareClient.getWriteConcern(driverSession) !== undefined) {
+ writeConcern = sessionAwareClient.getWriteConcern(driverSession);
+ }
+ if (_txnOptions.getTxnWriteConcern() !== undefined) {
+ writeConcern = _txnOptions.getTxnWriteConcern();
+ }
+ return writeConcern;
+ };
+
const endTransaction = (commandName, driverSession) => {
// If commitTransaction or abortTransaction is the first statement in a
// transaction, it should not send a command to the server and should mark the
@@ -732,22 +746,18 @@ var {
}
let cmd = {[commandName]: 1, txnNumber: this.handle.getTxnNumber()};
- // writeConcern should only be specified on commit or abort. If a writeConcern is
- // not specified from the default transaction options, it will be inherited from
- // the session.
- const sessionAwareClient = driverSession._getSessionAwareClient();
- if (sessionAwareClient.getWriteConcern(driverSession) !== undefined) {
- cmd.writeConcern = sessionAwareClient.getWriteConcern(driverSession);
- }
- if (_txnOptions.getTxnWriteConcern() !== undefined) {
- cmd.writeConcern = _txnOptions.getTxnWriteConcern();
+ // writeConcern should only be specified on commit or abort.
+ const writeConcern = driverSession._serverSession.getTxnWriteConcern(driverSession);
+ if (writeConcern !== undefined) {
+ cmd.writeConcern = writeConcern;
}
// If commit or abort raises an error, the transaction's state should still change.
let res;
try {
// run command against the admin database.
- res = sessionAwareClient.runCommand(driverSession, "admin", cmd, 0);
+ res = driverSession._getSessionAwareClient().runCommand(
+ driverSession, "admin", cmd, 0);
} finally {
if (commandName === "commitTransaction") {
setTxnState("committed");
@@ -874,6 +884,10 @@ var {
return this._serverSession.getTxnNumber();
};
+ this.getTxnWriteConcern_forTesting = function getTxnWriteConcern_forTesting() {
+ return this._serverSession.getTxnWriteConcern(this);
+ };
+
this.setTxnNumber_forTesting = function setTxnNumber_forTesting(newTxnNumber) {
this._serverSession.setTxnNumber_forTesting(newTxnNumber);
};