diff --git a/src/log.cpp b/src/log.cpp index 6dbc43372..98939c9bf 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -34,6 +34,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif +#if !defined(_WIN32) +#include // isatty +#endif + #include #include #include @@ -104,21 +108,19 @@ thread_local LogStream dout_con(trace_target); static unsigned int g_level_to_android[] = { ANDROID_LOG_INFO, // LL_NONE - //ANDROID_LOG_FATAL, ANDROID_LOG_ERROR, // LL_ERROR ANDROID_LOG_WARN, // LL_WARNING - ANDROID_LOG_WARN, // LL_ACTION - //ANDROID_LOG_INFO, + ANDROID_LOG_INFO, // LL_ACTION ANDROID_LOG_DEBUG, // LL_INFO ANDROID_LOG_VERBOSE, // LL_VERBOSE ANDROID_LOG_VERBOSE, // LL_TRACE }; -void AndroidLogOutput::logRaw(LogLevel lev, const std::string &line) { +void AndroidLogOutput::logRaw(LogLevel lev, const std::string &line) +{ static_assert(ARRLEN(g_level_to_android) == LL_MAX, "mismatch between android and internal loglevels"); - __android_log_print(g_level_to_android[lev], - PROJECT_NAME_C, "%s", line.c_str()); + __android_log_write(g_level_to_android[lev], PROJECT_NAME_C, line.c_str()); } #endif @@ -156,9 +158,7 @@ void Logger::addOutput(ILogOutput *out) void Logger::addOutput(ILogOutput *out, LogLevel lev) { - MutexAutoLock lock(m_mutex); - m_outputs[lev].push_back(out); - m_has_outputs[lev] = true; + addOutputMasked(out, LOGLEVEL_TO_MASKLEVEL(lev)); } void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask) @@ -187,9 +187,7 @@ LogLevelMask Logger::removeOutput(ILogOutput *out) MutexAutoLock lock(m_mutex); LogLevelMask ret_mask = 0; for (size_t i = 0; i < LL_MAX; i++) { - std::vector::iterator it; - - it = std::find(m_outputs[i].begin(), m_outputs[i].end(), out); + auto it = std::find(m_outputs[i].begin(), m_outputs[i].end(), out); if (it != m_outputs[i].end()) { ret_mask |= LOGLEVEL_TO_MASKLEVEL(i); m_outputs[i].erase(it); @@ -218,9 +216,9 @@ void Logger::deregisterThread() m_thread_names.erase(id); } -const std::string Logger::getLevelLabel(LogLevel lev) +const char *Logger::getLevelLabel(LogLevel lev) { - static const std::string names[] = { + static const char *names[] = { "", "ERROR", "WARNING", @@ -229,26 +227,29 @@ const std::string Logger::getLevelLabel(LogLevel lev) "VERBOSE", "TRACE", }; - assert(lev < LL_MAX && lev >= 0); static_assert(ARRLEN(names) == LL_MAX, "mismatch between loglevel names and enum"); + assert(lev < LL_MAX && lev >= 0); return names[lev]; } LogColor Logger::color_mode = LOG_COLOR_AUTO; -const std::string Logger::getThreadName() +const std::string &Logger::getThreadName() { - std::map::const_iterator it; - std::thread::id id = std::this_thread::get_id(); - it = m_thread_names.find(id); + + auto it = m_thread_names.find(id); if (it != m_thread_names.end()) return it->second; - std::ostringstream os; - os << "#0x" << std::hex << id; - return os.str(); + thread_local std::string fallback_name; + if (fallback_name.empty()) { + std::ostringstream os; + os << "#0x" << std::hex << id; + fallback_name = os.str(); + } + return fallback_name; } void Logger::log(LogLevel lev, const std::string &text) @@ -256,13 +257,15 @@ void Logger::log(LogLevel lev, const std::string &text) if (isLevelSilenced(lev)) return; - const std::string thread_name = getThreadName(); - const std::string label = getLevelLabel(lev); + const std::string &thread_name = getThreadName(); + const char *label = getLevelLabel(lev); const std::string timestamp = getTimestamp(); - std::ostringstream os(std::ios_base::binary); - os << timestamp << ": " << label << "[" << thread_name << "]: " << text; - logToOutputs(lev, os.str(), timestamp, thread_name, text); + std::string line = timestamp; + line.append(": ").append(label).append("[").append(thread_name) + .append("]: ").append(text); + + logToOutputs(lev, line, timestamp, thread_name, text); } void Logger::logRaw(LogLevel lev, const std::string &text) @@ -320,6 +323,17 @@ void FileLogOutput::setFile(const std::string &filename, s64 file_size_max) "-------------\n" << std::endl; } +StreamLogOutput::StreamLogOutput(std::ostream &stream) : + m_stream(stream) +{ +#if !defined(_WIN32) + if (&stream == &std::cout) + is_tty = isatty(STDOUT_FILENO); + else if (&stream == &std::cerr) + is_tty = isatty(STDERR_FILENO); +#endif +} + void StreamLogOutput::logRaw(LogLevel lev, const std::string &line) { bool colored_message = (Logger::color_mode == LOG_COLOR_ALWAYS) || diff --git a/src/log.h b/src/log.h index f92d17737..9ac4e5767 100644 --- a/src/log.h +++ b/src/log.h @@ -26,9 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#if !defined(_WIN32) // POSIX - #include -#endif #include "threading/mutex_auto_lock.h" #include "util/basic_macros.h" #include "util/stream.h" @@ -73,7 +70,7 @@ public: void logRaw(LogLevel lev, const std::string &text); static LogLevel stringToLevel(const std::string &name); - static const std::string getLevelLabel(LogLevel lev); + static const char *getLevelLabel(LogLevel lev); bool hasOutput(LogLevel level) { return m_has_outputs[level].load(std::memory_order_relaxed); @@ -91,7 +88,7 @@ private: const std::string &time, const std::string &thread_name, const std::string &payload_text); - const std::string getThreadName(); + const std::string &getThreadName(); std::vector m_outputs[LL_MAX]; std::atomic m_has_outputs[LL_MAX]; @@ -120,16 +117,7 @@ public: class StreamLogOutput : public ICombinedLogOutput { public: - StreamLogOutput(std::ostream &stream) : - m_stream(stream) - { -#if !defined(_WIN32) - if (&stream == &std::cout) - is_tty = isatty(STDOUT_FILENO); - else if (&stream == &std::cerr) - is_tty = isatty(STDERR_FILENO); -#endif - } + StreamLogOutput(std::ostream &stream); void logRaw(LogLevel lev, const std::string &line); diff --git a/src/terminal_chat_console.cpp b/src/terminal_chat_console.cpp index b1512d8f3..752d7c7b8 100644 --- a/src/terminal_chat_console.cpp +++ b/src/terminal_chat_console.cpp @@ -426,7 +426,7 @@ void TerminalChatConsole::step(int ch) printw("[ESC] Toggle ESC mode |" " [CTRL+C] Shut down |" " (L) in-, (l) decrease loglevel %s", - Logger::getLevelLabel((LogLevel) m_log_level).c_str()); + Logger::getLevelLabel((LogLevel) m_log_level)); } refresh();