X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flog.h;h=6ed6b1fb710b272ae66a8e81614850cdad14ba63;hb=391eec9ee78fc9dfdc476ad2a8ed7755009e4a2f;hp=5c9bb1b262fbde3a0e3c9c8bf11828e931bd4f9c;hpb=497ff1ecd64c8908f988e15ca879824f2781e3fd;p=minetest.git diff --git a/src/log.h b/src/log.h index 5c9bb1b26..6ed6b1fb7 100644 --- a/src/log.h +++ b/src/log.h @@ -1,6 +1,6 @@ /* Minetest -Copyright (C) 2011 celeron55, Perttu Ahola +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 @@ -17,62 +17,203 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef LOG_HEADER -#define LOG_HEADER +#pragma once +#include +#include #include +#include +#include +#include +#if !defined(_WIN32) // POSIX + #include +#endif +#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. -*/ +enum LogColor { + LOG_COLOR_NEVER, + LOG_COLOR_ALWAYS, + LOG_COLOR_AUTO, +}; + +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(); -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, + 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); + + static LogColor color_mode; + +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 std::mutex m_mutex; + bool m_trace_enabled; }; -class ILogOutput -{ +class ILogOutput { 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){}; + 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; }; -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); +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); + } +}; -void log_register_thread(const std::string &name); -void log_deregister_thread(); +class StreamLogOutput : public ICombinedLogOutput { +public: + StreamLogOutput(std::ostream &stream) : + m_stream(stream) + { +#if !defined(_WIN32) + is_tty = isatty(fileno(stdout)); +#else + is_tty = false; +#endif + } -void log_printline(enum LogMessageLevel lev, const std::string &text); + void logRaw(LogLevel lev, const std::string &line); -#define LOGLINEF(lev, ...)\ -{\ - char buf[10000];\ - snprintf(buf, 10000, __VA_ARGS__);\ - log_printline(lev, buf);\ -} +private: + std::ostream &m_stream; + bool is_tty; +}; + +class FileLogOutput : public ICombinedLogOutput { +public: + void setFile(const std::string &filename, s64 file_size_max); + + void logRaw(LogLevel lev, const std::string &line) + { + m_stream << line << std::endl; + } + +private: + std::ofstream m_stream; +}; + +class LogOutputBuffer : public ICombinedLogOutput { +public: + LogOutputBuffer(Logger &logger) : + m_logger(logger) + { + updateLogLevel(); + }; + + virtual ~LogOutputBuffer() + { + m_logger.removeOutput(this); + } + + void updateLogLevel(); + + void logRaw(LogLevel lev, const std::string &line); + + void clear() + { + m_buffer = std::queue(); + } + + bool empty() const + { + 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 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 *derr_server_ptr; + +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) -#endif +#define dout_con (*dout_con_ptr) +#define derr_con (*derr_con_ptr)