X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flog.h;h=219255d9abfd6af92f042efa32ea0df3946d56e2;hb=9762650f978cc7bae78861b70a051b26cc5e2dc6;hp=012e7e9387a18d08b51267ca9fa274dc779b2f5c;hpb=037b2591971d752e67fa7d47095b996b3f56da5a;p=minetest.git diff --git a/src/log.h b/src/log.h index 012e7e938..219255d9a 100644 --- a/src/log.h +++ b/src/log.h @@ -1,6 +1,6 @@ /* -Minetest-c55 -Copyright (C) 2011 celeron55, Perttu Ahola +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -20,59 +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. - - If you need to explicitly print something, use dstream or cout or cerr. -*/ +typedef u8 LogLevelMask; +#define LOGLEVEL_TO_MASKLEVEL(x) (1 << x) + +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; +}; + +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 ICombinedLogOutput : public ILogOutput { +public: + 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); + } +}; -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 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; +}; + +class FileLogOutput : public ICombinedLogOutput { +public: + void open(const std::string &filename); + + void logRaw(LogLevel lev, const std::string &line) + { + m_stream << line << std::endl; + } + +private: + std::ofstream m_stream; }; -class ILogOutput -{ +class LogOutputBuffer : public ICombinedLogOutput { public: - /* 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){}; + 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; }; -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_register_thread(const std::string &name); -void log_deregister_thread(); +extern StreamLogOutput stdout_output; +extern StreamLogOutput stderr_output; +extern std::ostream null_stream; -void log_printline(enum LogMessageLevel lev, const std::string &text); +extern std::ostream *dout_con_ptr; +extern std::ostream *derr_con_ptr; +extern std::ostream *dout_server_ptr; +extern std::ostream *derr_server_ptr; -#define LOGLINEF(lev, ...)\ -{\ - char buf[10000];\ - snprintf(buf, 10000, __VA_ARGS__);\ - log_printline(lev, buf);\ -} +#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; -extern bool log_trace_level_enabled; +#define TRACEDO(x) do { \ + if (g_logger.getTraceEnabled()) { \ + x; \ + } \ +} while (0) -#define TRACESTREAM(x){ if(log_trace_level_enabled) verbosestream x; } -#define TRACEDO(x){ if(log_trace_level_enabled){ x ;} } +#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 + #define dout_client (*dout_client_ptr) + #define derr_client (*derr_client_ptr) #endif + +#endif