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 error(Level::error);
LeveledSink warn(Level::warn);
LeveledSink note(Level::note);
LeveledSink info(Level::info);
LeveledSink debug(Level::debug);
LeveledSink trace(Level::trace);
LeveledSink fatal{Level::fatal};
LeveledSink error{Level::error};
LeveledSink warn{Level::warn};
LeveledSink note{Level::note};
LeveledSink info{Level::info};
LeveledSink debug{Level::debug};
LeveledSink trace{Level::trace};
/*
* class Entry
*/
Entry::Entry(Level lvl) : lvl(lvl) {
addMetadataHeader();
Entry::Entry(Level lvl) : lvl{lvl} {
for(auto metafunc : entryMetaFunctions) {
metafunc(ss, *this);
}
}
Entry::~Entry() {
log(lvl, ss.rdbuf());
}
void Entry::addMetadataHeader() {
static const char* LevelTag[] = {"", "[FATAL] ", "[ERROR] ", "[WARN ] ",
"[NOTE ] ", "[INFO ] ", "[DEBUG] ", "[TRACE] "};
std::vector<Entry::MetaFunction> entryMetaFunctions;
std::ostream& defaultEntryMetaTime(std::ostream& os, const Entry& e) {
(void) e; // unused
// datetime
using namespace std::chrono;
auto now = system_clock::to_time_t(system_clock::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"
// ref: https://sourceforge.net/p/mingw-w64/bugs/793/
// 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
ss << LevelTag[static_cast<int>(lvl)];
std::ostream& defaultEntryMetaLevel(std::ostream& os, const Entry& e) {
static const char* LevelTag[] = {
"", "[FATAL]", "[ERROR]", "[WARN ]", "[NOTE ]", "[INFO ]", "[DEBUG]", "[TRACE]"
};
return os << LevelTag[static_cast<int>(e.getLevel())];
}
void init() {
// add default console logger
if (outputs.empty())
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() {
@ -203,6 +220,4 @@ void setColoredOutput(bool enabled) {
((ConsoleOutput*) outputs.at(0))->setColoredOutput(enabled); // has to exist
}
LeveledSink::LeveledSink(Level level) : level(level) {}
} // namespace Log

19
Log.h
View File

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

View File

@ -44,6 +44,16 @@ int main() {
// log streams + colors
Log::setColoredOutput(true);
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;
Log::trace << "trace msg @Lvl trace; " << 42 << "; " << 3.14159;
Log::debug << "dbg msg @Lvl trace; " << 42 << "; " << 3.14159;