diff --git a/lib/ApplicationFeatures/LoggerFeature.cpp b/lib/ApplicationFeatures/LoggerFeature.cpp index 757952c6f0..9261f5b318 100644 --- a/lib/ApplicationFeatures/LoggerFeature.cpp +++ b/lib/ApplicationFeatures/LoggerFeature.cpp @@ -42,6 +42,7 @@ LoggerFeature::LoggerFeature(application_features::ApplicationServer* server) _lineNumber(false), _thread(false), _performance(false), + _keepLogRotate(false), _daemon(false), _backgrounded(false), _threaded(false) { @@ -92,6 +93,10 @@ void LoggerFeature::collectOptions(std::shared_ptr options) { options->addHiddenOption("--log.performance", "shortcut for '--log.level requests=trace'", new BooleanParameter(&_performance)); + + options->addHiddenOption("--log.keep-logrotate", + "keep the old log file after receiving a sighup", + new BooleanParameter(&_keepLogRotate)); } void LoggerFeature::loadOptions( @@ -138,6 +143,7 @@ void LoggerFeature::prepare() { Logger::setShowLineNumber(_lineNumber); Logger::setShowThreadIdentifier(_thread); Logger::setOutputPrefix(_prefix); + Logger::setKeepLogrotate(_keepLogRotate); for (auto definition : _output) { if (_daemon && StringUtils::isPrefix(definition, "file://")) { diff --git a/lib/ApplicationFeatures/LoggerFeature.h b/lib/ApplicationFeatures/LoggerFeature.h index cb92bdfa16..c9fd9f16a6 100644 --- a/lib/ApplicationFeatures/LoggerFeature.h +++ b/lib/ApplicationFeatures/LoggerFeature.h @@ -47,6 +47,7 @@ class LoggerFeature final : public application_features::ApplicationFeature { bool _lineNumber; bool _thread; bool _performance; + bool _keepLogRotate; private: bool _daemon; diff --git a/lib/Logger/LogAppenderFile.cpp b/lib/Logger/LogAppenderFile.cpp index 6743ca78de..ce1027552f 100644 --- a/lib/Logger/LogAppenderFile.cpp +++ b/lib/Logger/LogAppenderFile.cpp @@ -27,6 +27,7 @@ #include "Basics/Exceptions.h" #include "Basics/FileUtils.h" +#include "Logger/Logger.h" using namespace arangodb; using namespace arangodb::basics; @@ -60,10 +61,14 @@ void LogAppenderFile::reopen() { S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { - TRI_RenameFile(backup.c_str(), filename.c_str()); + FileUtils::rename(backup, filename); continue; } + if (!Logger::_keepLogRotate) { + FileUtils::remove(backup); + } + _fds[pos].first = fd; if (old > STDERR_FILENO) { diff --git a/lib/Logger/Logger.cpp b/lib/Logger/Logger.cpp index 5103b2a696..bf63b90e0a 100644 --- a/lib/Logger/Logger.cpp +++ b/lib/Logger/Logger.cpp @@ -44,6 +44,7 @@ bool Logger::_showLineNumber(false); bool Logger::_showThreadIdentifier(false); bool Logger::_threaded(false); bool Logger::_useLocalTime(false); +bool Logger::_keepLogRotate(false); std::string Logger::_outputPrefix(""); std::unique_ptr Logger::_loggingThread(nullptr); @@ -169,6 +170,16 @@ void Logger::setUseLocalTime(bool show) { _useLocalTime = show; } +// NOTE: this function should not be called if the logging is active. +void Logger::setKeepLogrotate(bool keep) { + if (_active) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, + "cannot change keep log rotate if logging is active"); + } + + _keepLogRotate = keep; +} + std::string const& Logger::translateLogLevel(LogLevel level) { static std::string DEFAULT = "DEFAULT"; static std::string FATAL = "FATAL"; diff --git a/lib/Logger/Logger.h b/lib/Logger/Logger.h index 0abc308c5d..11fa6732e0 100644 --- a/lib/Logger/Logger.h +++ b/lib/Logger/Logger.h @@ -124,6 +124,7 @@ class Logger { friend class LoggerStream; friend class LogThread; + friend class LogAppenderFile; public: static LogTopic COLLECTOR; @@ -180,6 +181,7 @@ class Logger { static void setShowLineNumber(bool); static void setShowThreadIdentifier(bool); static void setUseLocalTime(bool); + static void setKeepLogrotate(bool); static std::string const& translateLogLevel(LogLevel); @@ -213,6 +215,7 @@ class Logger { static bool _showThreadIdentifier; static bool _threaded; static bool _useLocalTime; + static bool _keepLogRotate; static std::string _outputPrefix; static std::unique_ptr _loggingThread; diff --git a/lib/Logger/X b/lib/Logger/X new file mode 100644 index 0000000000..256782ed89 --- /dev/null +++ b/lib/Logger/X @@ -0,0 +1,22 @@ + // helper function to prevent duplicate output filenames + auto hasAppender = [&existingAppenders](std::string const& filename) { + if (existingAppenders.find(filename) != existingAppenders.end()) { + return true; + } + // treat stderr and stdout as one output filename + if (filename == "-" && + existingAppenders.find("+") != existingAppenders.end()) { + return true; + } + if (filename == "+" && + existingAppenders.find("-") != existingAppenders.end()) { + return true; + } + return false; + }; + + if (hasAppender(filename)) { + // already have an appender for the same output + return nullptr; + } +