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 outStream(std::cout), errorStream(std::cerr) {}
38 const std::string &msg,
39 const std::map<std::string, std::any> *details) {
43 unsigned indentSpaces = 0;
64 if (!subsystem.empty()) {
65 os <<
"[" << subsystem <<
"] ";
66 indentSpaces += subsystem.size() + 3;
68 os << msg << std::endl;
71 std::string indent(indentSpaces,
' ');
72 for (
const auto &
detail : *details)
82 const std::string &msg,
83 const std::map<std::string, std::any> *details) {
87 unsigned indentSpaces = 0;
91 fmt::print(os, fmt::fg(fmt::color::red),
"[ ERROR] ");
95 fmt::print(os, fmt::fg(fmt::color::yellow),
"[WARNING] ");
99 fmt::print(os, fmt::fg(fmt::color::dark_green),
"[ INFO] ");
103 fmt::print(os, fmt::fg(fmt::color::beige),
"[ DEBUG] ");
108 if (!subsystem.empty()) {
109 fmt::print(os,
"[{}]", subsystem);
110 indentSpaces += subsystem.size() + 3;
112 fmt::print(os,
" {}", msg);
113 fmt::print(os,
"\n");
116 std::string indent(indentSpaces,
' ');
117 for (
const auto &
detail : *details)
118 fmt::print(os,
"{} {}: {}\n", indent,
detail.first,
124 if (value.type() ==
typeid(std::string))
125 return std::any_cast<std::string>(value);
126 if (value.type() ==
typeid(
int))
127 return std::to_string(std::any_cast<int>(value));
128 if (value.type() ==
typeid(
long))
129 return std::to_string(std::any_cast<long>(value));
130 if (value.type() ==
typeid(
unsigned))
131 return std::to_string(std::any_cast<unsigned>(value));
132 if (value.type() ==
typeid(
unsigned long))
133 return std::to_string(std::any_cast<unsigned long>(value));
134 if (value.type() ==
typeid(
bool))
135 return std::any_cast<bool>(value) ?
"true" :
"false";
136 if (value.type() ==
typeid(
double))
137 return std::to_string(std::any_cast<double>(value));
138 if (value.type() ==
typeid(
float))
139 return std::to_string(std::any_cast<float>(value));
140 if (value.type() ==
typeid(
const char *))
141 return std::string(std::any_cast<const char *>(value));
142 if (value.type() ==
typeid(
char))
143 return std::string(1, std::any_cast<char>(value));
145 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.