File: CLogger.h

package info (click to toggle)
vcmi 1.6.5%2Bdfsg-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 32,060 kB
  • sloc: cpp: 238,971; python: 265; sh: 224; xml: 157; ansic: 78; objc: 61; makefile: 49
file content (222 lines) | stat: -rw-r--r-- 6,825 bytes parent folder | download
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