feat: entry meta functions

possibility to modify the metadata string of each Entry
This commit is contained in:
Oliver 2022-09-04 21:58:50 +02:00
parent 6ecbc406d7
commit a59b5bbace
Signed by untrusted user: okaestne
GPG Key ID: 06A81B143EA9588F
3 changed files with 59 additions and 21 deletions

51
Log.cpp
View File

@ -137,31 +137,33 @@ void log(Level lvl, std::stringbuf* strb) {
} }
} }
LeveledSink fatal(Level::fatal); LeveledSink fatal{Level::fatal};
LeveledSink error(Level::error); LeveledSink error{Level::error};
LeveledSink warn(Level::warn); LeveledSink warn{Level::warn};
LeveledSink note(Level::note); LeveledSink note{Level::note};
LeveledSink info(Level::info); LeveledSink info{Level::info};
LeveledSink debug(Level::debug); LeveledSink debug{Level::debug};
LeveledSink trace(Level::trace); LeveledSink trace{Level::trace};
/* /*
* class Entry * class Entry
*/ */
Entry::Entry(Level lvl) : lvl(lvl) { Entry::Entry(Level lvl) : lvl{lvl} {
addMetadataHeader(); for(auto metafunc : entryMetaFunctions) {
metafunc(ss, *this);
}
} }
Entry::~Entry() { Entry::~Entry() {
log(lvl, ss.rdbuf()); log(lvl, ss.rdbuf());
} }
void Entry::addMetadataHeader() { std::vector<Entry::MetaFunction> entryMetaFunctions;
static const char* LevelTag[] = {"", "[FATAL] ", "[ERROR] ", "[WARN ] ",
"[NOTE ] ", "[INFO ] ", "[DEBUG] ", "[TRACE] "}; std::ostream& defaultEntryMetaTime(std::ostream& os, const Entry& e) {
(void) e; // unused
// datetime
using namespace std::chrono; using namespace std::chrono;
auto now = system_clock::to_time_t(system_clock::now()); auto now = system_clock::to_time_t(system_clock::now());
auto tm = *std::localtime(&now); auto tm = *std::localtime(&now);
@ -169,16 +171,31 @@ void Entry::addMetadataHeader() {
// MinGW doesn't support the ISO8601 formatting characters like "%F" and "%T" // MinGW doesn't support the ISO8601 formatting characters like "%F" and "%T"
// ref: https://sourceforge.net/p/mingw-w64/bugs/793/ // ref: https://sourceforge.net/p/mingw-w64/bugs/793/
// Therefore, use a more verbose time string // Therefore, use a more verbose time string
ss << "[" << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << "]"; return os << "[" << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << "]";
}
// log level std::ostream& defaultEntryMetaLevel(std::ostream& os, const Entry& e) {
ss << LevelTag[static_cast<int>(lvl)]; static const char* LevelTag[] = {
"", "[FATAL]", "[ERROR]", "[WARN ]", "[NOTE ]", "[INFO ]", "[DEBUG]", "[TRACE]"
};
return os << LevelTag[static_cast<int>(e.getLevel())];
} }
void init() { void init() {
// add default console logger // add default console logger
if (outputs.empty()) if (outputs.empty())
outputs.push_back(new ConsoleOutput()); outputs.push_back(new ConsoleOutput());
// set default entry metadata printing functions
auto space = [](std::ostream& os, const Entry& e) -> std::ostream& {
(void) e;
return os << ' ';
};
entryMetaFunctions = {
defaultEntryMetaTime,
defaultEntryMetaLevel,
space
};
} }
void stop() { void stop() {
@ -203,6 +220,4 @@ void setColoredOutput(bool enabled) {
((ConsoleOutput*) outputs.at(0))->setColoredOutput(enabled); // has to exist ((ConsoleOutput*) outputs.at(0))->setColoredOutput(enabled); // has to exist
} }
LeveledSink::LeveledSink(Level level) : level(level) {}
} // namespace Log } // namespace Log

19
Log.h
View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <functional>
#include <sstream> // std::stringstream (buffer for log entries) #include <sstream> // std::stringstream (buffer for log entries)
#include <string> #include <string>
#include <vector>
#ifndef LOG_USEMUTEX #ifndef LOG_USEMUTEX
#define LOG_USEMUTEX 0 #define LOG_USEMUTEX 0
@ -27,7 +29,7 @@ void setColoredOutput(bool enabled);
class Entry { class Entry {
private: private:
std::stringstream ss; std::stringstream ss;
Level lvl; const Level lvl;
void addMetadataHeader(); void addMetadataHeader();
@ -36,21 +38,32 @@ public:
Entry(Entry&&) = default; Entry(Entry&&) = default;
~Entry(); ~Entry();
Level getLevel() const {
return lvl;
}
using MetaFunction = std::function<std::ostream&(std::ostream&, const Entry&)>;
template <typename T> Entry& operator<<(const T& msg) { template <typename T> Entry& operator<<(const T& msg) {
ss << msg; ss << msg;
return *this; return *this;
} }
}; };
extern std::vector<Entry::MetaFunction> entryMetaFunctions;
std::ostream& defaultEntryMetaTime(std::ostream&, const Entry&);
std::ostream& defaultEntryMetaLevel(std::ostream&, const Entry&);
class LeveledSink { class LeveledSink {
private: private:
Level level; Level level;
public: public:
LeveledSink(Level level); LeveledSink(Level level) : level{level} {};
template <typename T> Entry operator<<(const T& msg) { template <typename T> Entry operator<<(const T& msg) {
Entry entry(level); Entry entry{level};
entry << msg; entry << msg;
return entry; return entry;
} }

View File

@ -44,6 +44,16 @@ int main() {
// log streams + colors // log streams + colors
Log::setColoredOutput(true); Log::setColoredOutput(true);
Log::setConsoleLogLevel(Log::Level::trace); Log::setConsoleLogLevel(Log::Level::trace);
// add entry meta function
Log::entryMetaFunctions.insert(
Log::entryMetaFunctions.cend() - 1,
[](std::ostream& os, const Log::Entry& e) -> std::ostream& {
(void) e;
return os << "[banana]";
}
);
std::cout << "=== Log level debug ===" << std::endl; std::cout << "=== Log level debug ===" << std::endl;
Log::trace << "trace msg @Lvl trace; " << 42 << "; " << 3.14159; Log::trace << "trace msg @Lvl trace; " << 42 << "; " << 3.14159;
Log::debug << "dbg msg @Lvl trace; " << 42 << "; " << 3.14159; Log::debug << "dbg msg @Lvl trace; " << 42 << "; " << 3.14159;