diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/auth/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager_impl.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/auth/ldap_operation_stats.cpp | 107 | ||||
-rw-r--r-- | src/mongo/db/auth/ldap_operation_stats.h | 166 | ||||
-rw-r--r-- | src/mongo/db/auth/user_acquisition_stats.h | 280 | ||||
-rw-r--r-- | src/mongo/db/auth/user_cache_acquisition_stats.h | 93 | ||||
-rw-r--r-- | src/mongo/db/curop.cpp | 44 | ||||
-rw-r--r-- | src/mongo/db/curop.h | 23 |
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; }; |