diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-06-05 14:55:52 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-06-06 18:19:01 -0400 |
commit | 616461d294bd9f5054ca38b302b6fc5d70fde20c (patch) | |
tree | 671cd2efc28166c2a8cb9d6273954e5a38ea5255 /src/mongo | |
parent | dae863af3f695fe98c16473ca07d79fb106121c0 (diff) | |
download | mongo-616461d294bd9f5054ca38b302b6fc5d70fde20c.tar.gz |
SERVER-4905: add flag to disable mongo's builtin log rotation
To support the standalone utility, we need to give administrators
support for disabling Mongo's builtin log rotation.
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/dbcommands_generic.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/server_options.h | 5 | ||||
-rw-r--r-- | src/mongo/db/server_options_helpers.cpp | 22 | ||||
-rw-r--r-- | src/mongo/logger/rotatable_file_manager.cpp | 3 | ||||
-rw-r--r-- | src/mongo/logger/rotatable_file_manager.h | 4 | ||||
-rw-r--r-- | src/mongo/logger/rotatable_file_writer.cpp | 39 | ||||
-rw-r--r-- | src/mongo/logger/rotatable_file_writer.h | 4 | ||||
-rw-r--r-- | src/mongo/logger/rotatable_file_writer_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/log.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/log.h | 10 | ||||
-rw-r--r-- | src/mongo/util/signal_handlers.cpp | 2 |
11 files changed, 68 insertions, 29 deletions
diff --git a/src/mongo/db/dbcommands_generic.cpp b/src/mongo/db/dbcommands_generic.cpp index 097e659e86d..5a893f7c98f 100644 --- a/src/mongo/db/dbcommands_generic.cpp +++ b/src/mongo/db/dbcommands_generic.cpp @@ -244,7 +244,7 @@ namespace mongo { out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); } virtual bool run(OperationContext* txn, const string& ns, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { - bool didRotate = rotateLogs(); + bool didRotate = rotateLogs(serverGlobalParams.logRenameOnRotate); if (didRotate) logProcessDetailsForLogRotate(); return didRotate; diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h index 2bf6df23a35..9df17b544c2 100644 --- a/src/mongo/db/server_options.h +++ b/src/mongo/db/server_options.h @@ -42,8 +42,8 @@ namespace mongo { configsvr(false), cpu(false), objcheck(true), defaultProfile(0), slowMS(100), defaultLocalThresholdMillis(15), moveParanoia(true), noUnixSocket(false), doFork(0), socket("/tmp"), maxConns(DEFAULT_MAX_CONN), - unixSocketPermissions(DEFAULT_UNIX_PERMS), logAppend(false), logWithSyslog(false), - isHttpInterfaceEnabled(false) + unixSocketPermissions(DEFAULT_UNIX_PERMS), logAppend(false), logRenameOnRotate(true), + logWithSyslog(false), isHttpInterfaceEnabled(false) { started = time(0); } @@ -91,6 +91,7 @@ namespace mongo { std::string logpath; // Path to log file, if logging to a file; otherwise, empty. bool logAppend; // True if logging to a file in append mode. + bool logRenameOnRotate;// True if logging should rename log files on rotate bool logWithSyslog; // True if logging to syslog; must not be set if logpath is set. int syslogFacility; // Facility used when appending messages to the syslog. diff --git a/src/mongo/db/server_options_helpers.cpp b/src/mongo/db/server_options_helpers.cpp index 67bff90a0bc..62c4bc8b27f 100644 --- a/src/mongo/db/server_options_helpers.cpp +++ b/src/mongo/db/server_options_helpers.cpp @@ -198,6 +198,9 @@ namespace { options->addOptionChaining("systemLog.logAppend", "logappend", moe::Switch, "append to logpath instead of over-writing"); + options->addOptionChaining("systemLog.logRotate", "logRotate", moe::String, + "set the log rotation behavior (rename|reopen)"); + options->addOptionChaining("systemLog.timeStampFormat", "timeStampFormat", moe::String, "Desired format for timestamps in log messages. One of ctime, " "iso8601-utc or iso8601-local"); @@ -814,6 +817,25 @@ namespace { serverGlobalParams.logAppend = true; } + if (params.count("systemLog.logRotate")) { + std::string logRotateParam = params["systemLog.logRotate"].as<string>(); + if (logRotateParam == "reopen") { + serverGlobalParams.logRenameOnRotate = false; + + if(serverGlobalParams.logAppend == false) { + return Status(ErrorCodes::BadValue, + "logAppend must equal true if logRotate is set to reopen" ); + } + } + else if (logRotateParam == "rename") { + serverGlobalParams.logRenameOnRotate = true; + } + else { + return Status(ErrorCodes::BadValue, + "unsupported value for logRotate " + logRotateParam ); + } + } + if (!serverGlobalParams.logpath.empty() && serverGlobalParams.logWithSyslog) { return Status(ErrorCodes::BadValue, "Cant use both a logpath and syslog "); } diff --git a/src/mongo/logger/rotatable_file_manager.cpp b/src/mongo/logger/rotatable_file_manager.cpp index d4e8d24d097..c5e9a3245d6 100644 --- a/src/mongo/logger/rotatable_file_manager.cpp +++ b/src/mongo/logger/rotatable_file_manager.cpp @@ -63,13 +63,14 @@ namespace logger { } RotatableFileManager::FileNameStatusPairVector RotatableFileManager::rotateAll( - const std::string& renameTargetSuffix) { + bool renameFiles, const std::string& renameTargetSuffix) { FileNameStatusPairVector badStatuses; for (WriterByNameMap::const_iterator iter = _writers.begin(); iter != _writers.end(); ++iter) { Status status = RotatableFileWriter::Use(iter->second).rotate( + renameFiles, iter->first + renameTargetSuffix); if (!status.isOK()) { badStatuses.push_back(std::make_pair(iter->first, status)); diff --git a/src/mongo/logger/rotatable_file_manager.h b/src/mongo/logger/rotatable_file_manager.h index 7258d0a195c..1b840716845 100644 --- a/src/mongo/logger/rotatable_file_manager.h +++ b/src/mongo/logger/rotatable_file_manager.h @@ -74,10 +74,12 @@ namespace logger { /** * Rotates all managed files, renaming each file by appending "renameTargetSuffix". * + * renameFiles - true we rename the log file, false we expect it was renamed externally + * * Returns a vector of <filename, Status> pairs for filenames with non-OK rotate status. * An empty vector indicates that all files were rotated successfully. */ - FileNameStatusPairVector rotateAll(const std::string& renameTargetSuffix); + FileNameStatusPairVector rotateAll(bool renameFiles, const std::string& renameTargetSuffix); private: typedef unordered_map<std::string, RotatableFileWriter*> WriterByNameMap; diff --git a/src/mongo/logger/rotatable_file_writer.cpp b/src/mongo/logger/rotatable_file_writer.cpp index 8b456e3f9fc..ee7e174e55a 100644 --- a/src/mongo/logger/rotatable_file_writer.cpp +++ b/src/mongo/logger/rotatable_file_writer.cpp @@ -251,28 +251,31 @@ namespace { return _openFileStream(append); } - Status RotatableFileWriter::Use::rotate(const std::string& renameTarget) { + Status RotatableFileWriter::Use::rotate(bool renameOnRotate, const std::string& renameTarget) { if (_writer->_stream) { _writer->_stream->flush(); - try { - if (boost::filesystem::exists(renameTarget)) { - return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << - "Renaming file " << _writer->_fileName << " to " << - renameTarget << " failed; destination already exists"); + + if(renameOnRotate) { + try { + if (boost::filesystem::exists(renameTarget)) { + return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << + "Renaming file " << _writer->_fileName << " to " << + renameTarget << " failed; destination already exists"); + } + } catch (const std::exception& e) { + return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << + "Renaming file " << _writer->_fileName << " to " << + renameTarget << " failed; Cannot verify whether destination " + "already exists: " << e.what()); } - } catch (const std::exception& e) { - return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << - "Renaming file " << _writer->_fileName << " to " << - renameTarget << " failed; Cannot verify whether destination " - "already exists: " << e.what()); - } - if (0 != renameFile(_writer->_fileName, renameTarget)) { - return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << - "Failed to rename \"" << _writer->_fileName << "\" to \"" << - renameTarget << "\": " << strerror(errno) << " (" << errno << ')'); - //TODO(schwerin): Make errnoWithDescription() available in the logger library, and - //use it here. + if (0 != renameFile(_writer->_fileName, renameTarget)) { + return Status(ErrorCodes::FileRenameFailed, mongoutils::str::stream() << + "Failed to rename \"" << _writer->_fileName << "\" to \"" << + renameTarget << "\": " << strerror(errno) << " (" << errno << ')'); + //TODO(schwerin): Make errnoWithDescription() available in the logger library, and + //use it here. + } } } return _openFileStream(false); diff --git a/src/mongo/logger/rotatable_file_writer.h b/src/mongo/logger/rotatable_file_writer.h index d621448f728..b68288250ea 100644 --- a/src/mongo/logger/rotatable_file_writer.h +++ b/src/mongo/logger/rotatable_file_writer.h @@ -80,13 +80,15 @@ namespace logger { * Rotates the currently opened file into "renameTarget", and open a new file * with the name previously set via setFileName(). * + * renameFiles - true we rename the log file, false we expect it was renamed externally + * * Returns Status::OK() on success. If the rename fails, returns * ErrorCodes::FileRenameFailed, and the stream continues to write to the unrotated * file. If the rename succeeds but the subsequent file open fails, returns * ErrorCodes::FileNotOpen, and the stream continues to target the original file, though * under its new name. */ - Status rotate(const std::string& renameTarget); + Status rotate(bool renameFile, const std::string& renameTarget); /** * Returns the status of the stream. diff --git a/src/mongo/logger/rotatable_file_writer_test.cpp b/src/mongo/logger/rotatable_file_writer_test.cpp index 9af7ce0d603..3bfc898253e 100644 --- a/src/mongo/logger/rotatable_file_writer_test.cpp +++ b/src/mongo/logger/rotatable_file_writer_test.cpp @@ -63,7 +63,7 @@ namespace { ASSERT_OK(writerUse.setFileName(logFileName, false)); ASSERT_TRUE(writerUse.stream() << "Level 1 message." << std::endl); ASSERT_TRUE(writerUse.stream() << "Level 2 message." << std::endl); - ASSERT_OK(writerUse.rotate(logFileNameRotated)); + ASSERT_OK(writerUse.rotate(true, logFileNameRotated)); ASSERT_TRUE(writerUse.stream() << "Level 3 message." << std::endl); ASSERT_TRUE(writerUse.stream() << "Level 4 message." << std::endl); } diff --git a/src/mongo/util/log.cpp b/src/mongo/util/log.cpp index ebf7556f109..bd0af52aac7 100644 --- a/src/mongo/util/log.cpp +++ b/src/mongo/util/log.cpp @@ -66,11 +66,11 @@ namespace mongo { return Status::OK(); } - bool rotateLogs() { + bool rotateLogs(bool renameFiles) { using logger::RotatableFileManager; RotatableFileManager* manager = logger::globalRotatableFileManager(); RotatableFileManager::FileNameStatusPairVector result( - manager->rotateAll("." + terseCurrentTime(false))); + manager->rotateAll(renameFiles, "." + terseCurrentTime(false))); for (RotatableFileManager::FileNameStatusPairVector::iterator it = result.begin(); it != result.end(); it++) { warning() << "Rotating log file " << it->first << " failed: " << it->second.toString() diff --git a/src/mongo/util/log.h b/src/mongo/util/log.h index b61913a0d32..ab221bd01da 100644 --- a/src/mongo/util/log.h +++ b/src/mongo/util/log.h @@ -93,8 +93,16 @@ namespace logger { /** * Rotates the log files. Returns true if all logs rotate successfully. + * + * renameFiles - true means we rename files, false means we expect the file to be renamed + * externally + * + * logrotate on *nix systems expects us not to rename the file, it is expected that the program + * simply open the file again with the same name. + * We expect logrotate to rename the existing file before we rotate, and so the next open + * we do should result in a file create. */ - bool rotateLogs(); + bool rotateLogs(bool renameFiles); /** output the error # and error message with prefix. handy for use as parm in uassert/massert. diff --git a/src/mongo/util/signal_handlers.cpp b/src/mongo/util/signal_handlers.cpp index 8d15ef4e912..863e946f045 100644 --- a/src/mongo/util/signal_handlers.cpp +++ b/src/mongo/util/signal_handlers.cpp @@ -306,7 +306,7 @@ namespace { switch (actualSignal) { case SIGUSR1: // log rotate signal - fassert(16782, rotateLogs()); + fassert(16782, rotateLogs(serverGlobalParams.logRenameOnRotate)); logProcessDetailsForLogRotate(); break; case SIGQUIT: |