diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2020-04-21 22:15:22 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-02 00:16:28 +0000 |
commit | 9cf5e9a0ecd0f0472705cc3477d3abfa7f3f35b7 (patch) | |
tree | 0201fd11a96602e03b1ef5818f49e6ba0315e6fa | |
parent | dd087ddf84d5137a09e8c7ac987f01c0ea67bac8 (diff) | |
download | mongo-9cf5e9a0ecd0f0472705cc3477d3abfa7f3f35b7.tar.gz |
SERVER-47697 Remove logging/log_test.cc and support files.
- LogComponent aliased
- LogSeverity aliased
- LogComponentSettings testing
- all relevant tests moved to logv2.
- bye bye log_test.cpp!
(cherry picked from commit 7b1053b738c3c6b0c634e39bf8f70a66fffc1ee0)
-rw-r--r-- | src/mongo/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/logger/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/logger/log_component.cpp | 258 | ||||
-rw-r--r-- | src/mongo/logger/log_component.h | 95 | ||||
-rw-r--r-- | src/mongo/logger/log_component_settings.cpp | 121 | ||||
-rw-r--r-- | src/mongo/logger/log_component_settings.h | 77 | ||||
-rw-r--r-- | src/mongo/logger/log_component_settings_test.cpp | 92 | ||||
-rw-r--r-- | src/mongo/logger/log_function_test.cpp | 131 | ||||
-rw-r--r-- | src/mongo/logger/log_severity.cpp | 101 | ||||
-rw-r--r-- | src/mongo/logger/log_severity.h | 174 | ||||
-rw-r--r-- | src/mongo/logger/log_test.cpp | 482 | ||||
-rw-r--r-- | src/mongo/logger/log_test.h | 143 | ||||
-rw-r--r-- | src/mongo/logger/log_test_util.h | 190 | ||||
-rw-r--r-- | src/mongo/logv2/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/logv2/log_component.h | 11 | ||||
-rw-r--r-- | src/mongo/logv2/log_component_settings.h | 11 | ||||
-rw-r--r-- | src/mongo/logv2/log_severity.h | 5 | ||||
-rw-r--r-- | src/mongo/logv2/logv2_component_test.cpp | 216 | ||||
-rw-r--r-- | src/mongo/logv2/logv2_test.cpp | 16 |
19 files changed, 239 insertions, 1891 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 843819bf072..035b00d7526 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -97,10 +97,7 @@ baseEnv.Library( 'bson/timestamp.cpp', 'logger/component_message_log_domain.cpp', 'logger/console.cpp', - 'logger/log_component.cpp', - 'logger/log_component_settings.cpp', 'logger/log_manager.cpp', - 'logger/log_severity.cpp', 'logger/logger.cpp', 'logger/logstream_builder.cpp', 'logger/message_event_utf8_encoder.cpp', diff --git a/src/mongo/logger/SConscript b/src/mongo/logger/SConscript index 8b51bc99d3a..91e950f2f1c 100644 --- a/src/mongo/logger/SConscript +++ b/src/mongo/logger/SConscript @@ -22,9 +22,6 @@ env.Program( env.CppUnitTest( target='logger_test', source=[ - 'log_component_settings_test.cpp', - 'log_function_test.cpp', - 'log_test.cpp', 'rotatable_file_writer_test.cpp', ], LIBDEPS=[ diff --git a/src/mongo/logger/log_component.cpp b/src/mongo/logger/log_component.cpp deleted file mode 100644 index 257c72668a5..00000000000 --- a/src/mongo/logger/log_component.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/** - * Copyright (C) 2018-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 "mongo/logger/log_component.h" - -#include "mongo/base/init.h" -#include "mongo/base/static_assert.h" -#include "mongo/util/assert_util.h" - -namespace mongo { -namespace logger { - -namespace { - -// Component dotted names. -// Lazily evaluated in LogComponent::getDottedName(). -std::string _dottedNames[LogComponent::kNumLogComponents + 1]; - -// -// Fully initialize _dottedNames before we enter multithreaded execution. -// - -MONGO_INITIALIZER_WITH_PREREQUISITES(SetupDottedNames, MONGO_NO_PREREQUISITES) -(InitializerContext* context) { - for (int i = 0; i <= int(LogComponent::kNumLogComponents); ++i) { - logger::LogComponent component = static_cast<logger::LogComponent::Value>(i); - component.getDottedName(); - } - - return Status::OK(); -} - -} // namespace - -// Children always come after parent component. -// This makes it unnecessary to compute children of each component -// when setting/clearing log severities in LogComponentSettings. -#define DECLARE_LOG_COMPONENT_PARENT(CHILD, PARENT) \ - case (CHILD): \ - do { \ - MONGO_STATIC_ASSERT(int(CHILD) > int(PARENT)); \ - return (PARENT); \ - } while (0) - -LogComponent LogComponent::parent() const { - switch (_value) { - case kDefault: - return kNumLogComponents; - DECLARE_LOG_COMPONENT_PARENT(kJournal, kStorage); - DECLARE_LOG_COMPONENT_PARENT(kASIO, kNetwork); - DECLARE_LOG_COMPONENT_PARENT(kConnectionPool, kNetwork); - DECLARE_LOG_COMPONENT_PARENT(kBridge, kNetwork); - DECLARE_LOG_COMPONENT_PARENT(kReplicationElection, kReplication); - DECLARE_LOG_COMPONENT_PARENT(kReplicationHeartbeats, kReplication); - DECLARE_LOG_COMPONENT_PARENT(kReplicationInitialSync, kReplication); - DECLARE_LOG_COMPONENT_PARENT(kReplicationRollback, kReplication); - DECLARE_LOG_COMPONENT_PARENT(kShardingCatalogRefresh, kSharding); - DECLARE_LOG_COMPONENT_PARENT(kShardingMigration, kSharding); - DECLARE_LOG_COMPONENT_PARENT(kStorageRecovery, kStorage); - case kNumLogComponents: - return kNumLogComponents; - default: - return kDefault; - } - MONGO_UNREACHABLE; -} - -StringData LogComponent::toStringData() const { - switch (_value) { - case kDefault: - return "default"_sd; - case kAccessControl: - return "accessControl"_sd; - case kCommand: - return "command"_sd; - case kControl: - return "control"_sd; - case kExecutor: - return "executor"_sd; - case kGeo: - return "geo"_sd; - case kIndex: - return "index"_sd; - case kNetwork: - return "network"_sd; - case kQuery: - return "query"_sd; - case kReplication: - return "replication"_sd; - case kReplicationElection: - return "election"_sd; - case kReplicationHeartbeats: - return "heartbeats"_sd; - case kReplicationInitialSync: - return "initialSync"_sd; - case kReplicationRollback: - return "rollback"_sd; - case kSharding: - return "sharding"_sd; - case kShardingCatalogRefresh: - return "shardingCatalogRefresh"_sd; - case kShardingMigration: - return "migration"_sd; - case kStorage: - return "storage"_sd; - case kStorageRecovery: - return "recovery"_sd; - case kJournal: - return "journal"_sd; - case kWrite: - return "write"_sd; - case kFTDC: - return "ftdc"_sd; - case kASIO: - return "asio"_sd; - case kBridge: - return "bridge"_sd; - case kTracking: - return "tracking"_sd; - case kTransaction: - return "transaction"_sd; - case kConnectionPool: - return "connectionPool"_sd; - case kTest: - return "test"_sd; - case kNumLogComponents: - return "total"_sd; - // No default. Compiler should complain if there's a log component that's not handled. - } - MONGO_UNREACHABLE; -} - -std::string LogComponent::getShortName() const { - return toStringData().toString(); -} - -std::string LogComponent::getDottedName() const { - // Lazily evaluate dotted names in anonymous namespace. - if (_dottedNames[_value].empty()) { - switch (_value) { - case kDefault: - _dottedNames[_value] = getShortName(); - break; - case kNumLogComponents: - _dottedNames[_value] = getShortName(); - break; - default: - // Omit short name of 'default' component from dotted name. - if (parent() == kDefault) { - _dottedNames[_value] = getShortName(); - } else { - _dottedNames[_value] = parent().getDottedName() + "." + getShortName(); - } - break; - } - } - return _dottedNames[_value]; -} - -StringData LogComponent::getNameForLog() const { - switch (_value) { - case kDefault: - return "- "_sd; - case kAccessControl: - return "ACCESS "_sd; - case kCommand: - return "COMMAND "_sd; - case kControl: - return "CONTROL "_sd; - case kExecutor: - return "EXECUTOR"_sd; - case kGeo: - return "GEO "_sd; - case kIndex: - return "INDEX "_sd; - case kNetwork: - return "NETWORK "_sd; - case kQuery: - return "QUERY "_sd; - case kReplication: - return "REPL "_sd; - case kReplicationElection: - return "ELECTION"_sd; - case kReplicationHeartbeats: - return "REPL_HB "_sd; - case kReplicationInitialSync: - return "INITSYNC"_sd; - case kReplicationRollback: - return "ROLLBACK"_sd; - case kSharding: - return "SHARDING"_sd; - case kShardingCatalogRefresh: - return "SH_REFR "_sd; - case kShardingMigration: - return "MIGRATE "_sd; - case kStorage: - return "STORAGE "_sd; - case kStorageRecovery: - return "RECOVERY"_sd; - case kJournal: - return "JOURNAL "_sd; - case kWrite: - return "WRITE "_sd; - case kFTDC: - return "FTDC "_sd; - case kASIO: - return "ASIO "_sd; - case kBridge: - return "BRIDGE "_sd; - case kTracking: - return "TRACKING"_sd; - case kTransaction: - return "TXN "_sd; - case kConnectionPool: - return "CONNPOOL"_sd; - case kTest: - return "TEST "_sd; - case kNumLogComponents: - return "TOTAL "_sd; - // No default. Compiler should complain if there's a log component that's not handled. - } - MONGO_UNREACHABLE; -} - -std::ostream& operator<<(std::ostream& os, LogComponent component) { - return os << component.getNameForLog(); -} - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/log_component.h b/src/mongo/logger/log_component.h index f216af088cd..ff06e7aaed0 100644 --- a/src/mongo/logger/log_component.h +++ b/src/mongo/logger/log_component.h @@ -28,97 +28,4 @@ */ #pragma once - -#include <iosfwd> -#include <string> - -#include "mongo/base/string_data.h" - -namespace mongo { -namespace logger { - -/** - * Log components. - * Debug messages logged using the LOG() or MONGO_LOG_COMPONENT(). - * Macros may be associated with one or more log components. - */ -class LogComponent { -public: - enum Value { - kDefault = 0, - kAccessControl, - kCommand, - kControl, - kExecutor, - kGeo, - kIndex, - kNetwork, - kQuery, - kReplication, - kReplicationElection, - kReplicationHeartbeats, - kReplicationInitialSync, - kReplicationRollback, - kSharding, - kShardingCatalogRefresh, - kShardingMigration, - kStorage, - kStorageRecovery, - kJournal, - kWrite, - kFTDC, - kASIO, - kBridge, - kTracking, - kTransaction, - kConnectionPool, - kTest, - kNumLogComponents, - }; - - /* implicit */ LogComponent(Value value) : _value(value) {} - - operator Value() const { - return _value; - } - - /** - * Returns parent component. - * Returns kNumComponents if parent component is not defined (for kDefault or - * kNumLogComponents). - */ - LogComponent parent() const; - - /** - * Returns short name as a StringData. - */ - StringData toStringData() const; - - /** - * Returns short name of log component. - * Used to generate server parameter names in the format "logLevel_<component short name>". - */ - std::string getShortName() const; - - /** - * Returns dotted name of log component - short name prefixed by dot-separated names of - * ancestors. - * Used to generate command line and config file option names. - */ - std::string getDottedName() const; - - /** - * Returns name suitable for inclusion in formatted log message. - * This is derived from upper-casing the short name with some padding to - * fit into a fixed length field. - */ - StringData getNameForLog() const; - -private: - Value _value; -}; - -std::ostream& operator<<(std::ostream& os, LogComponent component); - -} // namespace logger -} // namespace mongo +#include "mongo/logv2/log_component.h" diff --git a/src/mongo/logger/log_component_settings.cpp b/src/mongo/logger/log_component_settings.cpp deleted file mode 100644 index 6adba4da495..00000000000 --- a/src/mongo/logger/log_component_settings.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (C) 2018-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 "mongo/logger/log_component_settings.h" - -#include "mongo/util/assert_util.h" - -namespace mongo { -namespace logger { - -LogComponentSettings::LogComponentSettings() { - _minimumLoggedSeverity[LogComponent::kDefault].store(LogSeverity::Log().toInt()); - - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - _minimumLoggedSeverity[i].store(_minimumLoggedSeverity[LogComponent::kDefault].load()); - _hasMinimumLoggedSeverity[i].store(false); - } - - _hasMinimumLoggedSeverity[LogComponent::kDefault].store(true); -} - -LogComponentSettings::~LogComponentSettings() {} - -bool LogComponentSettings::hasMinimumLogSeverity(LogComponent component) const { - dassert(int(component) >= 0 && int(component) < LogComponent::kNumLogComponents); - return _hasMinimumLoggedSeverity[component].load(); -} - -LogSeverity LogComponentSettings::getMinimumLogSeverity(LogComponent component) const { - dassert(int(component) >= 0 && int(component) < LogComponent::kNumLogComponents); - return LogSeverity::cast(_minimumLoggedSeverity[component].load()); -} - -void LogComponentSettings::setMinimumLoggedSeverity(LogComponent component, LogSeverity severity) { - dassert(int(component) >= 0 && int(component) < LogComponent::kNumLogComponents); - stdx::lock_guard<Latch> lk(_mtx); - _setMinimumLoggedSeverityInLock(component, severity); -} - -void LogComponentSettings::_setMinimumLoggedSeverityInLock(LogComponent component, - LogSeverity severity) { - _minimumLoggedSeverity[component].store(severity.toInt()); - _hasMinimumLoggedSeverity[component].store(true); - - // Every unconfigured component will inherit log severity from parent. - // Traversing the severity array once works because child components always - // come after the parent in the LogComponent::Value enumeration. - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - if (!_hasMinimumLoggedSeverity[i].load()) { - LogComponent::Value v = LogComponent::Value(i); - LogComponent parentComponent = LogComponent(v).parent(); - LogSeverity parentSeverity = getMinimumLogSeverity(parentComponent); - _minimumLoggedSeverity[i].store(parentSeverity.toInt()); - } - } - - if (kDebugBuild) { - // This loop validates the guarantee that either an element has an individual log severity - // set or that it's value is equal to its parent's (i.e. either the value is set or - // inherited). - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent::Value v = LogComponent::Value(i); - LogComponent parentComponent = LogComponent(v).parent(); - invariant(_hasMinimumLoggedSeverity[i].load() || - _minimumLoggedSeverity[i].load() == - _minimumLoggedSeverity[parentComponent].load()); - } - } -} - -void LogComponentSettings::clearMinimumLoggedSeverity(LogComponent component) { - dassert(int(component) >= 0 && int(component) < LogComponent::kNumLogComponents); - - stdx::lock_guard<Latch> lk(_mtx); - - // LogComponent::kDefault must always be configured. - if (component == LogComponent::kDefault) { - _setMinimumLoggedSeverityInLock(component, LogSeverity::Log()); - return; - } - - // Set unconfigured severity level to match LogComponent::kDefault. - _setMinimumLoggedSeverityInLock(component, getMinimumLogSeverity(component.parent())); - _hasMinimumLoggedSeverity[component].store(false); -} - -bool LogComponentSettings::shouldLog(LogComponent component, LogSeverity severity) const { - dassert(int(component) >= 0 && int(component) < LogComponent::kNumLogComponents); - return severity >= LogSeverity::cast(_minimumLoggedSeverity[component].loadRelaxed()); -} - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/log_component_settings.h b/src/mongo/logger/log_component_settings.h index 3b85f174b31..8a018c485f1 100644 --- a/src/mongo/logger/log_component_settings.h +++ b/src/mongo/logger/log_component_settings.h @@ -28,79 +28,4 @@ */ #pragma once - -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_severity.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/platform/mutex.h" - -namespace mongo { -namespace logger { - -/** - * Contains log severities for a list of log components. - * kDefault always has a log severity defined but it is not necessary to - * provide log severities for the other components (up to but not including kNumLogComponents). - */ -class LogComponentSettings { - LogComponentSettings(const LogComponentSettings&) = delete; - LogComponentSettings& operator=(const LogComponentSettings&) = delete; - -public: - LogComponentSettings(); - ~LogComponentSettings(); - - /** - * Returns true if a minimum log severity has been set for this component. - * Used by log level commands to query component severity configuration. - */ - bool hasMinimumLogSeverity(LogComponent component) const; - - /** - * Gets the minimum log severity for component. - * Result is defined only if hasMinimumLogSeverity() returns true for component. - */ - LogSeverity getMinimumLogSeverity(LogComponent component) const; - - /** - * Sets the minimum log severity for component. - */ - void setMinimumLoggedSeverity(LogComponent component, LogSeverity severity); - - /** - * Clears the minimum log severity for component. - * For kDefault, severity level is initialized to default value. - */ - void clearMinimumLoggedSeverity(LogComponent component); - - /** - * Predicate that answers the question, "Should I, the caller, append to you, the log - * domain, componented messages of the given severity?" True means yes. - * - * If minimum severity levels are not configured, compare 'severity' against the configured - * level for kDefault. - */ - bool shouldLog(LogComponent component, LogSeverity severity) const; - -private: - void _setMinimumLoggedSeverityInLock(LogComponent component, LogSeverity severity); - - // A mutex to synchronize writes to the severity arrays. This mutex is to synchronize changes to - // the entire array, and the atomics are to synchronize individual elements. - Mutex _mtx = MONGO_MAKE_LATCH("LogComponentSettings::_mtx"); - - // True if a log severity is explicitly set for a component. - // This differentiates between unconfigured components and components that happen to have - // the same severity as kDefault. - // This is also used to update the severities of unconfigured components when the severity - // for kDefault is modified. - AtomicWord<bool> _hasMinimumLoggedSeverity[LogComponent::kNumLogComponents]; - - // Log severities for components. - // Store numerical values of severities to be cache-line friendly. - // Set to kDefault minimum logged severity if _hasMinimumLoggedSeverity[i] is false. - AtomicWord<int> _minimumLoggedSeverity[LogComponent::kNumLogComponents]; -}; - -} // namespace logger -} // namespace mongo +#include "mongo/logv2/log_component_settings.h" diff --git a/src/mongo/logger/log_component_settings_test.cpp b/src/mongo/logger/log_component_settings_test.cpp deleted file mode 100644 index 51d2d622586..00000000000 --- a/src/mongo/logger/log_component_settings_test.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright (C) 2018-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. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_component_settings.h" -#include "mongo/logger/log_test.h" -#include "mongo/logger/logger.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/stdx/thread.h" -#include "mongo/unittest/barrier.h" -#include "mongo/util/log_global_settings.h" - -#include "mongo/unittest/unittest.h" - -namespace { - -using namespace mongo; -using namespace mongo::logger; - -// This test checks that calling "shouldLog" and "setMinimumLoggedSeverity" concurrently doesn't -// cause an invariant failure, i.e. that these methods are thread-safe. -TEST(SERVER25981Test, SetSeverityShouldLogAndClear) { - unittest::Barrier startupBarrier(4); - AtomicWord<bool> running(true); - - stdx::thread shouldLogThread([&]() { - startupBarrier.countDownAndWait(); - while (running.load()) { - shouldLogV1(LogComponent::kDefault, logger::LogSeverity::Debug(3)); - } - }); - - stdx::thread setMinimumLoggedSeverityThreadA([&]() { - startupBarrier.countDownAndWait(); - while (running.load()) { - setMinimumLoggedSeverity(LogComponent::kDefault, logger::LogSeverity::Debug(1)); - } - }); - - stdx::thread setMinimumLoggedSeverityThreadB([&]() { - startupBarrier.countDownAndWait(); - while (running.load()) { - setMinimumLoggedSeverity(LogComponent::kDefault, logger::LogSeverity::Log()); - } - }); - - stdx::thread clearMinimumLoggedSeverityThread([&]() { - startupBarrier.countDownAndWait(); - while (running.load()) { - clearMinimumLoggedSeverity(LogComponent::kDefault); - } - }); - - mongo::sleepmillis(4000); - running.store(false); - shouldLogThread.join(); - setMinimumLoggedSeverityThreadA.join(); - setMinimumLoggedSeverityThreadB.join(); - clearMinimumLoggedSeverityThread.join(); -} - -} // namespace diff --git a/src/mongo/logger/log_function_test.cpp b/src/mongo/logger/log_function_test.cpp deleted file mode 100644 index a42818fa4a0..00000000000 --- a/src/mongo/logger/log_function_test.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Copyright (C) 2018-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. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kReplication - -#include "mongo/platform/basic.h" - -#include "mongo/logger/log_test.h" - -#include <sstream> -#include <string> -#include <vector> - -#include "mongo/logger/appender.h" -#include "mongo/logger/encoder.h" -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_test_util.h" -#include "mongo/logger/message_event_utf8_encoder.h" -#include "mongo/logv2/text_formatter.h" -#include "mongo/util/str.h" - -using namespace mongo::logger; - -namespace mongo { -namespace { - -typedef LogTest<MessageEventDetailsEncoder, logv2::TextFormatter> LogTestDetailsEncoder; - -// Constants for log component test cases. -const LogComponent componentA = LogComponent::kCommand; -const LogComponent componentB = MONGO_LOG_DEFAULT_COMPONENT; - -// Tests pass through of log component: -// unconditional log functions -> LogStreamBuilder -> MessageEventEphemeral -// -> MessageEventDetailsEncoder -// MONGO_DEFAULT_LOG_COMPONENT is set to kReplication before including util/log.h -// so non-debug logging without explicit component will log with kReplication instead -// of kDefault. -TEST_F(LogTestDetailsEncoder, LogFunctionsOverrideGlobalComponent) { - // severe() - no component specified. - severe() << "This is logged"; - ASSERT_TRUE(shouldLogV1(LogSeverity::Severe())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " F " << componentB.getNameForLog()), - std::string::npos); - - // severe() - with component. - _logLines.clear(); - severe(componentA) << "This is logged"; - ASSERT_TRUE(shouldLogV1(componentA, LogSeverity::Severe())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " F " << componentA.getNameForLog()), - std::string::npos); - - // error() - no component specified. - _logLines.clear(); - error() << "This is logged"; - ASSERT_TRUE(shouldLogV1(LogSeverity::Error())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " E " << componentB.getNameForLog()), - std::string::npos); - - // error() - with component. - _logLines.clear(); - error(componentA) << "This is logged"; - ASSERT_TRUE(shouldLogV1(componentA, LogSeverity::Error())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " E " << componentA.getNameForLog()), - std::string::npos); - - // warning() - no component specified. - _logLines.clear(); - warning() << "This is logged"; - ASSERT_TRUE(shouldLogV1(LogSeverity::Warning())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " W " << componentB.getNameForLog()), - std::string::npos); - - // warning() - with component. - _logLines.clear(); - warning(componentA) << "This is logged"; - ASSERT_TRUE(shouldLogV1(componentA, LogSeverity::Warning())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " W " << componentA.getNameForLog()), - std::string::npos); - - // log() - no component specified. - _logLines.clear(); - log() << "This is logged"; - ASSERT_TRUE(shouldLogV1(LogSeverity::Log())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " I " << componentB.getNameForLog()), - std::string::npos); - - // log() - with component. - _logLines.clear(); - log(componentA) << "This is logged"; - ASSERT_TRUE(shouldLogV1(componentA, LogSeverity::Log())); - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " I " << componentA.getNameForLog()), - std::string::npos); -} - -} // namespace -} // namespace mongo diff --git a/src/mongo/logger/log_severity.cpp b/src/mongo/logger/log_severity.cpp deleted file mode 100644 index 349be573983..00000000000 --- a/src/mongo/logger/log_severity.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (C) 2018-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 "mongo/logger/log_severity.h" - -#include <iostream> - -namespace mongo { -namespace logger { - -namespace { - -constexpr auto unknownSeverityString = "UNKNOWN"_sd; -constexpr auto severeSeverityString = "SEVERE"_sd; -constexpr auto errorSeverityString = "ERROR"_sd; -constexpr auto warningSeverityString = "warning"_sd; -constexpr auto infoSeverityString = "info"_sd; -constexpr auto debugSeverityString = "debug"_sd; - -constexpr StringData kDebugLevelStrings[LogSeverity::kMaxDebugLevel] = { - "D1"_sd, - "D2"_sd, - "D3"_sd, - "D4"_sd, - "D5"_sd, -}; - -} // namespace - -StringData LogSeverity::toStringData() const { - if (_severity > 0) - return debugSeverityString; - if (*this == LogSeverity::Severe()) - return severeSeverityString; - if (*this == LogSeverity::Error()) - return errorSeverityString; - if (*this == LogSeverity::Warning()) - return warningSeverityString; - if (*this == LogSeverity::Info()) - return infoSeverityString; - if (*this == LogSeverity::Log()) - return infoSeverityString; - return unknownSeverityString; -} - -StringData LogSeverity::toStringDataCompact() const { - - if ((*this == LogSeverity::Log()) || (*this == LogSeverity::Info())) - return "I "_sd; - - if ((_severity > 0) && (_severity <= kMaxDebugLevel)) - return kDebugLevelStrings[_severity - 1]; - - if (*this == LogSeverity::Warning()) - return "W "_sd; - - if (*this == LogSeverity::Error()) - return "E "_sd; - - // 'S' might be confused with "Success" - // Return 'F' to imply Fatal instead. - if (*this == LogSeverity::Severe()) - return "F "_sd; - - return "U "_sd; -} - -std::ostream& operator<<(std::ostream& os, LogSeverity severity) { - return os << severity.toStringData(); -} - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/log_severity.h b/src/mongo/logger/log_severity.h index c96b53cfe67..56cbb7bed52 100644 --- a/src/mongo/logger/log_severity.h +++ b/src/mongo/logger/log_severity.h @@ -28,176 +28,4 @@ */ #pragma once - -#include <iosfwd> -#include <string> - -#include "mongo/base/string_data.h" - -namespace mongo { -namespace logger { - -/** - * Representation of the severity / priority of a log message. - * - * Severities are totally ordered, from most severe to least severe as follows: - * Severe, Error, Warning, Info, Log, Debug(1), Debug(2), ... - */ -class LogSeverity { -public: - // - // Static factory methods for getting LogSeverity objects of the various severity levels. - // - - static inline LogSeverity Severe(); - static inline LogSeverity Error(); - static inline LogSeverity Warning(); - static inline LogSeverity Info(); - static inline LogSeverity Log(); // === Debug(0) - - static constexpr int kMaxDebugLevel = 5; - - // Construct a LogSeverity to represent the given debug level. Debug levels above - // kMaxDebugLevel will be reset to kMaxDebugLevel. - static inline LogSeverity Debug(int debugLevel); - - /** - * Casts an integer to a severity. - * - * Do not use this. It exists to enable a handful of leftover uses of LOG(0). - */ - static inline LogSeverity cast(int); - - inline int toInt() const; - - /** - * Returns a LogSeverity object that is one unit "more severe" than this one. - */ - inline LogSeverity moreSevere() const; - - /** - * Returns a LogSeverity object that is one unit "less severe" than this one. - */ - inline LogSeverity lessSevere() const; - - /** - * Returns a std::string naming this severity level. - * - * See toStringData(), below. - */ - inline std::string toString() const; - - /** - * Returns a StringData naming this security level. - * - * Not all levels are uniquely named. Debug(N) is named "debug", regardless of "N", - * e.g. - */ - StringData toStringData() const; - - /** - * Returns two characters naming this severity level. For non-debug levels, returns - * a single character mapping to the first letter of the string returned by - * `toStringData`, followed by a space. For debug levels, returns 'DN', where N - * is an integer greater than zero. - * - * All levels are uniquely named. - */ - StringData toStringDataCompact() const; - - // - // Comparison operations. - // - - /// Returns true if this is exactly as severe as other. - inline bool operator==(const LogSeverity other) const; - - /// Returns true if this is not exactly as severe as other. - inline bool operator!=(const LogSeverity other) const; - - /// Returns true if this is less severe than other. - inline bool operator<(const LogSeverity other) const; - - /// Returns true if this is no more severe than other. - inline bool operator<=(const LogSeverity other) const; - - /// Returns true if this is more severe than other. - inline bool operator>(const LogSeverity other) const; - - /// Returns true if this is no less severe than other. - inline bool operator>=(const LogSeverity other) const; - -private: - explicit LogSeverity(int severity) : _severity(severity) {} - - /// The stored severity. More negative is more severe. NOTE: This means that the >, <, >= - /// and <= operators on LogSeverity have opposite sense of the same operators on the - /// underlying integer. That is, given severities S1 and S2, S1 > S2 means that S1.toInt() - /// < S2.toInt(). - /// - /// TODO(schwerin): Decide if we should change this so more positive is more severe. The - /// logLevel parameter in the database is more compatible with this sense, but it's not - /// totally intuitive. One could also remove the operator overloads in favor of named - /// methods, isNoMoreSevereThan, isLessSevereThan, isMoreSevereThan, isNoLessSevereThan, - /// isSameSeverity and isDifferentSeverity. - int _severity; -}; - -std::ostream& operator<<(std::ostream& os, LogSeverity severity); - -LogSeverity LogSeverity::Severe() { - return LogSeverity(-4); -} -LogSeverity LogSeverity::Error() { - return LogSeverity(-3); -} -LogSeverity LogSeverity::Warning() { - return LogSeverity(-2); -} -LogSeverity LogSeverity::Info() { - return LogSeverity(-1); -} -LogSeverity LogSeverity::Log() { - return LogSeverity(0); -} -LogSeverity LogSeverity::Debug(int debugLevel) { - // It would be appropriate to use std::max or std::clamp instead, - // but it seems better not to drag in all of <algorithm> here. - return LogSeverity(debugLevel > kMaxDebugLevel ? kMaxDebugLevel : debugLevel); -} - -LogSeverity LogSeverity::cast(int ll) { - return LogSeverity(ll); -} - -int LogSeverity::toInt() const { - return _severity; -} -LogSeverity LogSeverity::moreSevere() const { - return LogSeverity(_severity - 1); -} -LogSeverity LogSeverity::lessSevere() const { - return LogSeverity(_severity + 1); -} - -bool LogSeverity::operator==(LogSeverity other) const { - return _severity == other._severity; -} -bool LogSeverity::operator!=(LogSeverity other) const { - return _severity != other._severity; -} -bool LogSeverity::operator<(LogSeverity other) const { - return _severity > other._severity; -} -bool LogSeverity::operator<=(LogSeverity other) const { - return _severity >= other._severity; -} -bool LogSeverity::operator>(LogSeverity other) const { - return _severity < other._severity; -} -bool LogSeverity::operator>=(LogSeverity other) const { - return _severity <= other._severity; -} - -} // namespace logger -} // namespace mongo +#include "mongo/logv2/log_severity.h" diff --git a/src/mongo/logger/log_test.cpp b/src/mongo/logger/log_test.cpp deleted file mode 100644 index 464f3583a8b..00000000000 --- a/src/mongo/logger/log_test.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/** - * Copyright (C) 2018-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. - */ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/logger/log_test.h" - -#include <sstream> -#include <string> -#include <vector> - -#include "mongo/logger/appender.h" -#include "mongo/logger/encoder.h" -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_component_settings.h" -#include "mongo/logger/log_test_util.h" -#include "mongo/logger/message_event_utf8_encoder.h" -#include "mongo/logger/message_log_domain.h" -#include "mongo/logger/rotatable_file_appender.h" -#include "mongo/logger/rotatable_file_writer.h" -#include "mongo/logv2/plain_formatter.h" -#include "mongo/logv2/text_formatter.h" -#include "mongo/platform/compiler.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/concurrency/thread_name.h" -#include "mongo/util/str.h" - -using namespace mongo::logger; - -namespace mongo { -namespace { - -typedef LogTest<MessageEventDetailsEncoder, logv2::TextFormatter> LogTestDetailsEncoder; -typedef LogTest<MessageEventUnadornedEncoder, logv2::PlainFormatter> LogTestUnadornedEncoder; - -class CountAppender : public Appender<MessageEventEphemeral> { -public: - CountAppender() : _count(0) {} - virtual ~CountAppender() {} - - virtual Status append(const MessageEventEphemeral& event) { - ++_count; - return Status::OK(); - } - - int getCount() { - return _count; - } - -private: - int _count; -}; - -/** Simple tests for detaching appenders. */ -TEST_F(LogTestUnadornedEncoder, DetachAppender) { - std::unique_ptr<MessageLogDomain::EventAppender> countAppender = - std::make_unique<CountAppender>(); - MessageLogDomain domain; - - // Appending to the domain before attaching the appender does not affect the appender. - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "1")) - .transitional_ignore(); - ASSERT_EQUALS(0, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); - - // Appending to the domain after attaching the appender does affect the appender. - MessageLogDomain::AppenderHandle handle = domain.attachAppender(std::move(countAppender)); - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "2")) - .transitional_ignore(); - countAppender = domain.detachAppender(handle); - ASSERT_EQUALS(1, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); - - // Appending to the domain after detaching the appender does not affect the appender. - domain.append(MessageEventEphemeral(Date_t(), LogSeverity::Log(), "", "3")) - .transitional_ignore(); - ASSERT_EQUALS(1, dynamic_cast<CountAppender*>(countAppender.get())->getCount()); -} - -class A { -public: - std::string toString() const { - log() << "Golly!\n"; - return "Golly!"; - } -}; - -// Tests that logging while in the midst of logging produces two distinct log messages, with the -// inner log message appearing before the outer. -TEST_F(LogTestUnadornedEncoder, LogstreamBuilderReentrance) { - log() << "Logging A() -- " << A() << " -- done!" << std::endl; - ASSERT_EQUALS(2U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("Golly!")); - ASSERT(StringData(_logLines[1]).startsWith("Logging A() -- Golly! -- done!")); -} - -// -// Instantiating this object is a basic test of static-initializer-time logging. -// -class B { -public: - B() { - log() << "Exercising initializer time logging."; - } -} b; - -// Constants for log component test cases. -const LogComponent componentDefault = LogComponent::kDefault; -const LogComponent componentA = LogComponent::kCommand; -const LogComponent componentB = LogComponent::kAccessControl; -const LogComponent componentC = LogComponent::kNetwork; -const LogComponent componentD = LogComponent::kStorage; -const LogComponent componentE = LogComponent::kJournal; - -// No log component declared at file scope. -// Component severity configuration: -// LogComponent::kDefault: 2 -TEST_F(LogTestUnadornedEncoder, MongoLogMacroNoFileScopeLogComponent) { - setMinimumLoggedSeverity(LogSeverity::Debug(2)); - - LOG(2) << "This is logged"; - LOG(3) << "This is not logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("This is logged")); - - // MONGO_LOG_COMPONENT - _logLines.clear(); - MONGO_LOG_COMPONENT(2, componentA) << "This is logged"; - MONGO_LOG_COMPONENT(3, componentA) << "This is not logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT(StringData(_logLines[0]).startsWith("This is logged")); -} - -// -// Component log level tests. -// The global log manager holds the component log level configuration for the global log domain. -// LOG() and MONGO_LOG_COMPONENT() macros in util/log.h determine at runtime if a log message -// should be written to the log domain. -// - -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsMinimumLogSeverity) { - LogComponentSettings settings; - ASSERT_TRUE(settings.hasMinimumLogSeverity(LogComponent::kDefault)); - ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == LogSeverity::Log()); - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - if (component == LogComponent::kDefault) { - continue; - } - ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); - } - - // Override and clear minimum severity level. - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - LogSeverity severity = LogSeverity::Debug(2); - - // Override severity level. - settings.setMinimumLoggedSeverity(component, severity); - ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); - ASSERT_TRUE(settings.getMinimumLogSeverity(component) == severity); - - // Clear severity level. - // Special case: when clearing LogComponent::kDefault, the corresponding - // severity level is set to default values (ie. Log()). - settings.clearMinimumLoggedSeverity(component); - if (component == LogComponent::kDefault) { - ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); - ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == - LogSeverity::Log()); - } else { - ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); - } - } -} - -// Test for shouldLog() when the minimum logged severity is set only for LogComponent::kDefault. -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogDefaultLogComponentOnly) { - LogComponentSettings settings; - - // Initial log severity for LogComponent::kDefault is Log(). - ASSERT_TRUE(shouldLogV1(LogSeverity::Info())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Log())); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - // If any components are provided to shouldLog(), we should get the same outcome - // because we have not configured any non-LogComponent::kDefault components. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Log())); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - - // Set minimum logged severity so that Debug(1) messages are written to log domain. - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - ASSERT_TRUE(shouldLogV1(LogSeverity::Info())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Log())); - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - // Revert back. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); - - // Same results when components are supplied to shouldLog(). - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); -} - -// Test for shouldLog() when we have configured a single component. -// Also checks that severity level has been reverted to match LogComponent::kDefault -// after clearing level. -// Minimum severity levels: -// LogComponent::kDefault: 1 -// componentA: 2 -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogSingleComponent) { - LogComponentSettings settings; - - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); - - // Components for log message: componentA only. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); - - // Clear severity level for componentA and check shouldLog() again. - settings.clearMinimumLoggedSeverity(componentA); - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - - // Test shouldLog() with global settings. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - // Components for log message: LogComponent::kDefault only. - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); -} - -// Test for shouldLog() when we have configured multiple components. -// Minimum severity levels: -// LogComponent::kDefault: 1 -// componentA: 2 -// componentB: 0 -TEST_F(LogTestUnadornedEncoder, LogComponentSettingsShouldLogMultipleComponentsConfigured) { - LogComponentSettings settings; - - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); - settings.setMinimumLoggedSeverity(componentB, LogSeverity::Log()); - - // Components for log message: componentA only. - ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); - - // Components for log message: componentB only. - ASSERT_TRUE(settings.shouldLog(componentB, LogSeverity::Log())); - ASSERT_FALSE(settings.shouldLog(componentB, LogSeverity::Debug(1))); - - // Components for log message: componentC only. - // Since a component-specific minimum severity is not configured for componentC, - // shouldLog() falls back on LogComponent::kDefault. - ASSERT_TRUE(settings.shouldLog(componentC, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentC, LogSeverity::Debug(2))); - - // Test shouldLog() with global settings. - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - - - // Components for log message: LogComponent::kDefault only. - ASSERT_TRUE(shouldLogV1(LogSeverity::Debug(1))); - ASSERT_FALSE(shouldLogV1(LogSeverity::Debug(2))); - - setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Log()); -} - -// Log component hierarchy. -TEST_F(LogTestUnadornedEncoder, LogComponentHierarchy) { - // Parent component is not meaningful for kDefault and kNumLogComponents. - ASSERT_EQUALS(LogComponent::kNumLogComponents, LogComponent(LogComponent::kDefault).parent()); - ASSERT_EQUALS(LogComponent::kNumLogComponents, - LogComponent(LogComponent::kNumLogComponents).parent()); - - // Default -> ComponentD -> ComponentE - ASSERT_EQUALS(LogComponent::kDefault, LogComponent(componentD).parent()); - ASSERT_EQUALS(componentD, LogComponent(componentE).parent()); - ASSERT_NOT_EQUALS(LogComponent::kDefault, LogComponent(componentE).parent()); - - // Log components should inherit parent's log severity in settings. - LogComponentSettings settings; - settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); - settings.setMinimumLoggedSeverity(componentD, LogSeverity::Debug(2)); - - // componentE should inherit componentD's log severity. - ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(2))); - ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(3))); - - // Clearing parent's log severity - componentE should inherit from Default. - settings.clearMinimumLoggedSeverity(componentD); - ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(1))); - ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(2))); -} - -// Dotted name of component includes names of ancestors. -TEST_F(LogTestUnadornedEncoder, LogComponentDottedName) { - // Default -> ComponentD -> ComponentE - ASSERT_EQUALS(componentDefault.getShortName(), - LogComponent(LogComponent::kDefault).getDottedName()); - ASSERT_EQUALS(componentD.getShortName(), componentD.getDottedName()); - ASSERT_EQUALS(componentD.getShortName() + "." + componentE.getShortName(), - componentE.getDottedName()); -} - -// Log names of all components should have the same length. -TEST_F(LogTestUnadornedEncoder, LogComponentNameForLog) { - size_t defaultNameForLogLength = componentDefault.getNameForLog().toString().length(); - ASSERT_NOT_EQUALS(0U, defaultNameForLogLength); - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - ASSERT_EQUALS(defaultNameForLogLength, component.getNameForLog().toString().length()); - } -} - -/** - * Verifies that the encoded log line contains string. - */ -void testEncodedLogLine(const MessageEventEphemeral& event, const std::string& expectedSubstring) { - MessageEventDetailsEncoder encoder; - std::ostringstream os; - ASSERT_TRUE(encoder.encode(event, os)); - std::string s = os.str(); - if (s.find(expectedSubstring) == std::string::npos) { - FAIL(str::stream() << "encoded log line does not contain substring \"" << expectedSubstring - << "\". log line: " << s); - } -} - -// Log severity should always be logged as a single capital letter. -TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogSeverity) { - Date_t d = Date_t::now(); - const auto ctx = "WHAT"_sd; - const auto msg = "HUH"_sd; - // Severe is indicated by (F)atal. - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Severe(), ctx, msg), " F "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Error(), ctx, msg), " E "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Warning(), ctx, msg), " W "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Info(), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Log(), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(0), ctx, msg), " I "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(1), ctx, msg), " D1 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(2), ctx, msg), " D2 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(3), ctx, msg), " D3 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(4), ctx, msg), " D4 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(5), ctx, msg), " D5 "); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Debug(100), ctx, msg), " D5 "); - // Unknown severity. - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Severe().moreSevere(), ctx, msg), - " U "); -} - -// Non-default log component short name should always be logged. -TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogComponent) { - Date_t d = Date_t::now(); - const auto ctx = "WHAT"_sd; - const auto msg = "HUH"_sd; - for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { - LogComponent component = static_cast<LogComponent::Value>(i); - testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Info(), component, ctx, msg), - str::stream() << " I " << component.getNameForLog() << " ["); - } -} - -// Tests pass through of log component: -// log macros -> LogStreamBuilder -> MessageEventEphemeral -> MessageEventDetailsEncoder -TEST_F(LogTestDetailsEncoder, ) { - setMinimumLoggedSeverity(LogSeverity::Log()); - - // Default log component short name should not appear in detailed log line. - MONGO_LOG_COMPONENT(0, componentDefault) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(componentDefault.getNameForLog().toString()), - std::string::npos); - - // Non-default log component short name should appear in detailed log line. - _logLines.clear(); - MONGO_LOG_COMPONENT(0, componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(componentA.getNameForLog().toString()), std::string::npos); -} - -// Tests pass through of log component: -// unconditional log functions -> LogStreamBuilder -> MessageEventEphemeral -// -> MessageEventDetailsEncoder -TEST_F(LogTestDetailsEncoder, LogFunctions) { - // severe() - no component specified. - severe() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " F " << componentDefault.getNameForLog()), - std::string::npos); - - // severe() - with component. - _logLines.clear(); - severe(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " F " << componentA.getNameForLog()), - std::string::npos); - - // error() - no component specified. - _logLines.clear(); - error() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " E " << componentDefault.getNameForLog()), - std::string::npos); - - // error() - with component. - _logLines.clear(); - error(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " E " << componentA.getNameForLog()), - std::string::npos); - - // warning() - no component specified. - _logLines.clear(); - warning() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " W " << componentDefault.getNameForLog()), - std::string::npos); - - // warning() - with component. - _logLines.clear(); - warning(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " W " << componentA.getNameForLog()), - std::string::npos); - - // log() - no component specified. - _logLines.clear(); - log() << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS( - _logLines[0].find(str::stream() << " I " << componentDefault.getNameForLog()), - std::string::npos); - - // log() - with component. - _logLines.clear(); - log(componentA) << "This is logged"; - ASSERT_EQUALS(1U, _logLines.size()); - ASSERT_NOT_EQUALS(_logLines[0].find(str::stream() << " I " << componentA.getNameForLog()), - std::string::npos); -} - -} // namespace -} // namespace mongo diff --git a/src/mongo/logger/log_test.h b/src/mongo/logger/log_test.h deleted file mode 100644 index 6a405052e15..00000000000 --- a/src/mongo/logger/log_test.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright (C) 2018-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 <boost/log/core.hpp> -#include <sstream> -#include <string> -#include <vector> - -#include "mongo/base/status.h" -#include "mongo/logger/appender.h" -#include "mongo/logger/log_severity.h" -#include "mongo/logger/logger.h" -#include "mongo/logger/logv2_appender.h" -#include "mongo/logger/message_log_domain.h" -#include "mongo/logv2/component_settings_filter.h" -#include "mongo/logv2/log_capture_backend.h" -#include "mongo/logv2/log_domain.h" -#include "mongo/logv2/log_domain_global.h" -#include "mongo/logv2/log_manager.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/log_global_settings.h" - -namespace mongo { - -inline logger::LogSeverity getMinimumLogSeverity() { - return logSeverityV2toV1(logv2::LogManager::global().getGlobalSettings().getMinimumLogSeverity( - mongo::logv2::LogComponent::kDefault)); -} - -inline logger::LogSeverity getMinimumLogSeverity(logger::LogComponent component) { - return logSeverityV2toV1(logv2::LogManager::global().getGlobalSettings().getMinimumLogSeverity( - logComponentV1toV2(component))); -} - -inline void setMinimumLoggedSeverity(logger::LogSeverity severity) { - return logv2::LogManager::global().getGlobalSettings().setMinimumLoggedSeverity( - mongo::logv2::LogComponent::kDefault, mongo::logSeverityV1toV2(severity)); -} - -inline void setMinimumLoggedSeverity(logger::LogComponent component, logger::LogSeverity severity) { - return logv2::LogManager::global().getGlobalSettings().setMinimumLoggedSeverity( - logComponentV1toV2(component), mongo::logSeverityV1toV2(severity)); -} - -inline void clearMinimumLoggedSeverity(logger::LogComponent component) { - return logv2::LogManager::global().getGlobalSettings().clearMinimumLoggedSeverity( - logComponentV1toV2(component)); -} - -inline bool hasMinimumLogSeverity(logger::LogComponent component) { - return logv2::LogManager::global().getGlobalSettings().hasMinimumLogSeverity( - logComponentV1toV2(component)); -} - -namespace logger { - - -// Used for testing logging framework only. -// TODO(schwerin): Have logger write to a different log from the global log, so that tests can -// redirect their global log output for examination. -template <typename MessageEventEncoder, typename LOGV2Formatter> -class LogTest : public unittest::Test { - friend class LogTestAppender; - -public: - LogTest() : _severityOld(getMinimumLogSeverity()) { - globalLogDomain()->clearAppenders(); - _appenderHandle = globalLogDomain()->attachAppender( - std::make_unique<LogV2Appender<MessageEventEphemeral>>( - &logv2::LogManager::global().getGlobalDomain(), true)); - - if (!_captureSink) { - _captureSink = logv2::LogCaptureBackend::create(_logLines); - _captureSink->set_filter( - logv2::ComponentSettingsFilter(logv2::LogManager::global().getGlobalDomain(), - logv2::LogManager::global().getGlobalSettings())); - _captureSink->set_formatter(LOGV2Formatter()); - } - boost::log::core::get()->add_sink(_captureSink); - } - - virtual ~LogTest() { - globalLogDomain()->detachAppender(_appenderHandle); - boost::log::core::get()->remove_sink(_captureSink); - setMinimumLoggedSeverity(_severityOld); - } - -protected: - std::vector<std::string> _logLines; - LogSeverity _severityOld; - -private: - class LogTestAppender : public MessageLogDomain::EventAppender { - public: - explicit LogTestAppender(LogTest* ltest) : _ltest(ltest) {} - virtual ~LogTestAppender() {} - virtual Status append(const MessageLogDomain::Event& event) { - std::ostringstream _os; - if (!_encoder.encode(event, _os)) - return Status(ErrorCodes::LogWriteFailed, "Failed to append to LogTestAppender."); - _ltest->_logLines.push_back(_os.str()); - return Status::OK(); - } - - private: - LogTest* _ltest; - MessageEventEncoder _encoder; - }; - - MessageLogDomain::AppenderHandle _appenderHandle; - boost::shared_ptr<boost::log::sinks::synchronous_sink<logv2::LogCaptureBackend>> _captureSink; -}; - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/log_test_util.h b/src/mongo/logger/log_test_util.h deleted file mode 100644 index c13ff7489ef..00000000000 --- a/src/mongo/logger/log_test_util.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Copyright (C) 2020-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 is not used in this header. -// This header attempts to enforce the rule that no logging should be done in -// an inline function defined in a header. -// To enforce this "no logging in header" rule, we use #include guards with a validating #else -// clause. -// Also, this header relies on a preprocessor macro to determine the default component for the -// unconditional logging functions severe(), error(), warning() and log(). Disallowing multiple -// inclusion of log.h will ensure that the default component will be set correctly. - -#if defined(MONGO_UTIL_LOG_H_) -#error \ - "This may occur when log_test_util.h is included in a header. " \ - "Please check your #include's." -#else // MONGO_UTIL_LOG_H_ -#define MONGO_UTIL_LOG_H_ - -#include "mongo/logger/log_component.h" -#include "mongo/logger/log_severity_limiter.h" -#include "mongo/logger/logger.h" -#include "mongo/logger/logstream_builder.h" -#include "mongo/util/concurrency/thread_name.h" -#include "mongo/util/errno_util.h" -#include "mongo/util/log_global_settings.h" - -namespace mongo { - -/* - * Although this is a "header" file, it is only supposed to be included in C++ files. The - * definitions of the following objects and functions (in the below anonymous namespace) will - * potentially differ by TU. Therefore these names must remain with internal linkage. This - * particular anoymous namespace in this header, therefore, is not an ODR problem but is instead a - * solution to an ODR problem which would arise. - */ -namespace { - -// Provide log component in global scope so that MONGO_LOG will always have a valid component. -// Global log component will be kDefault unless overridden by MONGO_LOG_DEFAULT_COMPONENT. -#if defined(MONGO_LOG_DEFAULT_COMPONENT) -const ::mongo::logger::LogComponent MongoLogDefaultComponent_component = - MONGO_LOG_DEFAULT_COMPONENT; -#else -#error "Please see http://www.mongodb.org/about/contributors/reference/server-logging-rules/ " -#endif // MONGO_LOG_DEFAULT_COMPONENT - -using logger::LogstreamBuilderDeprecated; - -/** - * Returns a LogstreamBuilder for logging a message with LogSeverity::Severe(). - */ -inline LogstreamBuilderDeprecated severe() { - return LogstreamBuilderDeprecated(logger::globalLogDomain(), - getThreadName(), - logger::LogSeverity::Severe(), - MongoLogDefaultComponent_component); -} - -inline LogstreamBuilderDeprecated severe(logger::LogComponent component) { - return LogstreamBuilderDeprecated( - logger::globalLogDomain(), getThreadName(), logger::LogSeverity::Severe(), component); -} - -/** - * Returns a LogstreamBuilder for logging a message with LogSeverity::Error(). - */ -inline LogstreamBuilderDeprecated error() { - return LogstreamBuilderDeprecated(logger::globalLogDomain(), - getThreadName(), - logger::LogSeverity::Error(), - MongoLogDefaultComponent_component); -} - -inline LogstreamBuilderDeprecated error(logger::LogComponent component) { - return LogstreamBuilderDeprecated( - logger::globalLogDomain(), getThreadName(), logger::LogSeverity::Error(), component); -} - -/** - * Returns a LogstreamBuilder for logging a message with LogSeverity::Warning(). - */ -inline LogstreamBuilderDeprecated warning() { - return LogstreamBuilderDeprecated(logger::globalLogDomain(), - getThreadName(), - logger::LogSeverity::Warning(), - MongoLogDefaultComponent_component); -} - -inline LogstreamBuilderDeprecated warning(logger::LogComponent component) { - return LogstreamBuilderDeprecated( - logger::globalLogDomain(), getThreadName(), logger::LogSeverity::Warning(), component); -} - -/** - * Returns a LogstreamBuilder for logging a message with LogSeverity::Log(). - */ -inline LogstreamBuilderDeprecated log() { - return LogstreamBuilderDeprecated(logger::globalLogDomain(), - getThreadName(), - logger::LogSeverity::Log(), - MongoLogDefaultComponent_component); -} - -/** - * Returns a LogstreamBuilder that does not cache its ostream in a threadlocal cache. - * Use this variant when logging from places that may not be able to access threadlocals, - * such as from within other threadlocal-managed objects, or thread_specific_ptr-managed - * objects. - * - * Once SERVER-29377 is completed, this overload can be removed. - */ -inline LogstreamBuilderDeprecated logNoCache() { - return LogstreamBuilderDeprecated(logger::globalLogDomain(), - getThreadName(), - logger::LogSeverity::Log(), - MongoLogDefaultComponent_component, - false); -} - -inline LogstreamBuilderDeprecated log(logger::LogComponent component) { - return LogstreamBuilderDeprecated( - logger::globalLogDomain(), getThreadName(), logger::LogSeverity::Log(), component); -} - -inline LogstreamBuilderDeprecated log(logger::LogComponent::Value componentValue) { - return LogstreamBuilderDeprecated( - logger::globalLogDomain(), getThreadName(), logger::LogSeverity::Log(), componentValue); -} - -} // namespace - -// this can't be in log_global_settings.h because it utilizes MongoLogDefaultComponent_component -inline bool shouldLogV1(logger::LogSeverity severity) { - return logv2::LogManager::global().getGlobalSettings().shouldLog( - logComponentV1toV2(MongoLogDefaultComponent_component), logSeverityV1toV2(severity)); -} - -// MONGO_LOG uses log component from MongoLogDefaultComponent from current or global namespace. -#define MONGO_LOG(DLEVEL) \ - if (!::mongo::shouldLogV1(MongoLogDefaultComponent_component, \ - ::mongo::LogstreamBuilderDeprecated::severityCast(DLEVEL))) { \ - } else \ - ::mongo::logger::LogstreamBuilderDeprecated( \ - ::mongo::logger::globalLogDomain(), \ - ::mongo::getThreadName(), \ - ::mongo::LogstreamBuilderDeprecated::severityCast(DLEVEL), \ - MongoLogDefaultComponent_component) - -#define LOG MONGO_LOG - -#define MONGO_LOG_COMPONENT(DLEVEL, COMPONENT1) \ - if (!::mongo::shouldLogV1((COMPONENT1), \ - ::mongo::LogstreamBuilderDeprecated::severityCast(DLEVEL))) { \ - } else \ - ::mongo::logger::LogstreamBuilderDeprecated( \ - ::mongo::logger::globalLogDomain(), \ - ::mongo::getThreadName(), \ - ::mongo::LogstreamBuilderDeprecated::severityCast(DLEVEL), \ - (COMPONENT1)) - -} // namespace mongo - -#endif // MONGO_UTIL_LOG_H_ diff --git a/src/mongo/logv2/SConscript b/src/mongo/logv2/SConscript index 12644f1c547..bb2b93b4522 100644 --- a/src/mongo/logv2/SConscript +++ b/src/mongo/logv2/SConscript @@ -7,6 +7,7 @@ env = env.Clone() env.CppUnitTest( target='logv2_test', source=[ + 'logv2_component_test.cpp', 'logv2_test.cpp', 'redaction_test.cpp', ], diff --git a/src/mongo/logv2/log_component.h b/src/mongo/logv2/log_component.h index c43b259823b..407a79e16e0 100644 --- a/src/mongo/logv2/log_component.h +++ b/src/mongo/logv2/log_component.h @@ -34,8 +34,7 @@ #include "mongo/base/string_data.h" -namespace mongo { -namespace logv2 { +namespace mongo::logv2 { // clang-format off /** @@ -144,5 +143,9 @@ private: std::ostream& operator<<(std::ostream& os, LogComponent component); -} // namespace logv2 -} // namespace mongo +} // namespace mongo::logv2 + +// Legacy alias +namespace mongo::logger { +using logv2::LogComponent; +} // namespace mongo::logger diff --git a/src/mongo/logv2/log_component_settings.h b/src/mongo/logv2/log_component_settings.h index 72e0b00358c..fd2737a2401 100644 --- a/src/mongo/logv2/log_component_settings.h +++ b/src/mongo/logv2/log_component_settings.h @@ -34,8 +34,7 @@ #include "mongo/platform/atomic_word.h" #include "mongo/platform/mutex.h" -namespace mongo { -namespace logv2 { +namespace mongo::logv2 { /** * Contains log severities for a list of log components. @@ -102,5 +101,9 @@ private: AtomicWord<int> _minimumLoggedSeverity[LogComponent::kNumLogComponents]; }; -} // namespace logv2 -} // namespace mongo +} // namespace mongo::logv2 + +// Legacy alias +namespace mongo::logger { +using logv2::LogComponentSettings; +} // namespace mongo::logger diff --git a/src/mongo/logv2/log_severity.h b/src/mongo/logv2/log_severity.h index 796dd43548e..6786a21e3b6 100644 --- a/src/mongo/logv2/log_severity.h +++ b/src/mongo/logv2/log_severity.h @@ -177,3 +177,8 @@ private: }; } // namespace mongo::logv2 + +// Legacy alias +namespace mongo::logger { +using logv2::LogSeverity; +} // namespace mongo::logger diff --git a/src/mongo/logv2/logv2_component_test.cpp b/src/mongo/logv2/logv2_component_test.cpp new file mode 100644 index 00000000000..1d40d1c6753 --- /dev/null +++ b/src/mongo/logv2/logv2_component_test.cpp @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2020-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/logv2/log_component.h" +#include "mongo/logv2/log_component_settings.h" +#include "mongo/unittest/unittest.h" + + +namespace mongo::logv2 { +namespace { + +// Constants for log component test cases. +const LogComponent componentDefault = LogComponent::kDefault; +const LogComponent componentA = LogComponent::kCommand; +const LogComponent componentB = LogComponent::kAccessControl; +const LogComponent componentC = LogComponent::kNetwork; +const LogComponent componentD = LogComponent::kStorage; +const LogComponent componentE = LogComponent::kJournal; + +TEST(LogV2ComponentSettingsTest, MinimumLogSeverity) { + LogComponentSettings settings; + ASSERT_TRUE(settings.hasMinimumLogSeverity(LogComponent::kDefault)); + ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == LogSeverity::Log()); + for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { + LogComponent component = static_cast<LogComponent::Value>(i); + if (component == LogComponent::kDefault) { + continue; + } + ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); + } + + // Override and clear minimum severity level. + for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { + LogComponent component = static_cast<LogComponent::Value>(i); + LogSeverity severity = LogSeverity::Debug(2); + + // Override severity level. + settings.setMinimumLoggedSeverity(component, severity); + ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); + ASSERT_TRUE(settings.getMinimumLogSeverity(component) == severity); + + // Clear severity level. + // Special case: when clearing LogComponent::kDefault, the corresponding + // severity level is set to default values (ie. Log()). + settings.clearMinimumLoggedSeverity(component); + if (component == LogComponent::kDefault) { + ASSERT_TRUE(settings.hasMinimumLogSeverity(component)); + ASSERT_TRUE(settings.getMinimumLogSeverity(LogComponent::kDefault) == + LogSeverity::Log()); + } else { + ASSERT_FALSE(settings.hasMinimumLogSeverity(component)); + } + } +} + +// Test for shouldLog() when the minimum logged severity is set only for LogComponent::kDefault. +TEST(LogV2ComponentSettingsTest, ShouldLogDefaultLogComponentOnly) { + LogComponentSettings settings; + + // Initial log severity for LogComponent::kDefault is Log(). + // Other components should get the same outcome as kDefault. + ASSERT_TRUE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Info())); + ASSERT_TRUE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Log())); + ASSERT_FALSE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Debug(2))); + + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Info())); + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Log())); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); + + // Set minimum logged severity so that Debug(1) messages are written to log domain. + settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); + + ASSERT_TRUE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Info())); + ASSERT_TRUE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Log())); + ASSERT_TRUE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(LogComponent::kDefault, LogSeverity::Debug(2))); + // Same results for non-default components. + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Info())); + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Log())); + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); +} + +// Test for shouldLog() when we have configured a single component. +// Also checks that severity level has been reverted to match LogComponent::kDefault +// after clearing level. +// Minimum severity levels: +// LogComponent::kDefault: 1 +// componentA: 2 +TEST(LogV2ComponentSettingsTest, ShouldLogSingleComponent) { + LogComponentSettings settings; + + settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); + settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); + + // Components for log message: componentA only. + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); + + // Clear severity level for componentA and check shouldLog() again. + settings.clearMinimumLoggedSeverity(componentA); + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(2))); +} + +// Test for shouldLog() when we have configured multiple components. +// Minimum severity levels: +// LogComponent::kDefault: 1 +// componentA: 2 +// componentB: 0 +TEST(LogV2ComponentSettingsTest, ShouldLogMultipleComponentsConfigured) { + LogComponentSettings settings; + + settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); + settings.setMinimumLoggedSeverity(componentA, LogSeverity::Debug(2)); + settings.setMinimumLoggedSeverity(componentB, LogSeverity::Log()); + + // Components for log message: componentA only. + ASSERT_TRUE(settings.shouldLog(componentA, LogSeverity::Debug(2))); + ASSERT_FALSE(settings.shouldLog(componentA, LogSeverity::Debug(3))); + + // Components for log message: componentB only. + ASSERT_TRUE(settings.shouldLog(componentB, LogSeverity::Log())); + ASSERT_FALSE(settings.shouldLog(componentB, LogSeverity::Debug(1))); + + // Components for log message: componentC only. + // Since a component-specific minimum severity is not configured for componentC, + // shouldLog() falls back on LogComponent::kDefault. + ASSERT_TRUE(settings.shouldLog(componentC, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(componentC, LogSeverity::Debug(2))); +} + +// Log component hierarchy. +TEST(LogV2ComponentTest, Hierarchy) { + // Parent component is not meaningful for kDefault and kNumLogComponents. + ASSERT_EQUALS(LogComponent::kNumLogComponents, LogComponent(LogComponent::kDefault).parent()); + ASSERT_EQUALS(LogComponent::kNumLogComponents, + LogComponent(LogComponent::kNumLogComponents).parent()); + + // Default -> ComponentD -> ComponentE + ASSERT_EQUALS(LogComponent::kDefault, LogComponent(componentD).parent()); + ASSERT_EQUALS(componentD, LogComponent(componentE).parent()); + ASSERT_NOT_EQUALS(LogComponent::kDefault, LogComponent(componentE).parent()); + + // Log components should inherit parent's log severity in settings. + LogComponentSettings settings; + settings.setMinimumLoggedSeverity(LogComponent::kDefault, LogSeverity::Debug(1)); + settings.setMinimumLoggedSeverity(componentD, LogSeverity::Debug(2)); + + // componentE should inherit componentD's log severity. + ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(2))); + ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(3))); + + // Clearing parent's log severity - componentE should inherit from Default. + settings.clearMinimumLoggedSeverity(componentD); + ASSERT_TRUE(settings.shouldLog(componentE, LogSeverity::Debug(1))); + ASSERT_FALSE(settings.shouldLog(componentE, LogSeverity::Debug(2))); +} + +// Dotted name of component includes names of ancestors. +TEST(LogV2ComponentTest, DottedNameOldTest) { + // Default -> ComponentD -> ComponentE + ASSERT_EQUALS(componentDefault.getShortName(), + LogComponent(LogComponent::kDefault).getDottedName()); + ASSERT_EQUALS(componentD.getShortName(), componentD.getDottedName()); + ASSERT_EQUALS(componentD.getShortName() + "." + componentE.getShortName(), + componentE.getDottedName()); +} + +TEST(LogV2ComponentTest, DottedName) { + struct { + LogComponent lc; + StringData expect; + } const kSpecs[] = { + {LogComponent::kDefault, "default"}, + {LogComponent::kAccessControl, "accessControl"}, + {LogComponent::kReplication, "replication"}, + {LogComponent::kReplicationElection, "replication.election"}, + {LogComponent::kNumLogComponents, "total"}, + }; + for (auto&& spec : kSpecs) { + ASSERT_EQ(spec.lc.getDottedName(), spec.expect) << spec.lc; + } +} + + +} // namespace +} // namespace mongo::logv2 diff --git a/src/mongo/logv2/logv2_test.cpp b/src/mongo/logv2/logv2_test.cpp index 8d9ce7e9efb..ad002d19eb4 100644 --- a/src/mongo/logv2/logv2_test.cpp +++ b/src/mongo/logv2/logv2_test.cpp @@ -288,22 +288,6 @@ private: std::vector<boost::shared_ptr<boost::log::sinks::sink>> _attachedSinks; }; -TEST(LogV2Component, DottedName) { - struct { - LogComponent lc; - StringData expect; - } const kSpecs[] = { - {LogComponent::kDefault, "default"}, - {LogComponent::kAccessControl, "accessControl"}, - {LogComponent::kReplication, "replication"}, - {LogComponent::kReplicationElection, "replication.election"}, - {LogComponent::kNumLogComponents, "total"}, - }; - for (auto&& spec : kSpecs) { - ASSERT_EQ(spec.lc.getDottedName(), spec.expect) << spec.lc; - } -} - TEST_F(LogV2Test, Basic) { auto lines = makeLineCapture(PlainFormatter()); |