commit 58a80c7da3167a745a76778ce7f895c7a26d9330 Author: Alexey Rybalchenko Date: Wed Oct 11 15:49:49 2017 +0200 Single Logger implementation for FairLogger & FairMQLogger diff --git a/logger/CMakeLists.txt b/logger/CMakeLists.txt new file mode 100644 index 0000000..2de3885 --- /dev/null +++ b/logger/CMakeLists.txt @@ -0,0 +1,25 @@ +add_library(Logger SHARED + Logger.cxx + Logger.h +) + +target_include_directories(Logger + PUBLIC + $ + $ +) + +add_executable(loggerTest loggerTest.cxx) +target_link_libraries(loggerTest Logger pthread) + +install( + TARGETS Logger loggerTest + EXPORT FairMQ + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +install( + FILES Logger.h + DESTINATION include +) \ No newline at end of file diff --git a/logger/Logger.cxx b/logger/Logger.cxx new file mode 100644 index 0000000..44449c4 --- /dev/null +++ b/logger/Logger.cxx @@ -0,0 +1,487 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#include + +#include +#include +#include +#include +#include // put_time + +using namespace std; + +namespace fair +{ + +enum class Color : int +{ + fgBlack = 30, + fgRed = 31, + fgGreen = 32, + fgYellow = 33, + fgBlue = 34, + fgMagenta = 35, + fgCyan = 36, + fgWhite = 37, + fgDefault = 39, + bgRed = 41, + bgGreen = 42, + bgBlue = 44, + bgDefault = 49 +}; + +string startColor(Color color) +{ + ostringstream os; + os << "\033[01;" << static_cast(color) << "m"; + return os.str(); +} + +string endColor() +{ + return "\033[0m"; +} + +class ColorOut +{ + public: + ColorOut(Color color, const string& str) + : fColor(color) + , fStr(str) + {} + + friend ostream& operator<<(ostream& os, const ColorOut& w) + { + return os << "\033[01;" << static_cast(w.fColor) << "m" << w.fStr << "\033[0m"; + } + + private: + Color fColor; + const string& fStr; +}; + +class ColoredSeverityWriter +{ + public: + ColoredSeverityWriter(Logger::Severity severity) + : fSeverity(severity) + {} + + friend ostream& operator<<(ostream& os, const ColoredSeverityWriter& w) + { + switch (w.fSeverity) + { + case Logger::Severity::nolog: + return os << "\033[01;" << static_cast(Color::fgDefault) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::fatal: + return os << "\033[01;" << static_cast(Color::bgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::error: + return os << "\033[01;" << static_cast(Color::fgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::warn: + return os << "\033[01;" << static_cast(Color::fgYellow) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::state: + return os << "\033[01;" << static_cast(Color::fgMagenta) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::info: + return os << "\033[01;" << static_cast(Color::fgGreen) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::debug: + return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::debug1: + return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::debug2: + return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::debug3: + return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::debug4: + return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + case Logger::Severity::trace: + return os << "\033[01;" << static_cast(Color::fgCyan) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; + break; + default: + return os << "UNKNOWN"; + break; + } + } + + private: + Logger::Severity fSeverity; +}; + +bool Logger::fColored = false; +bool Logger::fCerrOnly = false; +fstream Logger::fFileStream; +Logger::Verbosity Logger::fVerbosity = Logger::Verbosity::low; +Logger::Severity Logger::fConsoleSeverity = Logger::Severity::info; +Logger::Severity Logger::fFileSeverity = Logger::Severity::nolog; +Logger::Severity Logger::fMinSeverity = Logger::Severity::info; +std::function Logger::fFatalCallback; + +#if defined(__APPLE__) || defined(__FreeBSD__) +const string Logger::fProcessName = getprogname(); +#elif defined(_GNU_SOURCE) +const string Logger::fProcessName = program_invocation_short_name; +#else +const string Logger::fProcessName = "?"; +#endif + +const unordered_map Logger::fVerbosityMap = +{ + { "veryhigh", Verbosity::veryhigh }, + { "high", Verbosity::high }, + { "medium", Verbosity::medium }, + { "low", Verbosity::low }, + { "VERYHIGH", Verbosity::veryhigh }, + { "HIGH", Verbosity::high }, + { "MEDIUM", Verbosity::medium }, + { "LOW", Verbosity::low } +}; + +const unordered_map Logger::fSeverityMap = +{ + { "nolog", Severity::nolog }, + { "NOLOG", Severity::nolog }, + { "error", Severity::error }, + { "ERROR", Severity::error }, + { "warn", Severity::warn }, + { "WARN", Severity::warn }, + { "warning", Severity::warning }, + { "WARNING", Severity::warning }, + { "state", Severity::state }, + { "STATE", Severity::state }, + { "info", Severity::info }, + { "INFO", Severity::info }, + { "debug", Severity::debug }, + { "DEBUG", Severity::debug }, + { "trace", Severity::trace }, + { "TRACE", Severity::trace }, + { "debug1", Severity::debug1 }, + { "DEBUG1", Severity::debug1 }, + { "debug2", Severity::debug2 }, + { "DEBUG2", Severity::debug2 }, + { "debug3", Severity::debug3 }, + { "DEBUG3", Severity::debug3 }, + { "debug4", Severity::debug4 }, + { "DEBUG4", Severity::debug4 } +}; + +const array Logger::fSeverityNames = +{ + { + "NOLOG", + "FATAL", + "ERROR", + "WARN", + "STATE", + "INFO", + "DEBUG", + "DEBUG1", + "DEBUG2", + "DEBUG3", + "DEBUG4", + "TRACE" + } +}; + +const array Logger::fVerbosityNames = +{ + { + "low", + "medium", + "high", + "veryhigh" + } +}; + +string Logger::SeverityName(Severity severity) +{ + return fSeverityNames.at(static_cast(severity)); +} + +string Logger::VerbosityName(Verbosity verbosity) +{ + return fVerbosityNames.at(static_cast(verbosity)); +} + +Logger::Logger(Severity severity) + : fCurrentSeverity(severity) +{} + +void Logger::SetConsoleSeverity(const Severity severity) +{ + fConsoleSeverity = severity; + UpdateMinSeverity(); +} + +void Logger::SetConsoleSeverity(const string& severityStr) +{ + if (fSeverityMap.count(severityStr)) + { + SetConsoleSeverity(fSeverityMap.at(severityStr)); + } + else + { + LOG(ERROR) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'."; + SetConsoleSeverity(Severity::info); + } +} + +void Logger::SetFileSeverity(const Severity severity) +{ + fFileSeverity = severity; + UpdateMinSeverity(); +} + +void Logger::SetFileSeverity(const string& severityStr) +{ + if (fSeverityMap.count(severityStr)) + { + SetFileSeverity(fSeverityMap.at(severityStr)); + } + else + { + LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'."; + SetFileSeverity(Severity::info); + } +} + +void Logger::UpdateMinSeverity() +{ + fMinSeverity = (fConsoleSeverity <= fFileSeverity) ? fFileSeverity : fConsoleSeverity; +} + +bool Logger::Logging(Severity severity) +{ + if (Severity::fatal == severity) + { + return true; + } + if (severity <= fMinSeverity && severity > Severity::nolog) + { + return true; + } + else + { + return false; + } +} + +void Logger::SetVerbosity(const Verbosity verbosity) +{ + fVerbosity = verbosity; +} + +void Logger::SetVerbosity(const string& verbosityStr) +{ + if (fVerbosityMap.count(verbosityStr)) + { + fVerbosity = fVerbosityMap.at(verbosityStr); + } + else + { + LOG(error) << "Unknown verbosity setting: '" << verbosityStr << "', setting to default 'low'."; + fVerbosity = Verbosity::low; + } +} + +void Logger::SetConsoleColor(const bool colored) +{ + fColored = colored; +} + +void Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName) +{ + if (fFileStream.is_open()) + { + fFileStream.close(); + } + + string fullName = filename; + + if (customizeName) + { + // TODO: customize file name + auto now = chrono::system_clock::to_time_t(chrono::system_clock::now()); + stringstream ss; + ss << "_" << put_time(localtime(&now), "%Y-%m-%d_%H_%M_%S") << ".log"; + fullName += ss.str(); + } + + fFileStream.open(fullName, fstream::out | fstream::app); + + if (fFileStream.is_open()) + { + fFileSeverity = severity; + UpdateMinSeverity(); + } + else + { + cout << "Error opening file: " << fullName; + } + +} + +void Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName) +{ + if (fSeverityMap.count(severityStr)) + { + InitFileSink(fSeverityMap.at(severityStr), filename, customizeName); + } + else + { + LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'."; + InitFileSink(Severity::info, filename); + } +} + +void Logger::RemoveFileSink() +{ + if (fFileStream.is_open()) + { + fFileStream.close(); + } +} + +bool Logger::LoggingToConsole() const +{ + return (fCurrentSeverity <= fConsoleSeverity && + fCurrentSeverity > Severity::nolog) || + fCurrentSeverity == Severity::fatal; +} + +bool Logger::LoggingToFile() const +{ + return (fCurrentSeverity <= fFileSeverity && + fCurrentSeverity > Severity::nolog) || + fCurrentSeverity == Severity::fatal; +} + +ostringstream& Logger::Log(const string& file, const string& line, const string& func) +{ + size_t pos = file.rfind("/"); + auto now = chrono::system_clock::now(); + auto now_c = chrono::system_clock::to_time_t(now); + auto ns = chrono::duration_cast(now.time_since_epoch()) % 1000000; + + if ((!fColored && LoggingToConsole()) || (fFileStream.is_open() && LoggingToFile())) + { + if (fVerbosity >= Verbosity::high) + { + fBWOut << "[" << fProcessName << "]" + << "[" << put_time(localtime(&now_c), "%H:%M:%S") << "." << setw(6) << setfill('0') << ns.count() << "]"; + } + else if (fVerbosity == Verbosity::medium) + { + fBWOut << "[" << put_time(localtime(&now_c), "%H:%M:%S") << "]"; + } + + fBWOut << "[" << fSeverityNames.at(static_cast(fCurrentSeverity)) << "]"; + + if (fVerbosity == Verbosity::veryhigh) + { + fBWOut << "[" << file.substr(pos + 1) << ":" << line << ":" << func << "]"; + } + + fBWOut << " "; + } + + if (fColored && (LoggingToConsole())) + { + if (fVerbosity >= Verbosity::high) + { + fColorOut << "[" << ColorOut(Color::fgBlue, fProcessName) << "]" + << "[" << startColor(Color::fgCyan) << put_time(localtime(&now_c), "%H:%M:%S") << "." << setw(6) << setfill('0') << ns.count() << endColor() << "]"; + } + else if (fVerbosity == Verbosity::medium) + { + fColorOut << "[" << startColor(Color::fgCyan) << put_time(localtime(&now_c), "%H:%M:%S") << endColor() << "]"; + } + + fColorOut << "[" << ColoredSeverityWriter(fCurrentSeverity) << "]"; + + if (fVerbosity == Verbosity::veryhigh) + { + fColorOut << "[" << ColorOut(Color::fgBlue, file.substr(pos + 1)) << ":" << ColorOut(Color::fgYellow, line) << ":" << ColorOut(Color::fgBlue, func) << "]"; + } + + fColorOut << " "; + } + + return fContent; +} + +void Logger::OnFatal(std::function func) +{ + fFatalCallback = func; +} + +void Logger::SetCerrOnly(bool cerrOnly) +{ + fCerrOnly = cerrOnly; +} + +Logger::~Logger() noexcept(false) +{ + fContent << "\n"; // "\n" + flush instead of endl makes output thread safe. + + fBWOut << fContent.str(); + + if (LoggingToConsole()) + { + if (fColored) + { + fColorOut << fContent.str(); + if (fCurrentSeverity == Severity::fatal || fCurrentSeverity == Severity::error || fCerrOnly) + { + cerr << fColorOut.str() << flush; + } + else + { + cout << fColorOut.str() << flush; + } + } + else + { + if (fCurrentSeverity == Severity::fatal || fCurrentSeverity == Severity::error || fCerrOnly) + { + cerr << fBWOut.str() << flush; + } + else + { + cout << fBWOut.str() << flush; + } + } + } + + if (LoggingToFile()) + { + if (fFileStream.is_open()) + { + fFileStream << fBWOut.str() << flush; + } + } + + if (fCurrentSeverity == Severity::fatal) + { + if (fFatalCallback) + { + fFatalCallback(); + } + } +} + +} // namespace fair diff --git a/logger/Logger.h b/logger/Logger.h new file mode 100644 index 0000000..9674899 --- /dev/null +++ b/logger/Logger.h @@ -0,0 +1,177 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#ifndef FAIR_LOGGER_H +#define FAIR_LOGGER_H + +#ifdef DEBUG +#undef DEBUG +#warning "The symbol 'DEBUG' is used in FairRoot Logger. undefining..." +#endif + +#include +#include +#include +#include +#include + +namespace fair +{ + +// non-std exception to avoid undesirable catches - fatal should exit in a way we want. +class FatalException +{ + public: + FatalException() + : fWhat() + {} + + FatalException(std::string what) + : fWhat(what) + {} + + std::string What() + { + return fWhat; + } + + private: + std::string fWhat; +}; + +class Logger +{ + public: + enum class Severity : int + { + nolog, + fatal, + error, + warn, + state, + info, + debug, + debug1, + debug2, + debug3, + debug4, + trace, + // backwards-compatibility: + NOLOG = nolog, + FATAL = fatal, + ERROR = error, + WARN = warn, + warning = warn, + WARNING = warn, + STATE = state, + INFO = info, + DEBUG = debug, + DEBUG1 = debug1, + DEBUG2 = debug2, + DEBUG3 = debug3, + DEBUG4 = debug4, + TRACE = trace + }; + + // verbosity levels: + // low: [severity] message + // medium: [HH:MM:SS][severity] message + // high: [process name][HH:MM:SS:NS][severity] message + // veryhigh: [process name][HH:MM:SS:NS][severity][file:line:function] message + enum class Verbosity : int + { + low, + medium, + high, + veryhigh, + // backwards-compatibility: + LOW = low, + MEDIUM = medium, + HIGH = high, + VERYHIGH = veryhigh + }; + + Logger(Severity severity); + + static void SetConsoleSeverity(const Severity severity); + static void SetConsoleSeverity(const std::string& severityStr); + + static void SetFileSeverity(const Severity severity); + static void SetFileSeverity(const std::string& severityStr); + + static bool Logging(const Severity severity); + + static void SetVerbosity(const Verbosity verbosity); + static void SetVerbosity(const std::string& verbosityStr); + + static void SetConsoleColor(const bool colored = true); + + static void InitFileSink(const Severity severity, const std::string& filename, bool customizeName = true); + static void InitFileSink(const std::string& severityStr, const std::string& filename, bool customizeName = true); + + static void RemoveFileSink(); + + static std::string SeverityName(Severity); + static std::string VerbosityName(Verbosity); + + std::ostringstream& Log(const std::string& file, const std::string& line, const std::string& func); + + static const std::unordered_map fVerbosityMap; + static const std::unordered_map fSeverityMap; + static const std::array fSeverityNames; + static const std::array fVerbosityNames; + + static void OnFatal(std::function func); + + static void SetCerrOnly(bool cerrOnly); + + virtual ~Logger() noexcept(false); + + private: + Severity fCurrentSeverity; + + std::ostringstream fContent; + std::ostringstream fColorOut; + std::ostringstream fBWOut; + static const std::string fProcessName; + static bool fColored; + static bool fCerrOnly; + static std::fstream fFileStream; + + static Severity fConsoleSeverity; + static Severity fFileSeverity; + static Severity fMinSeverity; + + static Verbosity fVerbosity; + + static std::function fFatalCallback; + + bool LoggingToConsole() const; + bool LoggingToFile() const; + + static void UpdateMinSeverity(); +}; + +} // namespace fair + +#define IMP_CONVERTTOSTRING(s) # s +#define CONVERTTOSTRING(s) IMP_CONVERTTOSTRING(s) + +#define LOG(severity) \ + for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Logger::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \ + fair::Logger(fair::Logger::Severity::severity).Log(__FILE__, CONVERTTOSTRING(__LINE__), __FUNCTION__) + +// with custom file, line, function +#define LOGD(severity, file, line, function) \ + for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \ + fair::Logger(severity).Log(file, line, function) + +#define LOG_IF(severity, condition) \ + for (bool fairLOggerunLikelyvariable2 = false; condition && !fairLOggerunLikelyvariable2; fairLOggerunLikelyvariable2 = true) \ + LOG(severity) + +#endif // FAIR_LOGGER_H diff --git a/logger/loggerTest.cxx b/logger/loggerTest.cxx new file mode 100644 index 0000000..35a73a3 --- /dev/null +++ b/logger/loggerTest.cxx @@ -0,0 +1,134 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +// WARNING : pragma commands to hide boost warning +// TODO : remove these pragma commands when boost will fix this issue in future release + +#include + +#include +#include +#include + +using namespace std; +using namespace fair; + +void printEverySeverity() +{ + static int i = 1; + + LOG(nolog) << "nolog message " << i++; + LOG(error) << "error message " << i++; + LOG(warn) << "warning message " << i++; + LOG(state) << "state message " << i++; + LOG(info) << "info message " << i++; + LOG(debug) << "debug message " << i++; + LOG(debug1) << "debug1 message " << i++; + LOG(debug2) << "debug2 message " << i++; + LOG(debug3) << "debug3 message " << i++; + LOG(debug4) << "debug4 message " << i++; + LOG(trace) << "trace message " << i++; +} + +void printAllVerbositiesWithSeverity(Logger::Severity sev) +{ + Logger::SetConsoleSeverity(sev); + + cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl; + Logger::SetVerbosity(Logger::Verbosity::low); + printEverySeverity(); + cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl; + Logger::SetVerbosity(Logger::Verbosity::medium); + printEverySeverity(); + cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl; + Logger::SetVerbosity(Logger::Verbosity::high); + printEverySeverity(); + cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl; + Logger::SetVerbosity(Logger::Verbosity::veryhigh); + printEverySeverity(); +} + +void silentlyPrintAllVerbositiesWithSeverity(Logger::Severity sev) +{ + Logger::SetConsoleSeverity(sev); + + Logger::SetVerbosity(Logger::Verbosity::low); + printEverySeverity(); + Logger::SetVerbosity(Logger::Verbosity::medium); + printEverySeverity(); + Logger::SetVerbosity(Logger::Verbosity::high); + printEverySeverity(); + Logger::SetVerbosity(Logger::Verbosity::veryhigh); + printEverySeverity(); +} + +int main() +{ + Logger::SetConsoleColor(true); + + cout << "testing severities..." << endl; + + printAllVerbositiesWithSeverity(Logger::Severity::trace); + printAllVerbositiesWithSeverity(Logger::Severity::debug4); + printAllVerbositiesWithSeverity(Logger::Severity::debug3); + printAllVerbositiesWithSeverity(Logger::Severity::debug2); + printAllVerbositiesWithSeverity(Logger::Severity::debug1); + printAllVerbositiesWithSeverity(Logger::Severity::debug); + printAllVerbositiesWithSeverity(Logger::Severity::info); + printAllVerbositiesWithSeverity(Logger::Severity::state); + printAllVerbositiesWithSeverity(Logger::Severity::warn); + printAllVerbositiesWithSeverity(Logger::Severity::error); + printAllVerbositiesWithSeverity(Logger::Severity::nolog); + + cout << endl; + cout << "resetting severity to 'info' and verbosity to 'medium'" << endl; + Logger::SetConsoleSeverity(Logger::Severity::info); + Logger::SetVerbosity(Logger::Verbosity::medium); + + cout << "is logging trace: " << fair::Logger::Logging(Logger::Severity::trace) << endl; + cout << "is logging debug4: " << fair::Logger::Logging(Logger::Severity::debug) << endl; + cout << "is logging debug3: " << fair::Logger::Logging(Logger::Severity::debug) << endl; + cout << "is logging debug2: " << fair::Logger::Logging(Logger::Severity::debug) << endl; + cout << "is logging debug1: " << fair::Logger::Logging(Logger::Severity::debug) << endl; + cout << "is logging debug: " << fair::Logger::Logging(Logger::Severity::debug) << endl; + cout << "is logging info: " << fair::Logger::Logging(Logger::Severity::info) << endl; + cout << "is logging state: " << fair::Logger::Logging(Logger::Severity::state) << endl; + cout << "is logging warn: " << fair::Logger::Logging(Logger::Severity::warn) << endl; + cout << "is logging error: " << fair::Logger::Logging(Logger::Severity::error) << endl; + cout << "is logging fatal: " << fair::Logger::Logging(Logger::Severity::fatal) << endl; + cout << "is logging nolog: " << fair::Logger::Logging(Logger::Severity::nolog) << endl; + + for (int i = 0; i < 1000000; ++i) + { + silentlyPrintAllVerbositiesWithSeverity(Logger::Severity::nolog); + } + cout << endl; + cout << "resetting severity to 'trace' and verbosity to 'veryhigh'" << endl; + Logger::SetConsoleSeverity(Logger::Severity::trace); + Logger::SetVerbosity(Logger::Verbosity::veryhigh); + + cout << endl; + cout << "testing conditional logging..." << endl; + int x = 0; + LOG(info) << "x = " << x << " (initial)"; + LOG_IF(info, (x == 0)) << "incrementing x to " << ++x; + LOG(info) << "x = " << x << " (after increment)"; + LOG_IF(info, (x == 0)) << "this should not be printed and x not incremented: " << ++x; + LOG(info) << "x = " << x << " (after conditional increment)"; + + cout << endl; + cout << "resetting severity to 'nolog'" << endl; + Logger::SetConsoleSeverity(Logger::Severity::nolog); + + cout << "----------------------------" << endl; + cout << "open log file with severity 'error'" << endl; + Logger::InitFileSink(Logger::Severity::error, "test_log", true); + printEverySeverity(); + + return 0; +}