1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/*
* CLogger.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../CConsoleHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
class CLogger;
struct LogRecord;
class ILogTarget;
namespace ELogLevel
{
#ifdef VCMI_ANDROID
int toAndroid(ELogLevel logLevel);
#endif
}
/// The class CLoggerDomain provides convenient access to super domains from a sub domain.
class DLL_LINKAGE CLoggerDomain
{
public:
/// Constructs a CLoggerDomain with the domain designated by name.
/// Sub-domains can be specified by separating domains by a dot, e.g. "ai.battle". The global domain is named "global".
explicit CLoggerDomain(std::string name);
const std::string& getName() const;
CLoggerDomain getParent() const;
bool isGlobalDomain() const;
static const std::string DOMAIN_GLOBAL;
private:
std::string name;
};
/// The logger is used to log messages to certain targets of a specific domain/name.
/// It is thread-safe and can be used concurrently by several threads.
class DLL_LINKAGE CLogger final: public vstd::CLoggerBase
{
public:
ELogLevel::ELogLevel getLevel() const;
void setLevel(ELogLevel::ELogLevel level);
const CLoggerDomain & getDomain() const;
/// Logger access methods
static CLogger * getLogger(const CLoggerDomain & domain);
static CLogger * getGlobalLogger();
void log(ELogLevel::ELogLevel level, const std::string & message) const override;
void log(ELogLevel::ELogLevel level, const boost::format & fmt) const override;
void addTarget(std::unique_ptr<ILogTarget> && target);
void clearTargets();
/// Returns true if a debug/trace log message will be logged, false if not.
/// Useful if performance is important and concatenating the log message is a expensive task.
bool isDebugEnabled() const override;
bool isTraceEnabled() const override;
private:
explicit CLogger(const CLoggerDomain & domain);
inline ELogLevel::ELogLevel getEffectiveLevel() const override; /// Returns the log level applied on this logger whether directly or indirectly.
inline void callTargets(const LogRecord & record) const;
CLoggerDomain domain;
CLogger * parent;
ELogLevel::ELogLevel level;
std::vector<std::unique_ptr<ILogTarget> > targets;
mutable std::mutex mx;
static std::recursive_mutex smx;
};
/* ---------------------------------------------------------------------------- */
/* Implementation/Detail classes, Private API */
/* ---------------------------------------------------------------------------- */
/// The class CLogManager is a global storage for logger objects.
class DLL_LINKAGE CLogManager : public boost::noncopyable
{
public:
static CLogManager & get();
void addLogger(CLogger * logger);
CLogger * getLogger(const CLoggerDomain & domain); /// Returns a logger or nullptr if no one is registered for the given domain.
std::vector<std::string> getRegisteredDomains() const;
private:
CLogManager();
virtual ~CLogManager();
std::map<std::string, CLogger *> loggers;
mutable std::mutex mx;
static std::recursive_mutex smx;
};
/// The struct LogRecord holds the log message and additional logging information.
struct DLL_LINKAGE LogRecord
{
LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message);
CLoggerDomain domain;
ELogLevel::ELogLevel level;
std::string message;
boost::posix_time::ptime timeStamp;
std::string threadId;
};
/// The class CLogFormatter formats log records.
///
/// There are several pattern characters which can be used to format a log record:
/// %d = Date/Time
/// %l = Log level
/// %n = Logger name
/// %t = Thread ID
/// %m = Message
class DLL_LINKAGE CLogFormatter
{
public:
CLogFormatter();
CLogFormatter(std::string pattern);
void setPattern(const std::string & pattern);
void setPattern(std::string && pattern);
const std::string & getPattern() const;
std::string format(const LogRecord & record) const;
private:
std::string pattern;
};
/// The interface ILogTarget is used by all log target implementations. It holds
/// the abstract method write which sub-classes should implement.
class DLL_LINKAGE ILogTarget : public boost::noncopyable
{
public:
virtual ~ILogTarget() { };
virtual void write(const LogRecord & record) = 0;
};
/// The class CColorMapping maps a logger name and a level to a specific color. Supports domain inheritance.
class DLL_LINKAGE CColorMapping
{
public:
CColorMapping();
void setColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level, EConsoleTextColor::EConsoleTextColor color);
EConsoleTextColor::EConsoleTextColor getColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level) const;
private:
std::map<std::string, std::map<ELogLevel::ELogLevel, EConsoleTextColor::EConsoleTextColor> > map;
};
/// This target is a logging target which writes message to the console.
/// The target may be shared among multiple loggers. All methods except write aren't thread-safe.
/// The console target is intended to be configured once and then added to a logger.
class DLL_LINKAGE CLogConsoleTarget : public ILogTarget
{
public:
explicit CLogConsoleTarget(CConsoleHandler * console);
bool isColoredOutputEnabled() const;
void setColoredOutputEnabled(bool coloredOutputEnabled);
ELogLevel::ELogLevel getThreshold() const;
void setThreshold(ELogLevel::ELogLevel threshold);
const CLogFormatter & getFormatter() const;
void setFormatter(const CLogFormatter & formatter);
const CColorMapping & getColorMapping() const;
void setColorMapping(const CColorMapping & colorMapping);
void write(const LogRecord & record) override;
private:
#if !defined(VCMI_MOBILE)
CConsoleHandler * console;
#endif
ELogLevel::ELogLevel threshold;
bool coloredOutputEnabled;
CLogFormatter formatter;
CColorMapping colorMapping;
mutable std::mutex mx;
};
/// This target is a logging target which writes messages to a log file.
/// The target may be shared among multiple loggers. All methods except write aren't thread-safe.
/// The file target is intended to be configured once and then added to a logger.
class DLL_LINKAGE CLogFileTarget : public ILogTarget
{
public:
/// Constructs a CLogFileTarget and opens the file designated by filePath. If the append parameter is true, the file
/// will be appended to. Otherwise the file designated by filePath will be truncated before being opened.
explicit CLogFileTarget(const boost::filesystem::path & filePath, bool append = true);
~CLogFileTarget();
const CLogFormatter & getFormatter() const;
void setFormatter(const CLogFormatter & formatter);
void write(const LogRecord & record) override;
private:
std::fstream file;
CLogFormatter formatter;
mutable std::mutex mx;
};
VCMI_LIB_NAMESPACE_END
|