summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2014-06-05 14:55:52 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2014-06-06 18:19:01 -0400
commit616461d294bd9f5054ca38b302b6fc5d70fde20c (patch)
tree671cd2efc28166c2a8cb9d6273954e5a38ea5255 /src/mongo
parentdae863af3f695fe98c16473ca07d79fb106121c0 (diff)
downloadmongo-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.cpp2
-rw-r--r--src/mongo/db/server_options.h5
-rw-r--r--src/mongo/db/server_options_helpers.cpp22
-rw-r--r--src/mongo/logger/rotatable_file_manager.cpp3
-rw-r--r--src/mongo/logger/rotatable_file_manager.h4
-rw-r--r--src/mongo/logger/rotatable_file_writer.cpp39
-rw-r--r--src/mongo/logger/rotatable_file_writer.h4
-rw-r--r--src/mongo/logger/rotatable_file_writer_test.cpp2
-rw-r--r--src/mongo/util/log.cpp4
-rw-r--r--src/mongo/util/log.h10
-rw-r--r--src/mongo/util/signal_handlers.cpp2
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: