Logger: Do string formatting before lock and only if LogLevel is loggable

This commit is contained in:
Kae 2023-08-01 20:23:05 +10:00
parent 9ba734ea14
commit 678a461904
2 changed files with 36 additions and 12 deletions

View File

@ -16,6 +16,7 @@ LogSink::~LogSink() {}
void LogSink::setLevel(LogLevel level) { void LogSink::setLevel(LogLevel level) {
m_level = level; m_level = level;
Logger::refreshLoggable();
} }
LogLevel LogSink::level() { LogLevel LogSink::level() {
@ -44,11 +45,13 @@ void FileLogSink::log(char const* msg, LogLevel level) {
void Logger::addSink(LogSinkPtr s) { void Logger::addSink(LogSinkPtr s) {
MutexLocker locker(s_mutex); MutexLocker locker(s_mutex);
s_sinks.insert(s); s_sinks.insert(s);
refreshLoggable();
} }
void Logger::removeSink(LogSinkPtr s) { void Logger::removeSink(LogSinkPtr s) {
MutexLocker locker(s_mutex); MutexLocker locker(s_mutex);
s_sinks.erase(s); s_sinks.erase(s);
refreshLoggable();
} }
LogSinkPtr Logger::stdoutSink() { LogSinkPtr Logger::stdoutSink() {
@ -59,19 +62,36 @@ LogSinkPtr Logger::stdoutSink() {
void Logger::removeStdoutSink() { void Logger::removeStdoutSink() {
MutexLocker locker(s_mutex); MutexLocker locker(s_mutex);
s_sinks.erase(s_stdoutSink); s_sinks.erase(s_stdoutSink);
refreshLoggable();
} }
void Logger::log(LogLevel level, char const* msg) { void Logger::log(LogLevel level, char const* msg) {
if (loggable(level)) {
MutexLocker locker(s_mutex); MutexLocker locker(s_mutex);
for (auto const& l : s_sinks) { for (auto const& l : s_sinks) {
if (l->level() <= level) if (l->level() <= level)
l->log(msg, level); l->log(msg, level);
} }
}
}
bool Logger::loggable(LogLevel level) {
return s_loggable[(int)level];
}
void Logger::refreshLoggable() {
Array<bool, 4> loggable;
for (auto const& l : s_sinks) {
for (auto i = (size_t)l->level(); i != loggable.size(); ++i)
loggable[i] = true;
}
MutexLocker locker(s_mutex);
s_loggable = loggable;
} }
shared_ptr<StdoutLogSink> Logger::s_stdoutSink = make_shared<StdoutLogSink>(); shared_ptr<StdoutLogSink> Logger::s_stdoutSink = make_shared<StdoutLogSink>();
HashSet<LogSinkPtr> Logger::s_sinks{s_stdoutSink}; HashSet<LogSinkPtr> Logger::s_sinks{s_stdoutSink};
Array<bool, 4> Logger::s_loggable = Array<bool, 4>::filled(false);
Mutex Logger::s_mutex; Mutex Logger::s_mutex;
String LogMap::getValue(String const& key) { String LogMap::getValue(String const& key) {

View File

@ -81,9 +81,13 @@ public:
template <typename... Args> template <typename... Args>
static void error(char const* msg, Args const&... args); static void error(char const* msg, Args const&... args);
static bool loggable(LogLevel level);
static void refreshLoggable();
private: private:
static shared_ptr<StdoutLogSink> s_stdoutSink; static shared_ptr<StdoutLogSink> s_stdoutSink;
static HashSet<LogSinkPtr> s_sinks; static HashSet<LogSinkPtr> s_sinks;
static Array<bool, 4> s_loggable;
static Mutex s_mutex; static Mutex s_mutex;
}; };
@ -152,13 +156,13 @@ private:
template <typename... Args> template <typename... Args>
void Logger::logf(LogLevel level, char const* msg, Args const&... args) { void Logger::logf(LogLevel level, char const* msg, Args const&... args) {
if (loggable(level)) {
std::string output = strf(msg, args...);
MutexLocker locker(s_mutex); MutexLocker locker(s_mutex);
Maybe<std::string> output;
for (auto const& l : s_sinks) { for (auto const& l : s_sinks) {
if (l->level() <= level) { if (l->level() <= level) {
if (!output) l->log(output.c_str(), level);
output = strf(msg, args...); }
l->log(output->c_str(), level);
} }
} }
} }