X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flog.h;h=219255d9abfd6af92f042efa32ea0df3946d56e2;hb=9762650f978cc7bae78861b70a051b26cc5e2dc6;hp=bd223927a6c18158427ede259a9799424e9030c0;hpb=9527984dbcfc0a6cc7aa0470430cb6c3aa4103ba;p=minetest.git diff --git a/src/log.h b/src/log.h index bd223927a..219255d9a 100644 --- a/src/log.h +++ b/src/log.h @@ -20,83 +20,197 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef LOG_HEADER #define LOG_HEADER +#include +#include #include +#include +#include "threads.h" +#include "irrlichttypes.h" + +class ILogOutput; + +enum LogLevel { + LL_NONE, // Special level that is always printed + LL_ERROR, + LL_WARNING, + LL_ACTION, // In-game actions + LL_INFO, + LL_VERBOSE, + LL_MAX, +}; -/* - Use this for logging everything. +typedef u8 LogLevelMask; +#define LOGLEVEL_TO_MASKLEVEL(x) (1 << x) - If you need to explicitly print something, use dstream or cout or cerr. -*/ +class Logger { +public: + void addOutput(ILogOutput *out); + void addOutput(ILogOutput *out, LogLevel lev); + void addOutputMasked(ILogOutput *out, LogLevelMask mask); + void addOutputMaxLevel(ILogOutput *out, LogLevel lev); + LogLevelMask removeOutput(ILogOutput *out); + void setLevelSilenced(LogLevel lev, bool silenced); + + void registerThread(const std::string &name); + void deregisterThread(); + + void log(LogLevel lev, const std::string &text); + // Logs without a prefix + void logRaw(LogLevel lev, const std::string &text); + + void setTraceEnabled(bool enable) { m_trace_enabled = enable; } + bool getTraceEnabled() { return m_trace_enabled; } + + static LogLevel stringToLevel(const std::string &name); + static const std::string getLevelLabel(LogLevel lev); + +private: + void logToOutputsRaw(LogLevel, const std::string &line); + void logToOutputs(LogLevel, const std::string &combined, + const std::string &time, const std::string &thread_name, + const std::string &payload_text); + + const std::string getThreadName(); + + std::vector m_outputs[LL_MAX]; + + // Should implement atomic loads and stores (even though it's only + // written to when one thread has access currently). + // Works on all known architectures (x86, ARM, MIPS). + volatile bool m_silenced_levels[LL_MAX]; + std::map m_thread_names; + mutable Mutex m_mutex; + bool m_trace_enabled; +}; -enum LogMessageLevel { - LMT_ERROR, /* Something failed ("invalid map data on disk, block (2,2,1)") */ - LMT_ACTION, /* In-game actions ("celeron55 placed block at (12,4,-5)") */ - LMT_INFO, /* More deep info ("saving map on disk (only_modified=true)") */ - LMT_VERBOSE, /* Flood-style ("loaded block (2,2,2) from disk") */ - LMT_NUM_VALUES, +class ILogOutput { +public: + virtual void logRaw(LogLevel, const std::string &line) = 0; + virtual void log(LogLevel, const std::string &combined, + const std::string &time, const std::string &thread_name, + const std::string &payload_text) = 0; }; -class ILogOutput -{ +class ICombinedLogOutput : public ILogOutput { public: - ILogOutput() : - silence(false) - {} - - /* line: Full line with timestamp, level and thread */ - virtual void printLog(const std::string &line){}; - /* line: Full line with timestamp, level and thread */ - virtual void printLog(const std::string &line, enum LogMessageLevel lev){}; - /* line: Only actual printed text */ - virtual void printLog(enum LogMessageLevel lev, const std::string &line){}; - - bool silence; + void log(LogLevel lev, const std::string &combined, + const std::string &time, const std::string &thread_name, + const std::string &payload_text) + { + logRaw(lev, combined); + } }; -void log_add_output(ILogOutput *out, enum LogMessageLevel lev); -void log_add_output_maxlev(ILogOutput *out, enum LogMessageLevel lev); -void log_add_output_all_levs(ILogOutput *out); -void log_remove_output(ILogOutput *out); -void log_set_lev_silence(enum LogMessageLevel lev, bool silence); +class StreamLogOutput : public ICombinedLogOutput { +public: + StreamLogOutput(std::ostream &stream) : + m_stream(stream) + { + } + + void logRaw(LogLevel lev, const std::string &line) + { + m_stream << line << std::endl; + } + +private: + std::ostream &m_stream; +}; -void log_register_thread(const std::string &name); -void log_deregister_thread(); +class FileLogOutput : public ICombinedLogOutput { +public: + void open(const std::string &filename); -void log_printline(enum LogMessageLevel lev, const std::string &text); + void logRaw(LogLevel lev, const std::string &line) + { + m_stream << line << std::endl; + } -#define LOGLINEF(lev, ...)\ -{\ - char buf[10000];\ - snprintf(buf, 10000, __VA_ARGS__);\ - log_printline(lev, buf);\ -} +private: + std::ofstream m_stream; +}; -extern std::ostream errorstream; -extern std::ostream actionstream; -extern std::ostream infostream; -extern std::ostream verbosestream; +class LogOutputBuffer : public ICombinedLogOutput { +public: + LogOutputBuffer(Logger &logger, LogLevel lev) : + m_logger(logger) + { + m_logger.addOutput(this, lev); + } + + ~LogOutputBuffer() + { + m_logger.removeOutput(this); + } + + void logRaw(LogLevel lev, const std::string &line) + { + m_buffer.push(line); + } + + bool empty() + { + return m_buffer.empty(); + } + + std::string get() + { + if (empty()) + return ""; + std::string s = m_buffer.front(); + m_buffer.pop(); + return s; + } + +private: + std::queue m_buffer; + Logger &m_logger; +}; -extern bool log_trace_level_enabled; -#define TRACESTREAM(x){ if(log_trace_level_enabled) verbosestream x; } -#define TRACEDO(x){ if(log_trace_level_enabled){ x ;} } +extern StreamLogOutput stdout_output; +extern StreamLogOutput stderr_output; +extern std::ostream null_stream; extern std::ostream *dout_con_ptr; extern std::ostream *derr_con_ptr; extern std::ostream *dout_server_ptr; extern std::ostream *derr_server_ptr; + +#ifndef SERVER +extern std::ostream *dout_client_ptr; +extern std::ostream *derr_client_ptr; +#endif + +extern Logger g_logger; + +// Writes directly to all LL_NONE log outputs for g_logger with no prefix. +extern std::ostream rawstream; + +extern std::ostream errorstream; +extern std::ostream warningstream; +extern std::ostream actionstream; +extern std::ostream infostream; +extern std::ostream verbosestream; +extern std::ostream dstream; + +#define TRACEDO(x) do { \ + if (g_logger.getTraceEnabled()) { \ + x; \ + } \ +} while (0) + +#define TRACESTREAM(x) TRACEDO(verbosestream x) + #define dout_con (*dout_con_ptr) #define derr_con (*derr_con_ptr) #define dout_server (*dout_server_ptr) #define derr_server (*derr_server_ptr) #ifndef SERVER -extern std::ostream *dout_client_ptr; -extern std::ostream *derr_client_ptr; -#define dout_client (*dout_client_ptr) -#define derr_client (*derr_client_ptr) - + #define dout_client (*dout_client_ptr) + #define derr_client (*derr_client_ptr) #endif -#endif +#endif