27 const std::string &msg,
28 const std::map<std::string, std::any> *details) {
29 std::scoped_lock<std::mutex> lock(
mutex);
30 logImpl(level, subsystem, msg, details);
35 minLevel(minLevel), outStream(std::cout), errorStream(std::cerr) {}
38 const std::string &msg,
39 const std::map<std::string, std::any> *details) {
43 unsigned indentSpaces = 0;
68 if (!subsystem.empty()) {
69 os <<
"[" << subsystem <<
"] ";
70 indentSpaces += subsystem.size() + 3;
72 os << msg << std::endl;
75 std::string indent(indentSpaces,
' ');
76 for (
const auto &
detail : *details)
87 const std::string &msg,
88 const std::map<std::string, std::any> *details) {
92 unsigned indentSpaces = 0;
96 fmt::print(os, fmt::fg(fmt::color::red),
"[ ERROR] ");
100 fmt::print(os, fmt::fg(fmt::color::yellow),
"[WARNING] ");
104 fmt::print(os, fmt::fg(fmt::color::dark_green),
"[ INFO] ");
108 fmt::print(os, fmt::fg(fmt::color::beige),
"[ DEBUG] ");
112 fmt::print(os, fmt::fg(fmt::color::burly_wood),
"[ TRACE] ");
117 if (!subsystem.empty()) {
118 fmt::print(os,
"[{}]", subsystem);
119 indentSpaces += subsystem.size() + 3;
121 fmt::print(os,
" {}", msg);
122 fmt::print(os,
"\n");
125 std::string indent(indentSpaces,
' ');
126 for (
const auto &
detail : *details)
127 fmt::print(os,
"{} {}: {}\n", indent,
detail.first,
133 if (value.type() ==
typeid(std::string))
134 return std::any_cast<std::string>(value);
135 if (value.type() ==
typeid(
int))
136 return std::to_string(std::any_cast<int>(value));
137 if (value.type() ==
typeid(
long))
138 return std::to_string(std::any_cast<long>(value));
139 if (value.type() ==
typeid(
unsigned))
140 return std::to_string(std::any_cast<unsigned>(value));
141 if (value.type() ==
typeid(
unsigned long))
142 return std::to_string(std::any_cast<unsigned long>(value));
143 if (value.type() ==
typeid(
bool))
144 return std::any_cast<bool>(value) ?
"true" :
"false";
145 if (value.type() ==
typeid(
double))
146 return std::to_string(std::any_cast<double>(value));
147 if (value.type() ==
typeid(
float))
148 return std::to_string(std::any_cast<float>(value));
149 if (value.type() ==
typeid(
const char *))
150 return std::string(std::any_cast<const char *>(value));
151 if (value.type() ==
typeid(
char))
152 return std::string(1, std::any_cast<char>(value));
154 return std::any_cast<MessageData>(value).toHex();
ConsoleLogger(Level minLevel)
Create a stream logger that logs to stdout, stderr.
Level minLevel
The minimum log level to emit.
void logImpl(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details) override
Subclasses must implement this method to log messages.
A logical chunk of data representing serialized data.
Level minLevel
The minimum log level to emit.
void logImpl(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details) override
Subclasses must implement this method to log messages.
std::ostream & outStream
Everything except errors goes here.
std::ostream & errorStream
Just for errors.
StreamLogger(Level minLevel, std::ostream &out, std::ostream &error)
Create a stream logger that logs to the given output stream and error output stream.
A thread-safe logger which calls functions implemented by subclasses.
std::mutex mutex
Mutex to protect the stream from interleaved logging writes.
virtual void logImpl(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details)=0
Subclasses must implement this method to log messages.
void log(Level level, const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details) override final
Grabs the lock and calls logImpl.
std::string toString(const std::any &a)
'Stringify' a std::any. This is used to log std::any values by some loggers.