diff options
author | Ben Caimano <ben.caimano@10gen.com> | 2018-03-13 17:34:50 -0400 |
---|---|---|
committer | Ben Caimano <ben.caimano@10gen.com> | 2018-03-16 16:46:13 -0400 |
commit | 044c0d7d67e3b47e50282b7d9c4509313a6c8db0 (patch) | |
tree | f701064c8a4a938a46e7edf2ab5a65a222404237 | |
parent | e85ca2d097655626e1178ba41cfe9863e1ba1c8d (diff) | |
download | mongo-044c0d7d67e3b47e50282b7d9c4509313a6c8db0.tar.gz |
SERVER-33758 Remove logUserIds
Removed unused `--logUserIds` flag, consolidated logger encoding
-rw-r--r-- | jstests/auth/log_user_basic.js | 260 | ||||
-rw-r--r-- | src/mongo/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/initialize_server_global_state.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/server_extra_log_context.cpp | 88 | ||||
-rw-r--r-- | src/mongo/logger/max_log_size.cpp | 57 | ||||
-rw-r--r-- | src/mongo/logger/max_log_size.h | 46 | ||||
-rw-r--r-- | src/mongo/logger/message_event_utf8_encoder.cpp | 42 | ||||
-rw-r--r-- | src/mongo/logger/message_event_utf8_encoder.h | 39 |
9 files changed, 75 insertions, 463 deletions
diff --git a/jstests/auth/log_user_basic.js b/jstests/auth/log_user_basic.js deleted file mode 100644 index dbfe90c25da..00000000000 --- a/jstests/auth/log_user_basic.js +++ /dev/null @@ -1,260 +0,0 @@ -/** - * This file tests that "user:<username>@<db>" shows up in the logs. - * @tags: [requires_sharding] - */ - -// TODO(schwerin) Re-enable this test after resolving corresponding TODO in mongo/util/log.cpp. -if (0) { - /** - * Extracts information from a mongod/mongos log entry. - * - * @param line {string} a single line of log. - * - * @return {Object} format: - * - * { - * id: <string>, // thread id of the log line. - * // list of users logged in. Can be empty. - * users: <Object> // map of db name to user name - * } - */ - var parseLog = function(line) { - var THREAD_ID_PATTERN = / [012]?\d:\d\d:\d\d\.\d\d\d \[(.+)\] /; - var ID_USER_PATTERN = new RegExp(THREAD_ID_PATTERN.source + 'user:([^ ]*) '); - var res = THREAD_ID_PATTERN.exec(line); - - if (res == null) { - return null; - } - - var logInfo = {id: res[1], users: {}}; - - var userLog = null; - res = ID_USER_PATTERN.exec(line); - - if (res != null) { - userLog = res[2]; - // should not have trailing commas - assert.neq(',', userLog[userLog.length - 1], 'Bad user log list format: ' + line); - - userLog.split(',').forEach(function(userData) { - var userAndDB = userData.split('@'); - assert.eq(2, - userAndDB.length, - 'Bad user db pair format: ' + userData + ' from line: ' + line); - logInfo.users[userAndDB[1]] = userAndDB[0]; - }); - } - - return logInfo; - }; - - /** - * Performs a series of test on user id logging. - * - * @param conn1 {Mongo} the connection object to use for logging in users. - * @param conn2 {Mongo} another connection object different from conn1. - */ - var doTest = function(conn1, conn2) { - var connInfo1 = { - id: null, // thread id of this connection - mongo: conn1, // connection object - users: {} // contains authenticated users represented as a map of db to user names. - }; - - var connInfo2 = {id: null, mongo: conn2, users: {}}; - - var conn1Auth = - [{user: 'foo', pwd: 'bar', db: 'test'}, {user: 'chun', pwd: 'li', db: 'sf'}]; - - var conn2Auth = - [{user: 'root', pwd: 'ugat', db: 'admin'}, {user: 'elbow', pwd: 'freeze', db: 'bboy'}]; - - var loginUser = function(connInfo, connAuth) { - var db = connInfo.mongo.getDB(connAuth.db); - db.createUser({user: connAuth.user, pwd: connAuth.pwd, roles: jsTest.adminUserRoles}); - db.auth(connAuth.user, connAuth.pwd); - connInfo.users[connAuth.db] = connAuth.user; - }; - - var logoutUser = function(connInfo, connAuth) { - var db = connInfo.mongo.getDB(connAuth.db); - db.runCommand({logout: 1}); - delete connInfo.users[connAuth.db]; - }; - - /** - * Performs a couple of test to make sure that the format of the log is correct. - * Also checks that whether the right users show up in the logs. - * - * @param log {Array.<string>} list of log lines to check. - * @param connInfo {Object} - */ - var checkLogs = function(log, connInfo) { - var foundOne = false; - - /** - * @return true if the logInfo contains the same users as connIfo. - */ - var checkUsers = function(logInfo) { - for (var db in logInfo.users) { - if (logInfo.users.hasOwnProperty(db) && - logInfo.users[db] != connInfo.users[db]) { - return false; - } - } - - for (db in connInfo.users) { - if (connInfo.users.hasOwnProperty(db) && - logInfo.users[db] != connInfo.users[db]) { - return false; - } - } - - return true; - }; - - var hasUser = function(logInfo) { - for (var db in logInfo.users) { - if (logInfo.users.hasOwnProperty(db)) { - return true; - } - } - - return false; - }; - - log.forEach(function(line) { - var logInfo = parseLog(line); - - if (logInfo == null) - return; - if (connInfo.id == null) { - if (checkUsers(logInfo)) { - connInfo.id = logInfo.id; - foundOne = true; - } - - return; - } - - if (logInfo.id == connInfo.id) { - foundOne = true; - assert(checkUsers(logInfo), - 'logged users does not match [' + tojson(connInfo.users) + '], log: ' + - line); - } else if (hasUser(logInfo)) { - assert(!checkUsers(logInfo), 'Unexpected user log on another thread: ' + line); - } - }); - - assert(foundOne, 'User log not found in: ' + tojson(log)); - }; - - var testDB1 = connInfo1.mongo.getDB('test'); - var testDB2 = connInfo2.mongo.getDB('test'); - - // Note: The succeeding tests should not be re-ordered. - (function() { - jsTest.log('Test single user on 1 connection.'); - loginUser(connInfo1, conn1Auth[0]); - testDB1.runCommand({dbStats: 1}); - var log = testDB1.adminCommand({getLog: 'global'}); - checkLogs(log.log, connInfo1); - })(); - - (function() { - jsTest.log('Test multiple conn with 1 user each'); - loginUser(connInfo2, conn2Auth[0]); - testDB2.runCommand({dbStats: 1}); - var log = testDB1.adminCommand({getLog: 'global'}); - checkLogs(log.log, connInfo2); - })(); - - (function() { - jsTest.log('Test multiple conn with 1 multiple user'); - loginUser(connInfo1, conn1Auth[1]); - var log = testDB1.adminCommand({getLog: 'global'}); - var lastLogLine = log.log.pop(); // Used for trimming out logs before this point. - testDB1.runCommand({dbStats: 1}); - log = testDB1.adminCommand({getLog: 'global'}); - - // Remove old log entries. - while (log.log.shift() != lastLogLine) { - } - assert(log.log.length > 0); - checkLogs(log.log, connInfo1); - })(); - - (function() { - jsTest.log('Test multiple conn with multiple users each'); - loginUser(connInfo2, conn2Auth[1]); - var log = testDB2.adminCommand({getLog: 'global'}); - var lastLogLine = log.log.pop(); // Used for trimming out logs before this point. - testDB1.runCommand({dbStats: 1}); - log = testDB2.adminCommand({getLog: 'global'}); - - // Remove old log entries. - while (log.log.shift() != lastLogLine) { - } - assert(log.log.length > 0); - checkLogs(log.log, connInfo2); - })(); - - (function() { - // Case for logout older user first. - jsTest.log('Test log line will not show foo'); - logoutUser(connInfo1, conn1Auth[0]); - var log = testDB1.adminCommand({getLog: 'global'}); - var lastLogLine = log.log.pop(); // Used for trimming out logs before this point. - testDB1.runCommand({dbStats: 1}); - log = testDB1.adminCommand({getLog: 'global'}); - - // Remove old log entries. - while (log.log.shift() != lastLogLine) { - } - assert(log.log.length > 0); - checkLogs(log.log, connInfo1); - })(); - - (function() { - jsTest.log('Test that log for conn1 will not show \'user:\''); - logoutUser(connInfo1, conn1Auth[1]); - var log = testDB1.adminCommand({getLog: 'global'}); - var lastLogLine = log.log.pop(); // Used for trimming out logs before this point. - testDB1.runCommand({dbStats: 1}); - log = testDB1.adminCommand({getLog: 'global'}); - - // Remove old log entries. - while (log.log.shift() != lastLogLine) { - } - assert(log.log.length > 0); - checkLogs(log.log, connInfo1); - })(); - - (function() { - // Case for logout newer user first. - jsTest.log('Test log line will not show elbow'); - logoutUser(connInfo2, conn2Auth[1]); - var log = testDB2.adminCommand({getLog: 'global'}); - var lastLogLine = log.log.pop(); // Used for trimming out logs before this point. - testDB1.runCommand({dbStats: 1}); - log = testDB2.adminCommand({getLog: 'global'}); - - // Remove old log entries. - while (log.log.shift() != lastLogLine) { - } - assert(log.log.length > 0); - checkLogs(log.log, connInfo2); - })(); - }; - - var conn = MongoRunner.runMongod({verbose: 5, setParameter: 'logUserIds=1'}); - doTest(conn, new Mongo(conn.host)); - MongoRunner.stopMongod(conn); - - var st = new ShardingTest( - {shards: 1, verbose: 5, other: {mongosOptions: {setParameter: 'logUserIds=1'}}}); - doTest(st.s, new Mongo(st.s.host)); - st.stop(); -} diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 6abf24572fe..3d4fb782bd9 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -92,7 +92,6 @@ env.Library( 'logger/log_severity.cpp', 'logger/logger.cpp', 'logger/logstream_builder.cpp', - 'logger/max_log_size.cpp', 'logger/message_event_utf8_encoder.cpp', 'logger/message_log_domain.cpp', 'logger/ramlog.cpp', diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index edc113ead36..91344e17244 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -401,7 +401,6 @@ env.Library( target="mongodandmongos", source=[ "initialize_server_global_state.cpp", - "server_extra_log_context.cpp", "server_options_init.cpp", ], LIBDEPS=[ diff --git a/src/mongo/db/initialize_server_global_state.cpp b/src/mongo/db/initialize_server_global_state.cpp index 7d757f930dd..87d378727f3 100644 --- a/src/mongo/db/initialize_server_global_state.cpp +++ b/src/mongo/db/initialize_server_global_state.cpp @@ -212,6 +212,7 @@ void forkServerOrDie() { quickExit(EXIT_FAILURE); } +MONGO_EXPORT_SERVER_PARAMETER(maxLogSizeKB, int, logger::LogContext::kDefaultMaxLogSizeKB); MONGO_INITIALIZER_GENERAL(ServerLogRedirection, ("GlobalLogManager", "EndStartupOptionHandling", "ForkServer"), ("default")) @@ -224,6 +225,9 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection, using logger::RotatableFileAppender; using logger::StatusWithRotatableFileWriter; + // Hook up this global into our logging encoder + MessageEventDetailsEncoder::setMaxLogSizeKBSource(maxLogSizeKB); + if (serverGlobalParams.logWithSyslog) { #ifdef _WIN32 return Status(ErrorCodes::InternalError, diff --git a/src/mongo/db/server_extra_log_context.cpp b/src/mongo/db/server_extra_log_context.cpp deleted file mode 100644 index f557ae34051..00000000000 --- a/src/mongo/db/server_extra_log_context.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/** -* Copyright (C) 2012 10gen Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License, version 3, -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your version of the -* file(s), but you are not obligated to do so. If you do not wish to do so, -* delete this exception statement from your version. If you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ - -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - -#include "mongo/platform/basic.h" - -#include "mongo/base/init.h" -#include "mongo/bson/util/builder.h" -#include "mongo/db/auth/authorization_session.h" -#include "mongo/db/auth/user_set.h" -#include "mongo/db/client.h" -#include "mongo/db/server_parameters.h" -#include "mongo/logger/max_log_size.h" -#include "mongo/util/log.h" - -namespace mongo { -namespace { - -// Server parameter controlling whether or not user ids are included in log entries. -MONGO_EXPORT_STARTUP_SERVER_PARAMETER(logUserIds, bool, false); -MONGO_EXPORT_SERVER_PARAMETER(maxLogSizeKB, int, 10); - -/** - * Note: When appending new strings to the builder, make sure to pass false to the - * includeEndingNull parameter. - */ -void appendServerExtraLogContext(BufBuilder& builder) { - Client* client = Client::getCurrent(); - if (!client) - return; - if (!AuthorizationSession::exists(client)) - return; - - UserNameIterator users = AuthorizationSession::get(client)->getAuthenticatedUserNames(); - - if (!users.more()) - return; - - builder.appendStr("user:", false); - builder.appendStr(users.next().toString(), false); - while (users.more()) { - builder.appendChar(','); - builder.appendStr(users.next().toString(), false); - } - builder.appendChar(' '); -} - -int getMaxLogSizeKB() { - return maxLogSizeKB.load(); -} - -MONGO_INITIALIZER(SetServerLogContextFunction)(InitializerContext*) { - logger::MaxLogSizeKB::setGetter(getMaxLogSizeKB); - - if (!logUserIds) - return Status::OK(); - - return logger::registerExtraLogContextFn(appendServerExtraLogContext); -} - -} // namespace -} // namespace mongo diff --git a/src/mongo/logger/max_log_size.cpp b/src/mongo/logger/max_log_size.cpp deleted file mode 100644 index 1a767924020..00000000000 --- a/src/mongo/logger/max_log_size.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2016 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/logger/max_log_size.h" - -#include "mongo/stdx/functional.h" - -namespace mongo { -namespace logger { - -namespace { - -stdx::function<int()>& getGetterFunction() { - static stdx::function<int()> instance; - return instance; -} - -} // namespace - -int MaxLogSizeKB::get() { - auto& getter = getGetterFunction(); - return !getter ? 10 : getter(); -} - -void MaxLogSizeKB::setGetter(stdx::function<int()> getter) { - getGetterFunction() = std::move(getter); -} - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/max_log_size.h b/src/mongo/logger/max_log_size.h deleted file mode 100644 index c254fe2fd10..00000000000 --- a/src/mongo/logger/max_log_size.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (C) 2016 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/stdx/functional.h" - -namespace mongo { -namespace logger { - -class MaxLogSizeKB { -public: - static int get(); - static void setGetter(stdx::function<int()> getter); - -private: - static stdx::function<int()> _getter; -}; - -} // namespace logger -} // namespace mongo diff --git a/src/mongo/logger/message_event_utf8_encoder.cpp b/src/mongo/logger/message_event_utf8_encoder.cpp index 8a412e855c8..e616d3402a3 100644 --- a/src/mongo/logger/message_event_utf8_encoder.cpp +++ b/src/mongo/logger/message_event_utf8_encoder.cpp @@ -31,21 +31,45 @@ #include <iostream> -#include "mongo/logger/max_log_size.h" #include "mongo/util/time_support.h" namespace mongo { namespace logger { -static MessageEventDetailsEncoder::DateFormatter _dateFormatter = outputDateAsISOStringLocal; +const int LogContext::kDefaultMaxLogSizeKB; + +LogContext::LogContext() + : _dateFormatter{outputDateAsISOStringLocal}, _maxLogSizeSource{nullptr} {}; + +LogContext& MessageEventDetailsEncoder::getGlobalLogContext() { + static LogContext context; + return context; +} + +void MessageEventDetailsEncoder::setMaxLogSizeKBSource(const AtomicWord<int>& source) { + invariant(getGlobalLogContext()._maxLogSizeSource == nullptr); + getGlobalLogContext()._maxLogSizeSource = &source; +} + +int MessageEventDetailsEncoder::getMaxLogSizeKB() { + auto* source = getGlobalLogContext()._maxLogSizeSource; + + // If not initialized, use the default + if (source == nullptr) + return LogContext::kDefaultMaxLogSizeKB; + + // If initialized, use the reference + // TODO: This seems like a CST seq'd load we don't need. `loadRelaxed()`? + return source->load(); +} void MessageEventDetailsEncoder::setDateFormatter(DateFormatter dateFormatter) { - _dateFormatter = dateFormatter; + getGlobalLogContext()._dateFormatter = dateFormatter; } -MessageEventDetailsEncoder::DateFormatter MessageEventDetailsEncoder::getDateFormatter() { - return _dateFormatter; +DateFormatter MessageEventDetailsEncoder::getDateFormatter() { + return getGlobalLogContext()._dateFormatter; } namespace { @@ -59,9 +83,11 @@ constexpr auto kEOL = "\n"_sd; MessageEventDetailsEncoder::~MessageEventDetailsEncoder() {} std::ostream& MessageEventDetailsEncoder::encode(const MessageEventEphemeral& event, std::ostream& os) { - const size_t maxLogSize = MaxLogSizeKB::get() * 1024; + const auto maxLogSizeKB = getMaxLogSizeKB(); + + const size_t maxLogSize = maxLogSizeKB * 1024; - _dateFormatter(os, event.getDate()); + getDateFormatter()(os, event.getDate()); os << ' '; os << event.getSeverity().toChar(); @@ -99,7 +125,7 @@ std::ostream& MessageEventDetailsEncoder::encode(const MessageEventEphemeral& ev if (event.isTruncatable() && msg.size() > maxLogSize) { os << "warning: log line attempted (" << msg.size() / 1024 << "kB) over max size (" - << MaxLogSizeKB::get() << "kB), printing beginning and end ... "; + << maxLogSizeKB << "kB), printing beginning and end ... "; os << msg.substr(0, maxLogSize / 3); os << " .......... "; os << msg.substr(msg.size() - (maxLogSize / 3)); diff --git a/src/mongo/logger/message_event_utf8_encoder.h b/src/mongo/logger/message_event_utf8_encoder.h index 914bc302f35..4b85d99d783 100644 --- a/src/mongo/logger/message_event_utf8_encoder.h +++ b/src/mongo/logger/message_event_utf8_encoder.h @@ -36,13 +36,26 @@ namespace mongo { namespace logger { +typedef void (*DateFormatter)(std::ostream&, Date_t); + +/** + * This is the logging context for the MessageEventDetailsEncoder below. It actively controls how + * the output is encoded. As of now, there can be only one. + */ +struct LogContext { + static constexpr int kDefaultMaxLogSizeKB = 10; + + LogContext(); + + DateFormatter _dateFormatter; + const AtomicWord<int>* _maxLogSizeSource; +}; + /** * Encoder that writes log messages of the style that MongoDB writes to console and files. */ class MessageEventDetailsEncoder : public Encoder<MessageEventEphemeral> { public: - typedef void (*DateFormatter)(std::ostream&, Date_t); - /** * Sets the date formatter function for all instances of MessageEventDetailsEncoder. * @@ -58,8 +71,30 @@ public: */ static DateFormatter getDateFormatter(); + /** + * Sets a static wrapper to track an atomic variable reference + * + * Only safe to call once during single-threaded execution, as in during start-up + * initialization. + */ + static void setMaxLogSizeKBSource(const AtomicWord<int>& source); + + /** + * Loads a max log size from the reference set above. If no reference has been set, it returns + * the default. Note that this has to be an atomic operation, cache values when possible. + * + * Always safe to call. + */ + static int getMaxLogSizeKB(); + virtual ~MessageEventDetailsEncoder(); virtual std::ostream& encode(const MessageEventEphemeral& event, std::ostream& os); + +private: + /** + * Grab the singleton LogContext + */ + static LogContext& getGlobalLogContext(); }; /** |