summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoraldo-aguilar <aldo.aguilar@mongodb.com>2021-08-02 23:34:19 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-08-20 02:43:57 +0000
commitbf8178c96766b5509a8b0afe56d548e6b5561456 (patch)
tree9fcd5b2d1d71f927e117b58a49f3e3f87c2db983 /src
parent00f2ee65095bb32c4b4fdaff7a65e83f22695be1 (diff)
downloadmongo-bf8178c96766b5509a8b0afe56d548e6b5561456.tar.gz
SERVER-58848 Using UserAcquisitionStats in place of UserCacheAcquisitionStats, now tracking LDAP operations as well.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript2
-rw-r--r--src/mongo/db/auth/SConscript3
-rw-r--r--src/mongo/db/auth/authorization_manager_impl.cpp8
-rw-r--r--src/mongo/db/auth/ldap_operation_stats.cpp107
-rw-r--r--src/mongo/db/auth/ldap_operation_stats.h166
-rw-r--r--src/mongo/db/auth/user_acquisition_stats.h280
-rw-r--r--src/mongo/db/auth/user_cache_acquisition_stats.h93
-rw-r--r--src/mongo/db/curop.cpp44
-rw-r--r--src/mongo/db/curop.h23
9 files changed, 625 insertions, 101 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 68b9ff7f466..c2e185306b1 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -165,7 +165,7 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'auth/auth',
- 'auth/user_cache_acquisition_stats',
+ 'auth/user_acquisition_stats',
'prepare_conflict_tracker',
'stats/resource_consumption_metrics',
],
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index 217aa97e9fd..cb93c84665b 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -502,8 +502,9 @@ env.Library(
)
env.Library(
- target='user_cache_acquisition_stats',
+ target='user_acquisition_stats',
source=[
+ 'ldap_operation_stats.cpp',
'user_cache_acquisition_stats.cpp'
],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp
index 49a7843e978..5ddc068c1d2 100644
--- a/src/mongo/db/auth/authorization_manager_impl.cpp
+++ b/src/mongo/db/auth/authorization_manager_impl.cpp
@@ -495,15 +495,17 @@ StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* o
// Track wait time and user cache access statistics for the current op for logging. An extra
// second of delay is added via the failpoint for testing.
- auto userCacheAcquisitionStats = CurOp::get(opCtx)->getMutableUserCacheAcquisitionStats(
- opCtx->getClient(), opCtx->getServiceContext()->getTickSource());
+ UserAcquisitionStatsHandle userAcquisitionStatsHandle =
+ UserAcquisitionStatsHandle(CurOp::get(opCtx)->getMutableUserAcquisitionStats(),
+ opCtx->getServiceContext()->getTickSource(),
+ kCache);
if (authUserCacheSleep.shouldFail()) {
sleepsecs(1);
}
auto cachedUser = _userCache.acquire(opCtx, request);
- userCacheAcquisitionStats.recordCacheAccessEnd();
+ userAcquisitionStatsHandle.recordTimerEnd();
invariant(cachedUser);
LOGV2_DEBUG(20226, 1, "Returning user from cache", "user"_attr = userName);
diff --git a/src/mongo/db/auth/ldap_operation_stats.cpp b/src/mongo/db/auth/ldap_operation_stats.cpp
new file mode 100644
index 00000000000..259e88ffec9
--- /dev/null
+++ b/src/mongo/db/auth/ldap_operation_stats.cpp
@@ -0,0 +1,107 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include <cstdint>
+
+#include "mongo/base/error_extra_info.h"
+#include "mongo/db/auth/ldap_operation_stats.h"
+#include "mongo/util/duration.h"
+#include "mongo/util/tick_source.h"
+
+namespace mongo {
+namespace {
+/**
+ * LDAPOperationStats members
+ */
+constexpr auto kNumberOfReferrals = "LDAPNumberOfReferrals"_sd;
+constexpr auto kBindStats = "bindStats"_sd;
+constexpr auto kSearchStats = "searchStats"_sd;
+constexpr auto kUnbindStats = "unbindStats"_sd;
+
+/**
+ * Fields of the Stats struct
+ */
+constexpr auto kLDAPMetricNumOp = "numOp"_sd;
+constexpr auto kLDAPMetricDuration = "opDuration"_sd;
+
+} // namespace
+
+void LDAPOperationStats::report(BSONObjBuilder* builder, TickSource* tickSource) const {
+ builder->append(kNumberOfReferrals, _numReferrals);
+ reportHelper(builder, tickSource, _bindStats, kBindStats);
+ reportHelper(builder, tickSource, _searchStats, kSearchStats);
+ reportHelper(builder, tickSource, _unbindStats, kUnbindStats);
+}
+
+void LDAPOperationStats::reportHelper(BSONObjBuilder* builder,
+ TickSource* tickSource,
+ Stats ldapOpStats,
+ StringData statsName) const {
+ BSONObjBuilder subObjBuildr(builder->subobjStart(statsName));
+ subObjBuildr.append(kLDAPMetricNumOp, ldapOpStats.numOps);
+ subObjBuildr.append(kLDAPMetricDuration,
+ durationCount<Microseconds>(_timeElapsed(tickSource, ldapOpStats)));
+}
+
+void LDAPOperationStats::toString(StringBuilder* sb, TickSource* tickSource) const {
+ *sb << "{" << kNumberOfReferrals << ":" << _numReferrals << ",";
+ toStringHelper(sb, tickSource, _bindStats, kBindStats);
+ toStringHelper(sb, tickSource, _searchStats, kSearchStats);
+ toStringHelper(sb, tickSource, _unbindStats, kUnbindStats);
+ *sb << "}";
+}
+
+void LDAPOperationStats::toStringHelper(StringBuilder* sb,
+ TickSource* tickSource,
+ Stats ldapOpStats,
+ StringData statsName) const {
+ *sb << statsName << "{" << kLDAPMetricNumOp << ":" << ldapOpStats.numOps << ","
+ << kLDAPMetricDuration << ":"
+ << durationCount<Microseconds>(_timeElapsed(tickSource, ldapOpStats)) << "}";
+}
+
+Microseconds LDAPOperationStats::_timeElapsed(TickSource* tickSource, Stats ldapOpStats) const {
+ if (ldapOpStats.startTime == Microseconds{0}) {
+ return Microseconds{0};
+ }
+
+ if (ldapOpStats.endTime <= ldapOpStats.startTime) {
+ return tickSource->ticksTo<Microseconds>(tickSource->getTicks()) - ldapOpStats.startTime;
+ }
+
+ return ldapOpStats.endTime - ldapOpStats.startTime;
+}
+
+bool LDAPOperationStats::shouldReport() const {
+ return _numReferrals != 0 || _bindStats.numOps != 0 || _searchStats.numOps != 0 ||
+ _unbindStats.numOps != 0;
+}
+} // namespace mongo
diff --git a/src/mongo/db/auth/ldap_operation_stats.h b/src/mongo/db/auth/ldap_operation_stats.h
new file mode 100644
index 00000000000..c9a141c6581
--- /dev/null
+++ b/src/mongo/db/auth/ldap_operation_stats.h
@@ -0,0 +1,166 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <iostream>
+#include <memory>
+
+#include "mongo/base/string_data.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/util/duration.h"
+#include "mongo/util/tick_source.h"
+
+namespace mongo {
+/**
+ * Class used to track statistics associated with LDAP operations for a specfic
+ * UserAcquisitionStats object.
+ */
+class LDAPOperationStats {
+public:
+ LDAPOperationStats() = default;
+ ~LDAPOperationStats() = default;
+ LDAPOperationStats(const LDAPOperationStats&) = delete;
+ LDAPOperationStats& operator=(const LDAPOperationStats&) = delete;
+ /**
+ * Marshals all statistics into BSON for reporting.
+ */
+ void report(BSONObjBuilder* builder, TickSource* tickSource) const;
+
+ /**
+ * Marshals all statistics into a string for reporting.
+ */
+ void toString(StringBuilder* sb, TickSource* tickSource) const;
+
+ /**
+ * Checks if any memebers of the LDAPOperationStats object have been updated.
+ */
+ bool shouldReport() const;
+
+ /**
+ * Increment the total number of referrals for an LDAP operation.
+ */
+ void incrementReferrals() {
+ ++_numReferrals;
+ }
+
+ /**
+ * Increment LDAPOperationStats bind, search, and unbind number of operations feild
+ */
+ void incrementBindNumOps() {
+ ++_bindStats.numOps;
+ }
+
+ void incrementSearchNumOps() {
+ ++_searchStats.numOps;
+ }
+
+ void incrementUnbindNumOps() {
+ ++_unbindStats.numOps;
+ }
+
+ /**
+ * Setters for bind, search, and unbind start times
+ */
+ void setBindStatsStartTime(Microseconds startTime) {
+ _bindStats.startTime = startTime;
+ }
+
+ void setSearchStatsStartTime(Microseconds startTime) {
+ _searchStats.startTime = startTime;
+ }
+
+ void setUnbindStatsStartTime(Microseconds startTime) {
+ _unbindStats.startTime = startTime;
+ }
+
+ /**
+ * Setters for bind, search, and unbind end times
+ */
+ void setBindStatsEndTime(Microseconds startTime) {
+ invariant(_bindStats.startTime != Microseconds{0});
+ _bindStats.endTime = startTime;
+ }
+
+ void setSearchStatsEndTime(Microseconds startTime) {
+ invariant(_searchStats.startTime != Microseconds{0});
+ _searchStats.endTime = startTime;
+ }
+
+ void setUnbindStatsEndTime(Microseconds startTime) {
+ invariant(_unbindStats.startTime != Microseconds{0});
+ _unbindStats.endTime = startTime;
+ }
+
+private:
+ /**
+ * Struct Stats is used to contain information about the bind, search, and unbind stats
+ * of the LDAP Operations.
+ */
+ struct Stats {
+ int64_t numOps{0};
+ Microseconds startTime{Microseconds{0}};
+ Microseconds endTime{Microseconds{0}};
+ };
+
+ /**
+ * Helper function to reduce redundancy for constructing BSON report of LDAPOperationsStats.
+ */
+ void reportHelper(BSONObjBuilder* builder,
+ TickSource* tickSource,
+ Stats ldapOpStats,
+ StringData statsName) const;
+
+ /**
+ * Helper function to reduce redundancy for constructing string of LDAPOperationsStats.
+ */
+ void toStringHelper(StringBuilder* sb,
+ TickSource* tickSource,
+ Stats ldapOpStats,
+ StringData statsName) const;
+
+ /**
+ * Computes and returns total time spent on all cache accesses.
+ */
+ Microseconds _timeElapsed(TickSource* tickSource, Stats ldapOpStats) const;
+
+ /**
+ * Number of referrals to other LDAP servers
+ */
+ int64_t _numReferrals{0};
+
+ /**
+ * Metrics associated with binding, search/query, and unbinding from an LDAP server.
+ */
+ Stats _bindStats;
+ Stats _searchStats;
+ Stats _unbindStats;
+};
+} // namespace mongo
diff --git a/src/mongo/db/auth/user_acquisition_stats.h b/src/mongo/db/auth/user_acquisition_stats.h
new file mode 100644
index 00000000000..c79d649c087
--- /dev/null
+++ b/src/mongo/db/auth/user_acquisition_stats.h
@@ -0,0 +1,280 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/auth/ldap_operation_stats.h"
+#include "mongo/db/client.h"
+#include "mongo/platform/mutex.h"
+#include "mongo/util/duration.h"
+#include "mongo/util/tick_source.h"
+#include "user_cache_acquisition_stats.h"
+
+namespace mongo {
+enum UserAcquisitionOpType { kCache, kBind, kSearch, kUnbind, kIncrementReferrals };
+
+/**
+ * Generalized wrapper class for CurOp. Has access to the `UserCacheAcquisitionStats` class and to
+ * `LDAPOperationStats` class. This allows CurOp to have encapsulated information about LDAP
+ * specific metrics and existing user cache metrics.
+ */
+class UserAcquisitionStats {
+ /**
+ * The RAII handle has access to private members of UserAcquisitionStats but only exposes
+ * methods for recording start times, end times of LDAP Operations or User Cache operations.
+ * And a method to increment the referral count of an LDAP operation.
+ */
+ friend class UserAcquisitionStatsHandle;
+
+public:
+ UserAcquisitionStats()
+ : _userCacheAcquisitionStats(UserCacheAcquisitionStats()),
+ _ldapOperationStats(LDAPOperationStats()){};
+ ~UserAcquisitionStats() = default;
+
+ /**
+ * Functions for determining if there is data to report in the userCacheAcquisitionStats or
+ * LDAPOperationStats object
+ */
+ bool shouldUserCacheAcquisitionStatsReport() const {
+ return _userCacheAcquisitionStats.shouldReport();
+ }
+
+ bool shouldLDAPOperationStatsReport() const {
+ return _ldapOperationStats.shouldReport();
+ }
+
+ /**
+ * Read only serialization methods for UserCacheAcquisitionStats object. Methods will serialize
+ * to string and to BSON. Used for reporting to $currentOp, database profiling, and logging.
+ */
+ void userCacheAcquisitionStatsReport(BSONObjBuilder* builder, TickSource* tickSource) const {
+ _userCacheAcquisitionStats.report(builder, tickSource);
+ }
+
+ void userCacheAcquisitionStatsToString(StringBuilder* sb, TickSource* tickSource) const {
+ _userCacheAcquisitionStats.toString(sb, tickSource);
+ }
+
+ /**
+ * Read only serialization methods for LDAPOperationStats object. Methods will serialize
+ * to string and to BSON. Used for reporting to $currentOp, database profiling, and logging.
+ */
+ void ldapOperationStatsReport(BSONObjBuilder* builder, TickSource* tickSource) const {
+ _ldapOperationStats.report(builder, tickSource);
+ }
+
+ void ldapOperationStatsToString(StringBuilder* sb, TickSource* tickSource) const {
+ _ldapOperationStats.toString(sb, tickSource);
+ }
+
+
+private:
+ /**
+ * Records the start time of an LDAP bind operation
+ */
+ void _recordBindStart(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setBindStatsStartTime(_getTime(tickSource));
+ _ldapOperationStats.incrementBindNumOps();
+ }
+
+ /**
+ * Records the completion of a LDAP bind operation by setting the end time. The start time
+ * must already be set.
+ */
+ void _recordBindEnd(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setBindStatsEndTime(_getTime(tickSource));
+ }
+
+ /**
+ * Records the start time of an LDAP search/query operation
+ */
+ void _recordSearchStart(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setSearchStatsStartTime(
+ tickSource->ticksTo<Microseconds>(tickSource->getTicks()));
+ _ldapOperationStats.incrementSearchNumOps();
+ }
+
+ /**
+ * Records the completion of a LDAP search/query operation by setting the end time. The start
+ *time must already be set.
+ */
+ void _recordSearchEnd(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setSearchStatsEndTime(_getTime(tickSource));
+ }
+
+ /**
+ * Records the start time of an LDAP unbind operation
+ */
+ void _recordUnbindStart(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setUnbindStatsStartTime(_getTime(tickSource));
+ _ldapOperationStats.incrementUnbindNumOps();
+ }
+
+ /**
+ * Records the completion of a LDAP unbind operation by setting the end time. The start time
+ * must already be set.
+ */
+ void _recordUnbindEnd(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _ldapOperationStats.setUnbindStatsEndTime(_getTime(tickSource));
+ }
+
+ /**
+ * Increments the number of referrals to another LDAP server, by increasing the numReferrals
+ * feild of the LDAPOperationStats object
+ */
+ void _incrementReferrals() {
+ _ldapOperationStats.incrementReferrals();
+ }
+
+ /**
+ * Records the start time of a new cache access attempt.
+ */
+ void _recordCacheAccessStart(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _userCacheAcquisitionStats.setCacheAccessStartTime(_getTime(tickSource));
+ _userCacheAcquisitionStats.incrementAcquisitionAttempts();
+ }
+
+ /**
+ * Records the completion of a cache access attempt by setting the end time. The start time must
+ * already be set.
+ */
+ void _recordCacheAccessEnd(TickSource* tickSource) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _userCacheAcquisitionStats.setCacheAccessEndTime(_getTime(tickSource));
+ _userCacheAcquisitionStats.incrementAcquisitionCompletions();
+ }
+
+ /**
+ * Helper function to get the time from a TickSouce and convert it to Microseconds.
+ */
+ Microseconds _getTime(TickSource* tickSource) {
+ return tickSource->ticksTo<Microseconds>(tickSource->getTicks());
+ }
+
+ /**
+ * UserCacheAcquisitionStats and LDAPOperationStats
+ * associated with this UserAcquisitionStats object.
+ */
+ UserCacheAcquisitionStats _userCacheAcquisitionStats;
+ LDAPOperationStats _ldapOperationStats;
+
+ Mutex _mutex = MONGO_MAKE_LATCH("UserAcquisitionStats::_mutex");
+};
+
+/**
+ * RAII handle that is used to mutate a UserAcquisitionStats object. It automatically records
+ * the start time of either an LDAP or User Cache Acquisition operation upon construction.
+ * Additionally, it guarantees that an ongoing user attempt will be recorded as complete as
+ * soon as the handle goes out of scope. This ensures that a call to the corresponding
+ * operations set end timer will be called even if an exception is thrown.
+ */
+class UserAcquisitionStatsHandle {
+public:
+ UserAcquisitionStatsHandle() = delete;
+
+ UserAcquisitionStatsHandle(UserAcquisitionStats* statsParam,
+ TickSource* tickSource,
+ UserAcquisitionOpType type)
+ : _stats(statsParam), _tickSource(tickSource), _type(type) {
+ switch (_type) {
+ case kCache:
+ _stats->_recordCacheAccessStart(_tickSource);
+ break;
+ case kBind:
+ _stats->_recordBindStart(_tickSource);
+ break;
+ case kSearch:
+ _stats->_recordSearchStart(_tickSource);
+ break;
+ case kUnbind:
+ _stats->_recordUnbindStart(_tickSource);
+ break;
+ case kIncrementReferrals:
+ break;
+ }
+ }
+
+ UserAcquisitionStatsHandle(const UserAcquisitionStatsHandle&) = delete;
+
+ UserAcquisitionStatsHandle& operator=(const UserAcquisitionStatsHandle&) = delete;
+
+ UserAcquisitionStatsHandle(UserAcquisitionStatsHandle&& handle)
+ : _stats(std::exchange(handle._stats, nullptr)),
+ _tickSource(std::move(handle._tickSource)) {}
+
+ UserAcquisitionStatsHandle& operator=(UserAcquisitionStatsHandle&& handle) {
+ _stats = std::exchange(handle._stats, nullptr);
+ _tickSource = std::move(handle._tickSource);
+ return *this;
+ }
+
+ ~UserAcquisitionStatsHandle() {
+ recordTimerEnd();
+ }
+
+ void recordTimerEnd() {
+ if (_stats) {
+ switch (_type) {
+ case kCache:
+ _stats->_recordCacheAccessEnd(_tickSource);
+ break;
+ case kBind:
+ _stats->_recordBindEnd(_tickSource);
+ break;
+ case kSearch:
+ _stats->_recordSearchEnd(_tickSource);
+ break;
+ case kUnbind:
+ _stats->_recordUnbindEnd(_tickSource);
+ break;
+ case kIncrementReferrals:
+ _stats->_incrementReferrals();
+ break;
+ }
+ }
+ _stats = nullptr;
+ }
+
+private:
+ UserAcquisitionStats* _stats;
+ TickSource* _tickSource;
+ UserAcquisitionOpType _type;
+};
+} // namespace mongo
diff --git a/src/mongo/db/auth/user_cache_acquisition_stats.h b/src/mongo/db/auth/user_cache_acquisition_stats.h
index 75f24b2a747..c7323de8659 100644
--- a/src/mongo/db/auth/user_cache_acquisition_stats.h
+++ b/src/mongo/db/auth/user_cache_acquisition_stats.h
@@ -44,12 +44,6 @@ namespace mongo {
class UserCacheAcquisitionStats {
using AccessInterval = std::pair<Microseconds, Microseconds>;
- /*
- * The RAII handle has access to private members of UserCacheAcquisitionStats but only exposes
- * _recordCacheAccessStart() and _recordCacheAccessEnd().
- */
- friend class UserCacheAcquisitionStatsHandle;
-
public:
UserCacheAcquisitionStats() = default;
~UserCacheAcquisitionStats() = default;
@@ -74,28 +68,35 @@ public:
*/
void toString(StringBuilder* sb, TickSource* tickSource) const;
-private:
/**
- * Records the start time of a new cache access attempt.
- */
- void _recordCacheAccessStart(Client* client, TickSource* tickSource) {
- stdx::lock_guard<Client> lk(*client);
- _cacheAccessStartTime = tickSource->ticksTo<Microseconds>(tickSource->getTicks());
+ * Increments the number of cache acquisition attempts.
+ **/
+ void incrementAcquisitionAttempts() {
++_totalStartedAcquisitionAttempts;
}
/**
- * Records the completion of a cache access attempt by setting the end time. The start time must
- * already be set.
- */
- void _recordCacheAccessEnd(Client* client, TickSource* tickSource) {
- stdx::lock_guard<Client> lk(*client);
- invariant(_cacheAccessStartTime != Microseconds{0});
- _cacheAccessEndTime = tickSource->ticksTo<Microseconds>(tickSource->getTicks());
+ * Increments the number of cache acquisition attempts.
+ **/
+ void incrementAcquisitionCompletions() {
++_totalCompletedAcquisitionAttempts;
}
/**
+ * Setters for the Cache Access start and end time.
+ **/
+
+ void setCacheAccessStartTime(Microseconds startTime) {
+ _cacheAccessStartTime = startTime;
+ }
+
+ void setCacheAccessEndTime(Microseconds endTime) {
+ invariant(_cacheAccessStartTime != Microseconds{0});
+ _cacheAccessEndTime = endTime;
+ }
+
+private:
+ /**
* Computes and returns total time spent on all cache accesses.
*/
Microseconds _timeElapsed(TickSource* tickSource) const;
@@ -110,6 +111,7 @@ private:
*/
std::uint64_t _totalCompletedAcquisitionAttempts{0};
+
/**
* Start and end times of user cache access. If the access is still
* pending, then the end time will be 0.
@@ -117,57 +119,4 @@ private:
Microseconds _cacheAccessStartTime{Microseconds{0}};
Microseconds _cacheAccessEndTime{Microseconds{0}};
};
-
-/**
- * RAII handle that is used to mutate a UserCacheAcquisitionStats object. It automatically records
- * the start of a cache access attempt upon construction and provides access to
- * UserCacheAcquisitionStats::recordCacheAccessEnd(). Additionally, it guarantees that an ongoing
- * user cache attempt will be recorded as complete as soon as the handle goes out of scope. This
- * ensures that UserCacheAcquisitionStats::recordCacheAccessEnd() will be called even if an
- * exception is thrown.
- */
-class UserCacheAcquisitionStatsHandle {
-public:
- UserCacheAcquisitionStatsHandle() = delete;
-
- UserCacheAcquisitionStatsHandle(UserCacheAcquisitionStats* statsParam,
- Client* client,
- TickSource* tickSource)
- : _stats(statsParam), _client(client), _tickSource(tickSource) {
- _stats->_recordCacheAccessStart(_client, _tickSource);
- }
-
- UserCacheAcquisitionStatsHandle(const UserCacheAcquisitionStatsHandle&) = delete;
- UserCacheAcquisitionStatsHandle& operator=(const UserCacheAcquisitionStatsHandle&) = delete;
-
- UserCacheAcquisitionStatsHandle(UserCacheAcquisitionStatsHandle&& handle)
- : _stats(std::exchange(handle._stats, nullptr)),
- _client(std::move(handle._client)),
- _tickSource(std::move(handle._tickSource)) {}
-
- UserCacheAcquisitionStatsHandle& operator=(UserCacheAcquisitionStatsHandle&& handle) {
- _stats = std::exchange(handle._stats, nullptr);
- _client = std::move(handle._client);
- _tickSource = std::move(handle._tickSource);
-
- return *this;
- }
-
- ~UserCacheAcquisitionStatsHandle() {
- recordCacheAccessEnd();
- }
-
- void recordCacheAccessEnd() {
- if (_stats) {
- _stats->_recordCacheAccessEnd(_client, _tickSource);
- }
- _stats = nullptr;
- }
-
-private:
- UserCacheAcquisitionStats* _stats;
- Client* _client;
- TickSource* _tickSource;
-};
-
} // namespace mongo
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp
index b9e7ce060fe..24442c70f6d 100644
--- a/src/mongo/db/curop.cpp
+++ b/src/mongo/db/curop.cpp
@@ -881,14 +881,21 @@ void OpDebug::report(OperationContext* opCtx,
pAttrs->add("locks", locks.obj());
}
- auto userCacheAcquisitionStats = curop.getReadOnlyUserCacheAcquisitionStats();
- if (userCacheAcquisitionStats->shouldReport()) {
+ auto userAcquisitionStats = curop.getReadOnlyUserAcquisitionStats();
+ if (userAcquisitionStats->shouldUserCacheAcquisitionStatsReport()) {
BSONObjBuilder userCacheAcquisitionStatsBuilder;
- userCacheAcquisitionStats->report(&userCacheAcquisitionStatsBuilder,
- opCtx->getServiceContext()->getTickSource());
+ userAcquisitionStats->userCacheAcquisitionStatsReport(
+ &userCacheAcquisitionStatsBuilder, opCtx->getServiceContext()->getTickSource());
pAttrs->add("authorization", userCacheAcquisitionStatsBuilder.obj());
}
+ if (userAcquisitionStats->shouldLDAPOperationStatsReport()) {
+ BSONObjBuilder ldapOperationStatsBuilder;
+ userAcquisitionStats->ldapOperationStatsReport(&ldapOperationStatsBuilder,
+ opCtx->getServiceContext()->getTickSource());
+ pAttrs->add("LDAPOperations", ldapOperationStatsBuilder.obj());
+ }
+
BSONObj flowControlObj = makeFlowControlObject(flowControlStats);
if (flowControlObj.nFields() > 0) {
pAttrs->add("flowControl", flowControlObj);
@@ -1018,11 +1025,17 @@ void OpDebug::append(OperationContext* opCtx,
}
{
- auto userCacheAcquisitionStats = curop.getReadOnlyUserCacheAcquisitionStats();
- if (userCacheAcquisitionStats->shouldReport()) {
+ auto userAcquisitionStats = curop.getReadOnlyUserAcquisitionStats();
+ if (userAcquisitionStats->shouldUserCacheAcquisitionStatsReport()) {
BSONObjBuilder userCacheAcquisitionStatsBuilder(b.subobjStart("authorization"));
- userCacheAcquisitionStats->report(&userCacheAcquisitionStatsBuilder,
- opCtx->getServiceContext()->getTickSource());
+ userAcquisitionStats->userCacheAcquisitionStatsReport(
+ &userCacheAcquisitionStatsBuilder, opCtx->getServiceContext()->getTickSource());
+ }
+
+ if (userAcquisitionStats->shouldLDAPOperationStatsReport()) {
+ BSONObjBuilder ldapOperationStatsBuilder;
+ userAcquisitionStats->ldapOperationStatsReport(
+ &ldapOperationStatsBuilder, opCtx->getServiceContext()->getTickSource());
}
}
@@ -1285,11 +1298,18 @@ std::function<BSONObj(ProfileFilter::Args)> OpDebug::appendStaged(StringSet requ
});
addIfNeeded("authorization", [](auto field, auto args, auto& b) {
- auto userCacheAcquisitionStats = args.curop.getReadOnlyUserCacheAcquisitionStats();
- if (userCacheAcquisitionStats->shouldReport()) {
+ auto userAcquisitionStats = args.curop.getReadOnlyUserAcquisitionStats();
+ if (userAcquisitionStats->shouldUserCacheAcquisitionStatsReport()) {
BSONObjBuilder userCacheAcquisitionStatsBuilder(b.subobjStart(field));
- userCacheAcquisitionStats->report(&userCacheAcquisitionStatsBuilder,
- args.opCtx->getServiceContext()->getTickSource());
+ userAcquisitionStats->userCacheAcquisitionStatsReport(
+ &userCacheAcquisitionStatsBuilder,
+ args.opCtx->getServiceContext()->getTickSource());
+ }
+
+ if (userAcquisitionStats->shouldLDAPOperationStatsReport()) {
+ BSONObjBuilder ldapOperationStatsBuilder(b.subobjStart(field));
+ userAcquisitionStats->ldapOperationStatsReport(
+ &ldapOperationStatsBuilder, args.opCtx->getServiceContext()->getTickSource());
}
});
diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h
index afb48de2440..621106e3e0d 100644
--- a/src/mongo/db/curop.h
+++ b/src/mongo/db/curop.h
@@ -30,9 +30,11 @@
#pragma once
+#include <memory>
+
#include "mongo/config.h"
#include "mongo/db/auth/authorization_session.h"
-#include "mongo/db/auth/user_cache_acquisition_stats.h"
+#include "mongo/db/auth/user_acquisition_stats.h"
#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
@@ -46,6 +48,7 @@
#include "mongo/logv2/log_component.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/util/progress_meter.h"
+#include "mongo/util/tick_source.h"
#include "mongo/util/time_support.h"
#ifndef MONGO_CONFIG_USE_RAW_LATCHES
@@ -435,22 +438,18 @@ public:
}
/**
- * Returns a const pointer to the authorization user cache statistics for the current operation.
+ * Returns a const pointer to the UserAcquisitionStats for the current operation.
* This can only be used for reading (i.e., when logging or profiling).
*/
- const UserCacheAcquisitionStats* getReadOnlyUserCacheAcquisitionStats() const {
- return &_userCacheAcquisitionStats;
+ const UserAcquisitionStats* getReadOnlyUserAcquisitionStats() const {
+ return &_userAcquisitionStats;
}
/**
- * Returns an instance of UserCacheAcquisitionStatsHandle. By doing so, it automatically records
- * the start of the user cache access attempt upon creation. If the cache access is not
- * completed and recorded normally before it is about to be destroyed (i.e., due to an
- * exception), it will be automatically recorded as complete then.
+ * Returns a non-const raw pointers to UserAcquisitionStats member.
*/
- UserCacheAcquisitionStatsHandle getMutableUserCacheAcquisitionStats(Client* client,
- TickSource* tickSource) {
- return UserCacheAcquisitionStatsHandle(&_userCacheAcquisitionStats, client, tickSource);
+ UserAcquisitionStats* getMutableUserAcquisitionStats() {
+ return &_userAcquisitionStats;
}
/**
@@ -852,7 +851,7 @@ private:
boost::optional<SingleThreadedLockStats>
_lockStatsBase; // This is the snapshot of lock stats taken when curOp is constructed.
- UserCacheAcquisitionStats _userCacheAcquisitionStats;
+ UserAcquisitionStats _userAcquisitionStats;
TickSource* _tickSource = nullptr;
};