diff --git a/doc/releaseNotes.md b/doc/releaseNotes.md index f367a74..825880a 100644 --- a/doc/releaseNotes.md +++ b/doc/releaseNotes.md @@ -1,4 +1,4 @@ -# InfoLogger release notes +rsion# InfoLogger release notes This file describes the main feature changes for each InfoLogger released version. @@ -123,3 +123,6 @@ This file describes the main feature changes for each InfoLogger released versio ## v2.4.4 - 09/05/2022 - changed algorithm of DB threads message distribution, now based on timestamp to help keeping multi-line split messages in same order. + +## v2.5.0 - 17/06/2022 +- added InfoLogger::filterDiscardSetFile(), to allow saving to local file the messages that would be discarded with filterDiscard(...) settings. diff --git a/include/InfoLogger/InfoLogger.hxx b/include/InfoLogger/InfoLogger.hxx index 091a0d3..e109195 100644 --- a/include/InfoLogger/InfoLogger.hxx +++ b/include/InfoLogger/InfoLogger.hxx @@ -376,6 +376,14 @@ class InfoLogger /// Messages with undefined level are never filtered out. void filterDiscardLevel(int excludeLevel); + /// Defines a file where discarded messages are saved + /// path: path to file. If null, discarding to file is disabled. + /// rotateMaxBytes: Maximum file size, after which a new file is created. If zero, no limit. + /// rotateMaxFiles: Maximum number of files to keep (including the "current" file). If zero, no limit. + /// rotateNow: If non-zero, the file is immediately rotated (independently of its size), otherwise it is appended. + /// Returns 0 on success, or an error code. + int filterDiscardSetFile(const char *path, unsigned long rotateMaxBytes = 0, unsigned int rotateMaxFiles = 0, unsigned int rotateNow = 0); + /// Reset defined filters. /// All messages are then kept and handled normally. void filterReset(); diff --git a/src/InfoLogger.cxx b/src/InfoLogger.cxx index 2d04f85..8d00ef9 100644 --- a/src/InfoLogger.cxx +++ b/src/InfoLogger.cxx @@ -417,6 +417,8 @@ class InfoLogger::Impl bool filterDiscardDebug = false; // when set, messages with debug severity are dropped int filterDiscardLevel = InfoLogger::undefinedMessageOption.level; // when set, messages with higher level (>=) are dropped + bool filterDiscardFileEnabled = false; // when set, discarded messages go to file + SimpleLog filterDiscardFile; // file object where to save discarded messages // message flood prevention // constants @@ -549,14 +551,19 @@ int InfoLogger::Impl::pushMessage(InfoLogger::Severity severity, const char* mes int InfoLogger::Impl::pushMessage(const InfoLoggerMessageOption& options, const InfoLoggerContext& context, const char* messageBody, bool noFlood) { + bool discardMessage = 0; + // check if message passes local filter criteria, if any if (filterDiscardDebug && (options.severity == InfoLogger::Severity::Debug)) { - return 1; + discardMessage = 1; } if ((filterDiscardLevel != undefinedMessageOption.level) && (options.level != undefinedMessageOption.level) && (options.level >= filterDiscardLevel)) { - return 1; + discardMessage = 1; + } + if ((discardMessage) && (!filterDiscardFileEnabled)) { + return 1; } infoLog_msg_t msg = defaultMsg; @@ -630,6 +637,28 @@ int InfoLogger::Impl::pushMessage(const InfoLoggerMessageOption& options, const InfoLoggerMessageHelperSetValue(msg, msgHelper.ix_username, String, context.userName.c_str()); } + // handling of messages to be discarded to file + if (discardMessage) { + char buffer[LOG_MAX_SIZE]; + msgHelper.MessageToText(&msg, buffer, sizeof(buffer), InfoLoggerMessageHelper::Format::Simple); + + switch (options.severity) { + case (InfoLogger::Severity::Fatal): + case (InfoLogger::Severity::Error): + filterDiscardFile.error("%s", buffer); + break; + case (InfoLogger::Severity::Warning): + filterDiscardFile.warning("%s", buffer); + break; + case (InfoLogger::Severity::Info): + case (InfoLogger::Severity::Debug): + default: + filterDiscardFile.info("%s", buffer); + break; + } + return 1; + } + // message stats: after filter, before flood protection // NB: "Undefined" to be counted as "Info", as in defaultMsg. Translated correctly by getIndexFromSeverity. messageCountPerSeverity[0]++; @@ -1159,6 +1188,16 @@ void InfoLogger::filterDiscardLevel(int excludeLevel) { mPimpl->filterDiscardLevel = excludeLevel; } +int InfoLogger::filterDiscardSetFile(const char *path, unsigned long rotateMaxBytes, unsigned int rotateMaxFiles, unsigned int rotateNow) { + mPimpl->filterDiscardFileEnabled = false; + int err = mPimpl->filterDiscardFile.setLogFile(path, rotateMaxBytes, rotateMaxFiles, rotateNow); + if (!err) { + mPimpl->filterDiscardFileEnabled = true; + //mPimpl->filterDiscardFile.setOutputFormat(SimpleLog::FormatOption::ShowMessage); + } + return err; +} + void InfoLogger::filterReset() { mPimpl->filterDiscardDebug = false; mPimpl->filterDiscardLevel = InfoLogger::undefinedMessageOption.level; diff --git a/test/testInfoLogger.cxx b/test/testInfoLogger.cxx index aa047b6..2bd41df 100644 --- a/test/testInfoLogger.cxx +++ b/test/testInfoLogger.cxx @@ -83,7 +83,17 @@ int main() theLog.log(LogInfoDevel, "Info message with severity filter - you should see this"); theLog.filterReset(); theLog.log(LogDebugDevel, "Debug message with severity filter - you should see this again"); - + + #define PATH_LOGS_DISCARDED "/tmp/logsdiscarded.txt" + theLog.log(LogInfoDevel, "Discarding messages to file " PATH_LOGS_DISCARDED); + theLog.filterDiscardLevel(InfoLogger::Level::Devel); + theLog.filterDiscardDebug(1); + theLog.filterDiscardSetFile(PATH_LOGS_DISCARDED); + theLog.log(LogInfoDevel, "Devel message with level filter - you should see this only in file"); + theLog.log(LogDebugDevel, "Debug message with severity filter - you should see this only in file"); + theLog.log(LogErrorDevel, "Devel error message with level filter - you should see this only in file"); + theLog.filterReset(); + // message verbosity control with auto-mute const int limitN = 5; // max number of messages ... const int limitT = 3; // ... for given time interval