From a9f9030041331f289ca84800f90bc1e8fa0cd989 Mon Sep 17 00:00:00 2001 From: Alexey Rybalchenko Date: Thu, 25 Jan 2018 16:31:42 +0100 Subject: [PATCH] Logger: Allow adding custom sinks (example in logger/loggerTest.cxx, docs in fairmq/docs/Logging.md) --- logger/Logger.cxx | 197 +++++++++++++++++++++++++++++++----------- logger/Logger.h | 141 ++++++++++++++++++------------ logger/loggerTest.cxx | 134 +++++++++++++++++----------- 3 files changed, 313 insertions(+), 159 deletions(-) diff --git a/logger/Logger.cxx b/logger/Logger.cxx index 3d7f602..b7655f0 100644 --- a/logger/Logger.cxx +++ b/logger/Logger.cxx @@ -69,7 +69,7 @@ class ColorOut class ColoredSeverityWriter { public: - ColoredSeverityWriter(Logger::Severity severity) + ColoredSeverityWriter(Severity severity) : fSeverity(severity) {} @@ -77,40 +77,40 @@ class ColoredSeverityWriter { switch (w.fSeverity) { - case Logger::Severity::nolog: + case Severity::nolog: return os << "\033[01;" << static_cast(Color::fgDefault) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::fatal: + case Severity::fatal: return os << "\033[01;" << static_cast(Color::bgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::error: + case Severity::error: return os << "\033[01;" << static_cast(Color::fgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::warn: + case Severity::warn: return os << "\033[01;" << static_cast(Color::fgYellow) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::state: + case Severity::state: return os << "\033[01;" << static_cast(Color::fgMagenta) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::info: + case Severity::info: return os << "\033[01;" << static_cast(Color::fgGreen) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::debug: + case Severity::debug: return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::debug1: + case Severity::debug1: return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::debug2: + case Severity::debug2: return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::debug3: + case Severity::debug3: return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::debug4: + case Severity::debug4: return os << "\033[01;" << static_cast(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; - case Logger::Severity::trace: + case Severity::trace: return os << "\033[01;" << static_cast(Color::fgCyan) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m"; break; default: @@ -120,16 +120,18 @@ class ColoredSeverityWriter } private: - Logger::Severity fSeverity; + Severity fSeverity; }; bool Logger::fColored = 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; +Verbosity Logger::fVerbosity = Verbosity::low; +Severity Logger::fConsoleSeverity = Severity::info; +Severity Logger::fFileSeverity = Severity::nolog; +Severity Logger::fMinSeverity = Severity::info; +function Logger::fFatalCallback; +unordered_map>> Logger::fCustomSinks; +mutex Logger::fMtx; #if defined(__APPLE__) || defined(__FreeBSD__) const string Logger::fProcessName = getprogname(); @@ -139,7 +141,7 @@ const string Logger::fProcessName = program_invocation_short_name; const string Logger::fProcessName = "?"; #endif -const unordered_map Logger::fVerbosityMap = +const unordered_map Logger::fVerbosityMap = { { "veryhigh", Verbosity::veryhigh }, { "high", Verbosity::high }, @@ -151,7 +153,7 @@ const unordered_map Logger::fVerbosityMap = { "LOW", Verbosity::low } }; -const unordered_map Logger::fSeverityMap = +const unordered_map Logger::fSeverityMap = { { "nolog", Severity::nolog }, { "NOLOG", Severity::nolog }, @@ -217,9 +219,20 @@ string Logger::VerbosityName(Verbosity verbosity) return fVerbosityNames.at(static_cast(verbosity)); } -Logger::Logger(Severity severity) - : fCurrentSeverity(severity) -{} +Logger::Logger(Severity severity, const string& file, const string& line, const string& func) +{ + chrono::time_point now = chrono::system_clock::now(); + size_t pos = file.rfind("/"); + + fMetaData.timestamp = chrono::system_clock::to_time_t(now); + fMetaData.us = chrono::duration_cast(now.time_since_epoch()) % 1000000; + fMetaData.process_name = fProcessName; + fMetaData.file = file.substr(pos + 1); + fMetaData.line = line; + fMetaData.func = func; + fMetaData.severity_name = fSeverityNames.at(static_cast(severity)); + fMetaData.severity = severity; +} void Logger::SetConsoleSeverity(const Severity severity) { @@ -259,9 +272,36 @@ void Logger::SetFileSeverity(const string& severityStr) } } +void Logger::SetCustomSeverity(const string& key, const Severity severity) +{ + fCustomSinks.at(key).first = severity; // TODO: range checks + UpdateMinSeverity(); +} + +void Logger::SetCustomSeverity(const string& key, const string& severityStr) +{ + if (fSeverityMap.count(severityStr)) + { + SetCustomSeverity(key, fSeverityMap.at(severityStr)); + } + else + { + LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'."; + SetCustomSeverity(key, Severity::info); + } +} + void Logger::UpdateMinSeverity() { fMinSeverity = (fConsoleSeverity <= fFileSeverity) ? fFileSeverity : fConsoleSeverity; + + for (auto& it : fCustomSinks) + { + if (fMinSeverity <= it.second.first) + { + fMinSeverity = it.second.first; + } + } } bool Logger::Logging(Severity severity) @@ -305,6 +345,7 @@ void Logger::SetConsoleColor(const bool colored) void Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName) { + lock_guard lock(fMtx); if (fFileStream.is_open()) { fFileStream.close(); @@ -356,6 +397,7 @@ void Logger::InitFileSink(const string& severityStr, const string& filename, boo void Logger::RemoveFileSink() { + lock_guard lock(fMtx); if (fFileStream.is_open()) { fFileStream.close(); @@ -364,47 +406,95 @@ void Logger::RemoveFileSink() bool Logger::LoggingToConsole() const { - return (fCurrentSeverity <= fConsoleSeverity && - fCurrentSeverity > Severity::nolog) || - fCurrentSeverity == Severity::fatal; + return (fMetaData.severity <= fConsoleSeverity && + fMetaData.severity > Severity::nolog) || + fMetaData.severity == Severity::fatal; } bool Logger::LoggingToFile() const { - return (fCurrentSeverity <= fFileSeverity && - fCurrentSeverity > Severity::nolog) || - fCurrentSeverity == Severity::fatal; + return (fMetaData.severity <= fFileSeverity && + fMetaData.severity > Severity::nolog) || + fMetaData.severity == Severity::fatal; } -ostringstream& Logger::Log(const string& file, const string& line, const string& func) +bool Logger::LoggingCustom(const Severity severity) const +{ + return (fMetaData.severity <= severity && + fMetaData.severity > Severity::nolog) || + fMetaData.severity == Severity::fatal; +} + +void Logger::OnFatal(function func) +{ + fFatalCallback = func; +} + +void Logger::AddCustomSink(const string& key, Severity severity, function func) +{ + lock_guard lock(fMtx); + if (fCustomSinks.count(key) == 0) + { + fCustomSinks.insert(make_pair(key, make_pair(severity, func))); + UpdateMinSeverity(); + } + else + { + cout << "Logger::AddCustomSink: sink '" << key << "' already exists, will not add again. Remove first with Logger::RemoveCustomSink(const string& key)" << endl; + } +} + +void Logger::AddCustomSink(const string& key, const string& severityStr, function func) +{ + if (fSeverityMap.count(severityStr)) + { + AddCustomSink(key, fSeverityMap.at(severityStr), func); + } + else + { + LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'."; + AddCustomSink(key, Severity::info, func); + } +} + +void Logger::RemoveCustomSink(const string& key) +{ + if (fCustomSinks.count(key) > 0) + { + fCustomSinks.erase(key); + UpdateMinSeverity(); + } + else + { + cout << "Logger::RemoveCustomSink: sink '" << key << "' doesn't exists, will not remove." << endl; + } +} + +ostringstream& Logger::Log() { - 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; char tsstr[32]; - if (!strftime(tsstr, sizeof(tsstr), "%H:%M:%S", localtime(&now_c))) + if (!strftime(tsstr, sizeof(tsstr), "%H:%M:%S", localtime(&(fMetaData.timestamp)))) { tsstr[0] = 'u'; } - if ((!fColored && LoggingToConsole()) || (fFileStream.is_open() && LoggingToFile())) + if ((!fColored && LoggingToConsole()) || LoggingToFile()) { if (fVerbosity >= Verbosity::high) { - fBWOut << "[" << fProcessName << "]" - << "[" << tsstr << "." << setw(6) << setfill('0') << ns.count() << "]"; + fBWOut << "[" << fMetaData.process_name << "]" + << "[" << tsstr << "." << setw(6) << setfill('0') << fMetaData.us.count() << "]"; } else if (fVerbosity == Verbosity::medium) { fBWOut << "[" << tsstr << "]"; } - fBWOut << "[" << fSeverityNames.at(static_cast(fCurrentSeverity)) << "]"; + fBWOut << "[" << fMetaData.severity_name << "]"; if (fVerbosity == Verbosity::veryhigh) { - fBWOut << "[" << file.substr(pos + 1) << ":" << line << ":" << func << "]"; + fBWOut << "[" << fMetaData.file << ":" << fMetaData.line << ":" << fMetaData.func << "]"; } fBWOut << " "; @@ -414,19 +504,19 @@ ostringstream& Logger::Log(const string& file, const string& line, const string& { if (fVerbosity >= Verbosity::high) { - fColorOut << "[" << ColorOut(Color::fgBlue, fProcessName) << "]" - << "[" << startColor(Color::fgCyan) << tsstr << "." << setw(6) << setfill('0') << ns.count() << endColor() << "]"; + fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.process_name) << "]" + << "[" << startColor(Color::fgCyan) << tsstr << "." << setw(6) << setfill('0') << fMetaData.us.count() << endColor() << "]"; } else if (fVerbosity == Verbosity::medium) { fColorOut << "[" << startColor(Color::fgCyan) << tsstr << endColor() << "]"; } - fColorOut << "[" << ColoredSeverityWriter(fCurrentSeverity) << "]"; + fColorOut << "[" << ColoredSeverityWriter(fMetaData.severity) << "]"; if (fVerbosity == Verbosity::veryhigh) { - fColorOut << "[" << ColorOut(Color::fgBlue, file.substr(pos + 1)) << ":" << ColorOut(Color::fgYellow, line) << ":" << ColorOut(Color::fgBlue, func) << "]"; + fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.file) << ":" << ColorOut(Color::fgYellow, fMetaData.line) << ":" << ColorOut(Color::fgBlue, fMetaData.func) << "]"; } fColorOut << " "; @@ -435,13 +525,17 @@ ostringstream& Logger::Log(const string& file, const string& line, const string& return fContent; } -void Logger::OnFatal(std::function func) -{ - fFatalCallback = func; -} - Logger::~Logger() noexcept(false) { + for (auto& it : fCustomSinks) + { + if (LoggingCustom(it.second.first)) + { + lock_guard lock(fMtx); + it.second.second(fContent.str(), fMetaData); + } + } + fContent << "\n"; // "\n" + flush instead of endl makes output thread safe. fBWOut << fContent.str(); @@ -461,13 +555,14 @@ Logger::~Logger() noexcept(false) if (LoggingToFile()) { + lock_guard lock(fMtx); if (fFileStream.is_open()) { fFileStream << fBWOut.str() << flush; } } - if (fCurrentSeverity == Severity::fatal) + if (fMetaData.severity == Severity::fatal) { if (fFatalCallback) { diff --git a/logger/Logger.h b/logger/Logger.h index 14a606a..1060ca4 100644 --- a/logger/Logger.h +++ b/logger/Logger.h @@ -18,10 +18,64 @@ #include #include #include +#include +#include +#include +#include // pair +#include // time_t namespace fair { +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:µS][severity] message +// veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message +enum class Verbosity : int +{ + low, + medium, + high, + veryhigh, + // backwards-compatibility: + LOW = low, + MEDIUM = medium, + HIGH = high, + VERYHIGH = veryhigh +}; + // non-std exception to avoid undesirable catches - fatal should exit in a way we want. class FatalException { @@ -43,59 +97,22 @@ class FatalException std::string fWhat; }; +struct LogMetaData +{ + std::time_t timestamp; + std::chrono::microseconds us; + std::string process_name; + std::string file; + std::string line; + std::string func; + std::string severity_name; + fair::Severity severity; +}; + 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); + Logger(Severity severity, const std::string& file, const std::string& line, const std::string& func); static void SetConsoleSeverity(const Severity severity); static void SetConsoleSeverity(const std::string& severityStr); @@ -103,6 +120,9 @@ class Logger static void SetFileSeverity(const Severity severity); static void SetFileSeverity(const std::string& severityStr); + static void SetCustomSeverity(const std::string& key, const Severity severity); + static void SetCustomSeverity(const std::string& key, const std::string& severityStr); + static bool Logging(const Severity severity); static void SetVerbosity(const Verbosity verbosity); @@ -118,19 +138,23 @@ class Logger 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 void OnFatal(std::function func); + + static void AddCustomSink(const std::string& key, Severity severity, std::function sink); + static void AddCustomSink(const std::string& key, const std::string& severityStr, std::function sink); + static void RemoveCustomSink(const std::string& key); + + std::ostringstream& Log(); 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); - virtual ~Logger() noexcept(false); private: - Severity fCurrentSeverity; + LogMetaData fMetaData; std::ostringstream fContent; std::ostringstream fColorOut; @@ -146,9 +170,12 @@ class Logger static Verbosity fVerbosity; static std::function fFatalCallback; + static std::unordered_map>> fCustomSinks; + static std::mutex fMtx; bool LoggingToConsole() const; bool LoggingToFile() const; + bool LoggingCustom(const Severity) const; static void UpdateMinSeverity(); }; @@ -159,13 +186,13 @@ class Logger #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__) + for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \ + fair::Logger(fair::Severity::severity, __FILE__, CONVERTTOSTRING(__LINE__), __FUNCTION__).Log() // 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) + fair::Logger(severity, file, line, function).Log() #define LOG_IF(severity, condition) \ for (bool fairLOggerunLikelyvariable2 = false; condition && !fairLOggerunLikelyvariable2; fairLOggerunLikelyvariable2 = true) \ diff --git a/logger/loggerTest.cxx b/logger/loggerTest.cxx index 35a73a3..fd37e12 100644 --- a/logger/loggerTest.cxx +++ b/logger/loggerTest.cxx @@ -35,35 +35,35 @@ void printEverySeverity() LOG(trace) << "trace message " << i++; } -void printAllVerbositiesWithSeverity(Logger::Severity sev) +void printAllVerbositiesWithSeverity(Severity sev) { Logger::SetConsoleSeverity(sev); - cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl; - Logger::SetVerbosity(Logger::Verbosity::low); + cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl; + Logger::SetVerbosity(Verbosity::low); printEverySeverity(); - cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl; - Logger::SetVerbosity(Logger::Verbosity::medium); + cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl; + Logger::SetVerbosity(Verbosity::medium); printEverySeverity(); - cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl; - Logger::SetVerbosity(Logger::Verbosity::high); + cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl; + Logger::SetVerbosity(Verbosity::high); printEverySeverity(); - cout << endl << ">>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl; - Logger::SetVerbosity(Logger::Verbosity::veryhigh); + cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl; + Logger::SetVerbosity(Verbosity::veryhigh); printEverySeverity(); } -void silentlyPrintAllVerbositiesWithSeverity(Logger::Severity sev) +void silentlyPrintAllVerbositiesWithSeverity(Severity sev) { Logger::SetConsoleSeverity(sev); - Logger::SetVerbosity(Logger::Verbosity::low); + Logger::SetVerbosity(Verbosity::low); printEverySeverity(); - Logger::SetVerbosity(Logger::Verbosity::medium); + Logger::SetVerbosity(Verbosity::medium); printEverySeverity(); - Logger::SetVerbosity(Logger::Verbosity::high); + Logger::SetVerbosity(Verbosity::high); printEverySeverity(); - Logger::SetVerbosity(Logger::Verbosity::veryhigh); + Logger::SetVerbosity(Verbosity::veryhigh); printEverySeverity(); } @@ -71,49 +71,49 @@ int main() { Logger::SetConsoleColor(true); - cout << "testing severities..." << endl; + cout << "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); + printAllVerbositiesWithSeverity(Severity::trace); + printAllVerbositiesWithSeverity(Severity::debug4); + printAllVerbositiesWithSeverity(Severity::debug3); + printAllVerbositiesWithSeverity(Severity::debug2); + printAllVerbositiesWithSeverity(Severity::debug1); + printAllVerbositiesWithSeverity(Severity::debug); + printAllVerbositiesWithSeverity(Severity::info); + printAllVerbositiesWithSeverity(Severity::state); + printAllVerbositiesWithSeverity(Severity::warn); + printAllVerbositiesWithSeverity(Severity::error); + printAllVerbositiesWithSeverity(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 << "cout: resetting severity to 'info' and verbosity to 'medium'" << endl; + Logger::SetConsoleSeverity(Severity::info); + Logger::SetVerbosity(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; + cout << "cout: is logging trace: " << fair::Logger::Logging(Severity::trace) << endl; + cout << "cout: is logging debug4: " << fair::Logger::Logging(Severity::debug) << endl; + cout << "cout: is logging debug3: " << fair::Logger::Logging(Severity::debug) << endl; + cout << "cout: is logging debug2: " << fair::Logger::Logging(Severity::debug) << endl; + cout << "cout: is logging debug1: " << fair::Logger::Logging(Severity::debug) << endl; + cout << "cout: is logging debug: " << fair::Logger::Logging(Severity::debug) << endl; + cout << "cout: is logging info: " << fair::Logger::Logging(Severity::info) << endl; + cout << "cout: is logging state: " << fair::Logger::Logging(Severity::state) << endl; + cout << "cout: is logging warn: " << fair::Logger::Logging(Severity::warn) << endl; + cout << "cout: is logging error: " << fair::Logger::Logging(Severity::error) << endl; + cout << "cout: is logging fatal: " << fair::Logger::Logging(Severity::fatal) << endl; + cout << "cout: is logging nolog: " << fair::Logger::Logging(Severity::nolog) << endl; for (int i = 0; i < 1000000; ++i) { - silentlyPrintAllVerbositiesWithSeverity(Logger::Severity::nolog); + silentlyPrintAllVerbositiesWithSeverity(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 << "cout: resetting severity to 'trace' and verbosity to 'veryhigh'" << endl; + Logger::SetConsoleSeverity(Severity::trace); + Logger::SetVerbosity(Verbosity::veryhigh); cout << endl; - cout << "testing conditional logging..." << endl; + cout << "cout: testing conditional logging..." << endl; int x = 0; LOG(info) << "x = " << x << " (initial)"; LOG_IF(info, (x == 0)) << "incrementing x to " << ++x; @@ -122,13 +122,45 @@ int main() LOG(info) << "x = " << x << " (after conditional increment)"; cout << endl; - cout << "resetting severity to 'nolog'" << endl; - Logger::SetConsoleSeverity(Logger::Severity::nolog); + cout << "cout: resetting severity to 'nolog'" << endl; + Logger::SetConsoleSeverity(Severity::nolog); - cout << "----------------------------" << endl; - cout << "open log file with severity 'error'" << endl; - Logger::InitFileSink(Logger::Severity::error, "test_log", true); + cout << "cout: ----------------------------" << endl; + cout << "cout: open log file with severity 'error'" << endl; + Logger::InitFileSink(Severity::error, "test_log", true); printEverySeverity(); + cout << "cout: closing log file" << endl; + Logger::RemoveFileSink(); + + + cout << "cout: resetting severity to 'nolog'" << endl; + Logger::SetConsoleSeverity(Severity::nolog); + cout << "cout: ----------------------------" << endl; + cout << "cout: adding custom sink with error severity" << endl << endl; + + Logger::AddCustomSink("CustomSink", "error", [](const string& content, const LogMetaData& metadata) + { + cout << "CustomSink: content: " << content << endl; + + cout << "CustomSink: available metadata: " << endl; + cout << "CustomSink: \tstd::time_t timestamp: " << metadata.timestamp << endl; + cout << "CustomSink: \tstd::chrono::microseconds us: " << metadata.us.count() << endl; + cout << "CustomSink: \tstd::string process_name: " << metadata.process_name << endl; + cout << "CustomSink: \tstd::string file: " << metadata.file << endl; + cout << "CustomSink: \tstd::string line: " << metadata.line << endl; + cout << "CustomSink: \tstd::string func: " << metadata.func << endl; + cout << "CustomSink: \tstd::string severity_name: " << metadata.severity_name << endl; + cout << "CustomSink: \tfair::Severity severity: " << static_cast(metadata.severity) << endl; + }); + + printEverySeverity(); + + cout << endl << "cout: removing custom sink with info severity" << endl; + + Logger::AddCustomSink("CustomSink", Severity::error, [](const string& content, const LogMetaData& metadata){}); + Logger::RemoveCustomSink("CustomSink"); + Logger::RemoveCustomSink("bla"); + return 0; }