mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	- Implemented the new logging API(not used currently) - Added lock typedefs to Global.h - Some layout updates to Global.h
This commit is contained in:
		
							
								
								
									
										198
									
								
								Global.h
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								Global.h
									
									
									
									
									
								
							| @@ -1,14 +1,3 @@ | |||||||
| #pragma once |  | ||||||
|  |  | ||||||
| // Standard include file |  | ||||||
| // Contents: |  | ||||||
| // Includes C/C++ libraries, STL libraries, IOStream and String libraries |  | ||||||
| // Includes the most important boost headers |  | ||||||
| // Defines the import + export, override and exception handling macros |  | ||||||
| // Defines the vstd library |  | ||||||
| // Includes the logger |  | ||||||
|  |  | ||||||
| // This file shouldn't be changed, except if there is a important header file missing which is shared among several projects. |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Global.h, part of VCMI engine |  * Global.h, part of VCMI engine | ||||||
| @@ -20,11 +9,59 @@ | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Compiler detection */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | // Fixed width bool data type is important for serialization | ||||||
|  | static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); | ||||||
|  |  | ||||||
|  | #if defined _M_X64 && defined _WIN32 //Win64 -> cannot load 32-bit DLLs for video handling | ||||||
|  |     #define DISABLE_VIDEO | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(__GNUC__) && (GCC_VERSION == 470 || GCC_VERSION == 471) | ||||||
|  | #error This GCC version has buggy std::array::at version and should not be used. Please update to 4.7.2 or use 4.6.x. | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Guarantee compiler features */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | //defining available c++11 features | ||||||
|  |  | ||||||
|  | //initialization lists - only gcc-4.4 or later | ||||||
|  | #if defined(__clang__) || (defined(__GNUC__) && (GCC_VERSION >= 440)) | ||||||
|  | #define CPP11_USE_INITIALIZERS_LIST | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //nullptr -  only msvc and gcc-4.6 or later, othervice define it  as NULL | ||||||
|  | #if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 460)) | ||||||
|  | #define nullptr NULL | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //override keyword - only msvc and gcc-4.7 or later. | ||||||
|  | #if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 470)) | ||||||
|  | #define override | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //workaround to support existing code | ||||||
|  | #define OVERRIDE override | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Suppress some compiler warnings */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #pragma warning (disable : 4800 ) /* disable conversion to bool warning -- I think it's intended in all places */ | #pragma warning (disable : 4800 ) /* disable conversion to bool warning -- I think it's intended in all places */ | ||||||
| #endif //_MSC_VER | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Commonly used C++, Boost headers */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
| #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers | #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| @@ -50,7 +87,6 @@ | |||||||
| #include <set> | #include <set> | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <string> | #include <string> | ||||||
| //#include <unordered_map> |  | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| @@ -70,6 +106,7 @@ | |||||||
| #include <boost/bind.hpp> | #include <boost/bind.hpp> | ||||||
| #include <boost/cstdint.hpp> | #include <boost/cstdint.hpp> | ||||||
| #include <boost/date_time/posix_time/posix_time.hpp> | #include <boost/date_time/posix_time/posix_time.hpp> | ||||||
|  | #include <boost/date_time/posix_time/posix_time_io.hpp> | ||||||
| #include <boost/filesystem.hpp> | #include <boost/filesystem.hpp> | ||||||
| #include <boost/foreach.hpp> | #include <boost/foreach.hpp> | ||||||
| #include <boost/format.hpp> | #include <boost/format.hpp> | ||||||
| @@ -90,6 +127,17 @@ | |||||||
| #include <android/log.h> | #include <android/log.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Usings */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | using std::shared_ptr; | ||||||
|  | using std::unique_ptr; | ||||||
|  | using std::make_shared; | ||||||
|  | namespace range = boost::range; | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Typedefs */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
| // Integral data types | // Integral data types | ||||||
| typedef boost::uint64_t ui64; //unsigned int 64 bits (8 bytes) | typedef boost::uint64_t ui64; //unsigned int 64 bits (8 bytes) | ||||||
| typedef boost::uint32_t ui32;  //unsigned int 32 bits (4 bytes) | typedef boost::uint32_t ui32;  //unsigned int 32 bits (4 bytes) | ||||||
| @@ -100,21 +148,14 @@ typedef boost::int32_t si32; //signed int 32 bits (4 bytes) | |||||||
| typedef boost::int16_t si16; //signed int 16 bits (2 bytes) | typedef boost::int16_t si16; //signed int 16 bits (2 bytes) | ||||||
| typedef boost::int8_t si8; //signed int 8 bits (1 byte) | typedef boost::int8_t si8; //signed int 8 bits (1 byte) | ||||||
|  |  | ||||||
| // Fixed width bool data type is important for serialization | // Lock typedefs | ||||||
| static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); | typedef boost::unique_lock<boost::shared_mutex> TWriteLock; | ||||||
|  | typedef boost::shared_lock<boost::shared_mutex> TReadLock; | ||||||
| #if defined _M_X64 && defined _WIN32 //Win64 -> cannot load 32-bit DLLs for video handling | typedef boost::lock_guard<boost::mutex> TLockGuard; | ||||||
| 	#define DISABLE_VIDEO |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef __GNUC__ |  | ||||||
| #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(__GNUC__) && (GCC_VERSION == 470 || GCC_VERSION == 471) |  | ||||||
| #error This GCC version has buggy std::array::at version and should not be used. Please update to 4.7.2 or use 4.6.x. |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* Macros */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
| // Import + Export macro declarations | // Import + Export macro declarations | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| #ifdef __GNUC__ | #ifdef __GNUC__ | ||||||
| @@ -150,26 +191,46 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); | |||||||
| #define DLL_LINKAGE DLL_IMPORT | #define DLL_LINKAGE DLL_IMPORT | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| //defining available c++11 features | #define THROW_FORMAT(message, formatting_elems)  throw std::runtime_error(boost::str(boost::format(message) % formatting_elems)) | ||||||
|  |  | ||||||
| //initialization lists - only gcc-4.4 or later | #define ASSERT_IF_CALLED_WITH_PLAYER if(!player) {tlog1 << __FUNCTION__ << "\n"; assert(0);} | ||||||
| #if defined(__clang__) || (defined(__GNUC__) && (GCC_VERSION >= 440)) |  | ||||||
| #define CPP11_USE_INITIALIZERS_LIST |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //nullptr -  only msvc and gcc-4.6 or later, othervice define it  as NULL | //XXX pls dont - 'debug macros' are usually more trouble than it's worth | ||||||
| #if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 460)) | #define HANDLE_EXCEPTION  \ | ||||||
| #define nullptr NULL |     catch (const std::exception& e) {	\ | ||||||
| #endif |     tlog1 << e.what() << std::endl;		\ | ||||||
|  |     throw;								\ | ||||||
|  | }									\ | ||||||
|  |     catch (const std::exception * e)	\ | ||||||
|  | {									\ | ||||||
|  |     tlog1 << e->what()<< std::endl;	\ | ||||||
|  |     throw;							\ | ||||||
|  | }									\ | ||||||
|  |     catch (const std::string& e) {		\ | ||||||
|  |     tlog1 << e << std::endl;		\ | ||||||
|  |     throw;							\ | ||||||
|  | } | ||||||
|  |  | ||||||
| //override keyword - only msvc and gcc-4.7 or later. | #define HANDLE_EXCEPTIONC(COMMAND)  \ | ||||||
| #if !defined(_MSC_VER) && !(defined(__GNUC__) && (GCC_VERSION >= 470)) |     catch (const std::exception& e) {	\ | ||||||
| #define override |     COMMAND;						\ | ||||||
| #endif |     tlog1 << e.what() << std::endl;	\ | ||||||
|  |     throw;							\ | ||||||
|  | }									\ | ||||||
|  |     catch (const std::string &e)	\ | ||||||
|  | {									\ | ||||||
|  |     COMMAND;						\ | ||||||
|  |     tlog1 << e << std::endl;	\ | ||||||
|  |     throw;							\ | ||||||
|  | } | ||||||
|  |  | ||||||
| //workaround to support existing code | // can be used for counting arrays | ||||||
| #define OVERRIDE override | template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N]; | ||||||
|  | #define ARRAY_COUNT(arr)    (sizeof(_ArrayCountObj(arr))) | ||||||
|  |  | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* VCMI standard library */ | ||||||
|  | /* ---------------------------------------------------------------------------- */ | ||||||
| //a normal std::map with a const operator[] for sanity | //a normal std::map with a const operator[] for sanity | ||||||
| template<typename KeyT, typename ValT> | template<typename KeyT, typename ValT> | ||||||
| class bmap : public std::map<KeyT, ValT> | class bmap : public std::map<KeyT, ValT> | ||||||
| @@ -508,53 +569,10 @@ namespace vstd | |||||||
| 		obj = (T)(((int)obj) + change); | 		obj = (T)(((int)obj) + change); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | using vstd::operator-=; | ||||||
| using std::shared_ptr; |  | ||||||
| using std::unique_ptr; |  | ||||||
| using std::make_shared; |  | ||||||
| using vstd::make_unique; | using vstd::make_unique; | ||||||
|  |  | ||||||
| using vstd::operator-=; | /* ---------------------------------------------------------------------------- */ | ||||||
|  | /* VCMI headers */ | ||||||
| namespace range = boost::range; | /* ---------------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| // can be used for counting arrays |  | ||||||
| template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N]; |  | ||||||
| #define ARRAY_COUNT(arr)    (sizeof(_ArrayCountObj(arr))) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define THROW_FORMAT(message, formatting_elems)  throw std::runtime_error(boost::str(boost::format(message) % formatting_elems)) |  | ||||||
|  |  | ||||||
| #define ASSERT_IF_CALLED_WITH_PLAYER if(!player) {tlog1 << __FUNCTION__ << "\n"; assert(0);} |  | ||||||
|  |  | ||||||
| //XXX pls dont - 'debug macros' are usually more trouble than it's worth |  | ||||||
| #define HANDLE_EXCEPTION  \ |  | ||||||
| 	catch (const std::exception& e) {	\ |  | ||||||
| 	tlog1 << e.what() << std::endl;		\ |  | ||||||
| 	throw;								\ |  | ||||||
| }									\ |  | ||||||
| 	catch (const std::exception * e)	\ |  | ||||||
| {									\ |  | ||||||
| 	tlog1 << e->what()<< std::endl;	\ |  | ||||||
| 	throw;							\ |  | ||||||
| }									\ |  | ||||||
| 	catch (const std::string& e) {		\ |  | ||||||
| 	tlog1 << e << std::endl;		\ |  | ||||||
| 	throw;							\ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #define HANDLE_EXCEPTIONC(COMMAND)  \ |  | ||||||
| 	catch (const std::exception& e) {	\ |  | ||||||
| 	COMMAND;						\ |  | ||||||
| 	tlog1 << e.what() << std::endl;	\ |  | ||||||
| 	throw;							\ |  | ||||||
| }									\ |  | ||||||
| 	catch (const std::string &e)	\ |  | ||||||
| {									\ |  | ||||||
| 	COMMAND;						\ |  | ||||||
| 	tlog1 << e << std::endl;	\ |  | ||||||
| 	throw;							\ |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "lib/CLogger.h" | #include "lib/CLogger.h" | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| { | { | ||||||
| 	"type" : "object", | 	"type" : "object", | ||||||
| 	"$schema": "http://json-schema.org/draft-04/schema", | 	"$schema": "http://json-schema.org/draft-04/schema", | ||||||
| 	"required" : [ "general", "video", "adventure", "battle", "server" ], | 	"required" : [ "general", "video", "adventure", "battle", "server", "logging" ], | ||||||
| 	"properties": | 	"properties": | ||||||
| 	{ | 	{ | ||||||
| 		"general" : { | 		"general" : { | ||||||
| @@ -133,6 +133,72 @@ | |||||||
| 					"default" : "StupidAI" | 					"default" : "StupidAI" | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 		}, | ||||||
|  | 		"logging" : { | ||||||
|  | 			"type" : "object", | ||||||
|  | 			"default" : {}, | ||||||
|  | 			"properties" : { | ||||||
|  | 				"console" : { | ||||||
|  | 					"type" : "object", | ||||||
|  | 					"properties" : { | ||||||
|  | 						"format" : { | ||||||
|  | 							"type" : "string", | ||||||
|  | 							"default" : "%l %n [%t] - %m" | ||||||
|  | 						}, | ||||||
|  | 						"threshold" : { | ||||||
|  | 							"type" : "string", | ||||||
|  | 							"default" : "info", | ||||||
|  | 							"enum" : [ "trace", "debug", "info", "warn", "error" ] | ||||||
|  | 						}, | ||||||
|  | 						"coloredOutputEnabled" : { | ||||||
|  | 							"type" : "boolean", | ||||||
|  | 							"default" : true | ||||||
|  | 						}, | ||||||
|  | 						"colorMapping" : { | ||||||
|  | 							"type" : "array", | ||||||
|  | 							"default" : [ | ||||||
|  | 								{ "domain" : "global", "level" : "trace", "color" : "gray"}, | ||||||
|  | 								{ "domain" : "global", "level" : "debug", "color" : "white"}, | ||||||
|  | 								{ "domain" : "global", "level" : "info", "color" : "green"}, | ||||||
|  | 								{ "domain" : "global", "level" : "warn", "color" : "yellow"}, | ||||||
|  | 								{ "domain" : "global", "level" : "error", "color" : "red"} | ||||||
|  | 							], | ||||||
|  | 							"items" : { | ||||||
|  | 								"type" : "object", | ||||||
|  | 								"required" : [ "domain", "level", "color" ], | ||||||
|  | 								"properties" : { | ||||||
|  | 									"domain" : { "type" : "string" }, | ||||||
|  | 									"level" : { "type" : "string", "enum" : [ "trace", "debug", "info", "warn", "error" ] }, | ||||||
|  | 									"color" : { "type" : "string", "enum" : [ "default", "green", "red", "magenta", "yellow", "white", "gray", "teal" ] } | ||||||
|  | 								} | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				}, | ||||||
|  | 				"file" : { | ||||||
|  | 					"type" : "object", | ||||||
|  | 					"properties" : { | ||||||
|  | 						"format" : { | ||||||
|  | 							"type" : "string", | ||||||
|  | 							"default" : "%d %l %n [%t] - %m" | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				}, | ||||||
|  | 				"loggers" : { | ||||||
|  | 					"type" : "object", | ||||||
|  | 					"additionalProperties" : { | ||||||
|  | 						"type":"object", | ||||||
|  | 						"required" : [ "level" ], | ||||||
|  | 						"properties" : { | ||||||
|  | 							"level" : { | ||||||
|  | 								"type" : "string", | ||||||
|  | 								"enum" : [ "trace", "debug", "info", "warn", "error" ] | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -141,43 +141,43 @@ LONG WINAPI onUnhandledException(EXCEPTION_POINTERS* exception) | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| void CConsoleHandler::setColor(int level) | void CConsoleHandler::setColor(EConsoleTextColor::EConsoleTextColor color) | ||||||
| { | { | ||||||
| 	TColor color; |     TColor colorCode; | ||||||
| 	switch(level) |     switch(color) | ||||||
| 	{ | 	{ | ||||||
| 	case -1: |     case EConsoleTextColor::DEFAULT: | ||||||
| 		color = defColor; |         colorCode = defColor; | ||||||
| 		break; | 		break; | ||||||
| 	case 0: |     case EConsoleTextColor::GREEN: | ||||||
| 		color = CONSOLE_GREEN; |         colorCode = CONSOLE_GREEN; | ||||||
| 		break; | 		break; | ||||||
| 	case 1: |     case EConsoleTextColor::RED: | ||||||
| 		color = CONSOLE_RED; |         colorCode = CONSOLE_RED; | ||||||
| 		break; | 		break; | ||||||
| 	case 2: |     case EConsoleTextColor::MAGENTA: | ||||||
| 		color = CONSOLE_MAGENTA; |         colorCode = CONSOLE_MAGENTA; | ||||||
| 		break; | 		break; | ||||||
| 	case 3: |     case EConsoleTextColor::YELLOW: | ||||||
| 		color = CONSOLE_YELLOW; |         colorCode = CONSOLE_YELLOW; | ||||||
| 		break; | 		break; | ||||||
| 	case 4: |     case EConsoleTextColor::WHITE: | ||||||
| 		color = CONSOLE_WHITE; |         colorCode = CONSOLE_WHITE; | ||||||
| 		break; | 		break; | ||||||
| 	case 5: |     case EConsoleTextColor::GRAY: | ||||||
| 		color = CONSOLE_GRAY; |         colorCode = CONSOLE_GRAY; | ||||||
| 		break; | 		break; | ||||||
| 	case -2: |     case EConsoleTextColor::TEAL: | ||||||
| 		color = CONSOLE_TEAL; |         colorCode = CONSOLE_TEAL; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		color = defColor; |         colorCode = defColor; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 	SetConsoleTextAttribute(handleOut,color); |     SetConsoleTextAttribute(handleOut, colorCode); | ||||||
| #else | #else | ||||||
| 	std::cout << color; |     std::cout << colorCode; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -210,7 +210,7 @@ int CConsoleHandler::run() | |||||||
| 	} | 	} | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| CConsoleHandler::CConsoleHandler() | CConsoleHandler::CConsoleHandler() : thread(nullptr) | ||||||
| { | { | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 	handleIn = GetStdHandle(STD_INPUT_HANDLE); | 	handleIn = GetStdHandle(STD_INPUT_HANDLE); | ||||||
| @@ -225,7 +225,6 @@ CConsoleHandler::CConsoleHandler() | |||||||
| 	defColor = "\x1b[0m"; | 	defColor = "\x1b[0m"; | ||||||
| #endif | #endif | ||||||
|     cb = new boost::function<void(const std::string &)>; |     cb = new boost::function<void(const std::string &)>; | ||||||
| 	thread = NULL; |  | ||||||
| } | } | ||||||
| CConsoleHandler::~CConsoleHandler() | CConsoleHandler::~CConsoleHandler() | ||||||
| { | { | ||||||
|   | |||||||
| @@ -10,36 +10,64 @@ | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | namespace EConsoleTextColor | ||||||
|  | { | ||||||
|  | /** The color enum is used for colored text console output. */ | ||||||
|  | enum EConsoleTextColor | ||||||
|  | { | ||||||
|  |     DEFAULT = -1, | ||||||
|  |     GREEN, | ||||||
|  |     RED, | ||||||
|  |     MAGENTA, | ||||||
|  |     YELLOW, | ||||||
|  |     WHITE, | ||||||
|  |     GRAY, | ||||||
|  |     TEAL = -2 | ||||||
|  | }; | ||||||
|  | } | ||||||
|  |  | ||||||
| /// Class which wraps the native console. It can print text based on | /// Class which wraps the native console. It can print text based on | ||||||
| /// the chosen color | /// the chosen color | ||||||
| class DLL_LINKAGE CConsoleHandler | class DLL_LINKAGE CConsoleHandler | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	boost::function<void(const std::string &)> *cb; //function to be called when message is received |  | ||||||
| 	int curLvl; //logging level |  | ||||||
| 	boost::thread *thread; |  | ||||||
|  |  | ||||||
| 	int run(); |  | ||||||
| 	void setColor(int level); //sets color of text appropriate for given logging level |  | ||||||
|  |  | ||||||
|     CConsoleHandler(); //c-tor |     CConsoleHandler(); //c-tor | ||||||
|     ~CConsoleHandler(); //d-tor |     ~CConsoleHandler(); //d-tor | ||||||
|     void start(); //starts listening thread |     void start(); //starts listening thread | ||||||
| 	void end(); //kills listening thread |  | ||||||
|  |  | ||||||
| 	template<typename T> void print(const T &data, int lvl) |     template<typename T> void print(const T &data, EConsoleTextColor::EConsoleTextColor color = EConsoleTextColor::DEFAULT, bool printToStdErr = false) | ||||||
| 	{ | 	{ | ||||||
|  |         TLockGuard _(mx); | ||||||
| #ifndef _WIN32 | #ifndef _WIN32 | ||||||
| 		// with love from ffmpeg - library is trying to print some warnings from separate thread | 		// with love from ffmpeg - library is trying to print some warnings from separate thread | ||||||
| 		// this results in broken console on Linux. Lock stdout to print all our data at once | 		// this results in broken console on Linux. Lock stdout to print all our data at once | ||||||
| 		flockfile(stdout); | 		flockfile(stdout); | ||||||
| #endif | #endif | ||||||
| 		setColor(lvl); |         if(color != EConsoleTextColor::DEFAULT) setColor(color); | ||||||
|  |         if(printToStdErr) | ||||||
|  |         { | ||||||
|  |             std::cerr << data << std::flush; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|             std::cout << data << std::flush; |             std::cout << data << std::flush; | ||||||
| 		setColor(-1); |         } | ||||||
|  |         if(color != EConsoleTextColor::DEFAULT) setColor(EConsoleTextColor::DEFAULT); | ||||||
| #ifndef _WIN32 | #ifndef _WIN32 | ||||||
| 		funlockfile(stdout); | 		funlockfile(stdout); | ||||||
| #endif | #endif | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |     boost::function<void(const std::string &)> *cb; //function to be called when message is received | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     int run(); | ||||||
|  |  | ||||||
|  |     void end(); //kills listening thread | ||||||
|  |  | ||||||
|  |     void setColor(EConsoleTextColor::EConsoleTextColor color); //sets color of text appropriate for given logging level | ||||||
|  |  | ||||||
|  |     mutable boost::mutex mx; | ||||||
|  |  | ||||||
|  |     boost::thread * thread; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ public: | |||||||
| 		if(lvl < CLogger::CONSOLE_LOGGING_LEVEL) | 		if(lvl < CLogger::CONSOLE_LOGGING_LEVEL) | ||||||
| 		{ | 		{ | ||||||
| 			if(console) | 			if(console) | ||||||
| 				console->print(data, lvl); |                 console->print(data, static_cast<EConsoleTextColor::EConsoleTextColor>(lvl)); | ||||||
| 			else | 			else | ||||||
| 				std::cout << data << std::flush; | 				std::cout << data << std::flush; | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -13,6 +13,12 @@ set(lib_SRCS | |||||||
| 		Filesystem/CResourceLoader.cpp | 		Filesystem/CResourceLoader.cpp | ||||||
| 		Filesystem/CFileInputStream.cpp | 		Filesystem/CFileInputStream.cpp | ||||||
| 		Filesystem/CCompressedStream.cpp | 		Filesystem/CCompressedStream.cpp | ||||||
|  | 		Logging/CBasicLogConfigurator.cpp | ||||||
|  | 		Logging/CLogConsoleTarget.cpp | ||||||
|  | 		Logging/CLogFileTarget.cpp | ||||||
|  | 		Logging/CLogFormatter.cpp | ||||||
|  | 		Logging/CLogger.cpp | ||||||
|  | 		Logging/CLogManager.cpp | ||||||
| 		Mapping/CCampaignHandler.cpp | 		Mapping/CCampaignHandler.cpp | ||||||
| 		Mapping/CMap.cpp | 		Mapping/CMap.cpp | ||||||
| 		Mapping/CMapEditManager.cpp | 		Mapping/CMapEditManager.cpp | ||||||
| @@ -59,6 +65,14 @@ set(lib_SRCS | |||||||
| set(lib_HEADERS | set(lib_HEADERS | ||||||
| 		Filesystem/CInputStream.h | 		Filesystem/CInputStream.h | ||||||
| 		Filesystem/ISimpleResourceLoader.h | 		Filesystem/ISimpleResourceLoader.h | ||||||
|  | 		Logging/CBasicLogConfigurator.h | ||||||
|  | 		Logging/CLogConsoleTarget.h | ||||||
|  | 		Logging/CLogFileTarget.h | ||||||
|  | 		Logging/CLogFormatter.h | ||||||
|  | 		Logging/CLogger.h | ||||||
|  | 		Logging/CLogManager.h | ||||||
|  | 		Logging/ILogTarget.h | ||||||
|  | 		Logging/LogRecord.h | ||||||
| 		Mapping/CCampaignHandler.h | 		Mapping/CCampaignHandler.h | ||||||
| 		Mapping/CMap.h | 		Mapping/CMap.h | ||||||
| 		Mapping/CMapEditManager.h | 		Mapping/CMapEditManager.h | ||||||
|   | |||||||
							
								
								
									
										113
									
								
								lib/Logging/CBasicLogConfigurator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								lib/Logging/CBasicLogConfigurator.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CBasicLogConfigurator.h" | ||||||
|  |  | ||||||
|  | #include "../CConfigHandler.h" | ||||||
|  | #include "CLogConsoleTarget.h" | ||||||
|  | #include "CLogFileTarget.h" | ||||||
|  |  | ||||||
|  | CBasicLogConfigurator::CBasicLogConfigurator(const std::string & filePath, CConsoleHandler * console) | ||||||
|  | { | ||||||
|  |     const JsonNode & logging = settings["logging"]; | ||||||
|  |  | ||||||
|  |     // Configure loggers | ||||||
|  |     const JsonNode & loggers = logging["loggers"]; | ||||||
|  |     if(!loggers.isNull()) | ||||||
|  |     { | ||||||
|  |         BOOST_FOREACH(auto & loggerPair, loggers.Struct()) | ||||||
|  |         { | ||||||
|  |             // Get logger | ||||||
|  |             std::string name = loggerPair.first; | ||||||
|  |             CGLogger * logger = CGLogger::getLogger(name); | ||||||
|  |  | ||||||
|  |             // Set log level | ||||||
|  |             const JsonNode & loggerNode = loggerPair.second; | ||||||
|  |             const JsonNode & levelNode = loggerNode["level"]; | ||||||
|  |             if(!levelNode.isNull()) | ||||||
|  |             { | ||||||
|  |                 logger->setLevel(getLogLevel(levelNode.String())); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Add console target | ||||||
|  |     CLogConsoleTarget * consoleTarget = new CLogConsoleTarget(console); | ||||||
|  |     const JsonNode & consoleNode = logging["console"]; | ||||||
|  |     if(!consoleNode.isNull()) | ||||||
|  |     { | ||||||
|  |         const JsonNode & consoleFormatNode = consoleNode["format"]; | ||||||
|  |         if(!consoleFormatNode.isNull()) consoleTarget->setFormatter(CLogFormatter(consoleFormatNode.String())); | ||||||
|  |         const JsonNode & consoleThresholdNode = consoleNode["threshold"]; | ||||||
|  |         if(!consoleThresholdNode.isNull()) consoleTarget->setThreshold(getLogLevel(consoleThresholdNode.String())); | ||||||
|  |         const JsonNode & coloredConsoleEnabledNode = consoleNode["coloredOutputEnabled"]; | ||||||
|  |         consoleTarget->setColoredOutputEnabled(coloredConsoleEnabledNode.Bool()); | ||||||
|  |  | ||||||
|  |         CColorMapping colorMapping; | ||||||
|  |         const JsonNode & colorMappingNode = consoleNode["colorMapping"]; | ||||||
|  |         if(!colorMappingNode.isNull()) | ||||||
|  |         { | ||||||
|  |             BOOST_FOREACH(const JsonNode & mappingNode, colorMappingNode.Vector()) | ||||||
|  |             { | ||||||
|  |                 std::string domain = mappingNode["domain"].String(); | ||||||
|  |                 std::string level = mappingNode["level"].String(); | ||||||
|  |                 std::string color = mappingNode["color"].String(); | ||||||
|  |                 colorMapping.setColorFor(domain, getLogLevel(level), getConsoleColor(color)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         consoleTarget->setColorMapping(colorMapping); | ||||||
|  |     } | ||||||
|  |     CGLogger::getGlobalLogger()->addTarget(consoleTarget); | ||||||
|  |  | ||||||
|  |     // Add file target | ||||||
|  |     CLogFileTarget * fileTarget = new CLogFileTarget(filePath); | ||||||
|  |     const JsonNode & fileNode = logging["file"]; | ||||||
|  |     if(!fileNode.isNull()) | ||||||
|  |     { | ||||||
|  |         const JsonNode & fileFormatNode = fileNode["format"]; | ||||||
|  |         if(!fileFormatNode.isNull()) fileTarget->setFormatter(CLogFormatter(fileFormatNode.String())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Add targets to the root logger by default | ||||||
|  |     CGLogger::getGlobalLogger()->addTarget(consoleTarget); | ||||||
|  |     CGLogger::getGlobalLogger()->addTarget(fileTarget); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ELogLevel::ELogLevel CBasicLogConfigurator::getLogLevel(const std::string & level) const | ||||||
|  | { | ||||||
|  |     static const std::map<std::string, ELogLevel::ELogLevel> levelMap = boost::assign::map_list_of | ||||||
|  |             ("trace", ELogLevel::TRACE) | ||||||
|  |             ("debug", ELogLevel::DEBUG) | ||||||
|  |             ("info", ELogLevel::INFO) | ||||||
|  |             ("warn", ELogLevel::WARN) | ||||||
|  |             ("error", ELogLevel::ERROR); | ||||||
|  |     const auto & levelPair = levelMap.find(level); | ||||||
|  |     if(levelPair != levelMap.end()) | ||||||
|  |     { | ||||||
|  |         return levelPair->second; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         throw std::runtime_error("Log level " + level + " unknown."); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | EConsoleTextColor::EConsoleTextColor CBasicLogConfigurator::getConsoleColor(const std::string & colorName) const | ||||||
|  | { | ||||||
|  |     static const std::map<std::string, EConsoleTextColor::EConsoleTextColor> colorMap = boost::assign::map_list_of | ||||||
|  |             ("default", EConsoleTextColor::DEFAULT) | ||||||
|  |             ("green", EConsoleTextColor::GREEN) | ||||||
|  |             ("red", EConsoleTextColor::RED) | ||||||
|  |             ("magenta", EConsoleTextColor::MAGENTA) | ||||||
|  |             ("yellow", EConsoleTextColor::YELLOW) | ||||||
|  |             ("white", EConsoleTextColor::WHITE) | ||||||
|  |             ("gray", EConsoleTextColor::GRAY) | ||||||
|  |             ("teal", EConsoleTextColor::TEAL); | ||||||
|  |     const auto & colorPair = colorMap.find(colorName); | ||||||
|  |     if(colorPair != colorMap.end()) | ||||||
|  |     { | ||||||
|  |         return colorPair->second; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         throw std::runtime_error("Color " + colorName + " unknown."); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								lib/Logging/CBasicLogConfigurator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								lib/Logging/CBasicLogConfigurator.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * CBasicLogConfigurator.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 "CLogger.h" | ||||||
|  |  | ||||||
|  | class CConsoleHandler; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The basic log configurator reads log properties from the settings.json and | ||||||
|  |  * sets up the logging system. The file path of the log file can be specified | ||||||
|  |  * via the constructor. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CBasicLogConfigurator | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param fileName The file path of the log file. | ||||||
|  |      * | ||||||
|  |      * @throws std::runtime_error if the configuration has errors | ||||||
|  |      */ | ||||||
|  |     CBasicLogConfigurator(const std::string & filePath, CConsoleHandler * console); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** | ||||||
|  |      * Gets the log level enum from a string. | ||||||
|  |      * | ||||||
|  |      * @param level The log level string to parse. | ||||||
|  |      * @return the corresponding log level enum value | ||||||
|  |      * | ||||||
|  |      * @throws std::runtime_error if the log level is unknown | ||||||
|  |      */ | ||||||
|  |     ELogLevel::ELogLevel getLogLevel(const std::string & level) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the console text color enum from a string. | ||||||
|  |      * | ||||||
|  |      * @param colorName The color string to parse. | ||||||
|  |      * @return the corresponding console text color enum value | ||||||
|  |      * | ||||||
|  |      * @throws std::runtime_error if the log level is unknown | ||||||
|  |      */ | ||||||
|  |     EConsoleTextColor::EConsoleTextColor getConsoleColor(const std::string & colorName) const; | ||||||
|  | }; | ||||||
							
								
								
									
										126
									
								
								lib/Logging/CLogConsoleTarget.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								lib/Logging/CLogConsoleTarget.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CLogConsoleTarget.h" | ||||||
|  |  | ||||||
|  | #include "LogRecord.h" | ||||||
|  |  | ||||||
|  | CColorMapping::CColorMapping() | ||||||
|  | { | ||||||
|  |     // Set default mappings | ||||||
|  |     auto & levelMap = map[""]; | ||||||
|  |     levelMap[ELogLevel::TRACE] = EConsoleTextColor::GRAY; | ||||||
|  |     levelMap[ELogLevel::DEBUG] = EConsoleTextColor::WHITE; | ||||||
|  |     levelMap[ELogLevel::INFO] = EConsoleTextColor::GREEN; | ||||||
|  |     levelMap[ELogLevel::WARN] = EConsoleTextColor::YELLOW; | ||||||
|  |     levelMap[ELogLevel::ERROR] = EConsoleTextColor::RED; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CColorMapping::setColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level, EConsoleTextColor::EConsoleTextColor color) | ||||||
|  | { | ||||||
|  |     if(level == ELogLevel::NOT_SET) throw std::runtime_error("Log level NOT_SET not allowed for configuring the color mapping."); | ||||||
|  |     map[domain.getName()][level] = color; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | EConsoleTextColor::EConsoleTextColor CColorMapping::getColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level) const | ||||||
|  | { | ||||||
|  |     std::string name = domain.getName(); | ||||||
|  |     while(true) | ||||||
|  |     { | ||||||
|  |         const auto & loggerPair = map.find(name); | ||||||
|  |         if(loggerPair != map.end()) | ||||||
|  |         { | ||||||
|  |             const auto & levelMap = loggerPair->second; | ||||||
|  |             const auto & levelPair = levelMap.find(level); | ||||||
|  |             if(levelPair != levelMap.end()) | ||||||
|  |             { | ||||||
|  |                 return levelPair->second; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         CLoggerDomain currentDomain(name); | ||||||
|  |         if(!currentDomain.isGlobalDomain()) | ||||||
|  |         { | ||||||
|  |             name = currentDomain.getParent().getName(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     throw std::runtime_error("No color mapping found. Should not happen."); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(console), threshold(ELogLevel::INFO), coloredOutputEnabled(true) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogConsoleTarget::write(const LogRecord & record) | ||||||
|  | { | ||||||
|  |     if(threshold > record.level) return; | ||||||
|  |  | ||||||
|  |     std::string message = formatter.format(record); | ||||||
|  |     bool printToStdErr = record.level >= ELogLevel::WARN; | ||||||
|  |     if(console) | ||||||
|  |     { | ||||||
|  |         if(coloredOutputEnabled) | ||||||
|  |         { | ||||||
|  |             console->print(message, colorMapping.getColorFor(record.domain, record.level)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             console->print(message, EConsoleTextColor::DEFAULT, printToStdErr); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         TLockGuard _(mx); | ||||||
|  |         if(printToStdErr) | ||||||
|  |         { | ||||||
|  |             std::cerr << message << std::flush; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             std::cout << message << std::flush; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool CLogConsoleTarget::isColoredOutputEnabled() const | ||||||
|  | { | ||||||
|  |     return coloredOutputEnabled; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogConsoleTarget::setColoredOutputEnabled(bool coloredOutputEnabled) | ||||||
|  | { | ||||||
|  |     this->coloredOutputEnabled = coloredOutputEnabled; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ELogLevel::ELogLevel CLogConsoleTarget::getThreshold() const | ||||||
|  | { | ||||||
|  |     return threshold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogConsoleTarget::setThreshold(ELogLevel::ELogLevel threshold) | ||||||
|  | { | ||||||
|  |     this->threshold = threshold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const CLogFormatter & CLogConsoleTarget::getFormatter() const | ||||||
|  | { | ||||||
|  |     return formatter; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogConsoleTarget::setFormatter(const CLogFormatter & formatter) | ||||||
|  | { | ||||||
|  |     this->formatter = formatter; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const CColorMapping & CLogConsoleTarget::getColorMapping() const | ||||||
|  | { | ||||||
|  |     return colorMapping; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogConsoleTarget::setColorMapping(const CColorMapping & colorMapping) | ||||||
|  | { | ||||||
|  |     this->colorMapping = colorMapping; | ||||||
|  | } | ||||||
							
								
								
									
										147
									
								
								lib/Logging/CLogConsoleTarget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								lib/Logging/CLogConsoleTarget.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * CLogConsoleTarget.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 "ILogTarget.h" | ||||||
|  | #include "CLogger.h" | ||||||
|  | #include "CLogFormatter.h" | ||||||
|  | #include "CConsoleHandler.h" | ||||||
|  |  | ||||||
|  | class LogRecord; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The color mapping maps a logger name and a level to a specific color. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CColorMapping | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Constructor. There are default color mappings for the root logger, which child loggers inherit if not overriden. | ||||||
|  |      */ | ||||||
|  |     CColorMapping(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets a console text color for a logger name and a level. | ||||||
|  |      * | ||||||
|  |      * @param domain The domain of the logger. | ||||||
|  |      * @param level The logger level. | ||||||
|  |      * @param color The console text color to use as the mapping. | ||||||
|  |      */ | ||||||
|  |     void setColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level, EConsoleTextColor::EConsoleTextColor color); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets a console text color for a logger name and a level. | ||||||
|  |      * | ||||||
|  |      * @param domain The domain of the logger. | ||||||
|  |      * @param level The logger level. | ||||||
|  |      * @return the console text color which has been applied for the mapping | ||||||
|  |      */ | ||||||
|  |     EConsoleTextColor::EConsoleTextColor getColorFor(const CLoggerDomain & domain, ELogLevel::ELogLevel level) const; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** The color mapping, 1. Key: Logger domain, 2. Key: Level, Value: Color. */ | ||||||
|  |     std::map<std::string, std::map<ELogLevel::ELogLevel, EConsoleTextColor::EConsoleTextColor> > map; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The console target is a logging target which writes message to the console. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CLogConsoleTarget : public ILogTarget | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param console Optional. The console handler which is used to output messages to the console. | ||||||
|  |      */ | ||||||
|  |     explicit CLogConsoleTarget(CConsoleHandler * console); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Writes a log record. | ||||||
|  |      * | ||||||
|  |      * @param record The log record to write. | ||||||
|  |      */ | ||||||
|  |     void write(const LogRecord & record); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * True if colored output is enabled. | ||||||
|  |      * | ||||||
|  |      * @return true if colored output is enabled, false if not | ||||||
|  |      */ | ||||||
|  |     bool isColoredOutputEnabled() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the colored output flag. | ||||||
|  |      * | ||||||
|  |      * @param coloredOutput True if the log target should write colored messages to the console, false if not. | ||||||
|  |      */ | ||||||
|  |     void setColoredOutputEnabled(bool coloredOutputEnabled); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the threshold log level. | ||||||
|  |      * | ||||||
|  |      * @return the threshold log level | ||||||
|  |      */ | ||||||
|  |     ELogLevel::ELogLevel getThreshold() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the threshold log level. | ||||||
|  |      * | ||||||
|  |      * @param threshold The threshold log level. | ||||||
|  |      */ | ||||||
|  |     void setThreshold(ELogLevel::ELogLevel threshold); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the log formatter. | ||||||
|  |      * | ||||||
|  |      * @return The log formatter. | ||||||
|  |      */ | ||||||
|  |     const CLogFormatter & getFormatter() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the log formatter. | ||||||
|  |      * | ||||||
|  |      * @param formatter The log formatter. | ||||||
|  |      */ | ||||||
|  |     void setFormatter(const CLogFormatter & formatter); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the color mapping. | ||||||
|  |      */ | ||||||
|  |     const CColorMapping & getColorMapping() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the color mapping. | ||||||
|  |      * | ||||||
|  |      * @param colorMapping The color mapping. | ||||||
|  |      */ | ||||||
|  |     void setColorMapping(const CColorMapping & colorMapping); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** The console handler which is used to output messages to the console. */ | ||||||
|  |     CConsoleHandler * console; | ||||||
|  |  | ||||||
|  |     /** The threshold log level. */ | ||||||
|  |     ELogLevel::ELogLevel threshold; | ||||||
|  |  | ||||||
|  |     /** Flag whether colored console output is enabled. */ | ||||||
|  |     bool coloredOutputEnabled; | ||||||
|  |  | ||||||
|  |     /** The log formatter to log messages. */ | ||||||
|  |     CLogFormatter formatter; | ||||||
|  |  | ||||||
|  |     /** The color mapping which maps a logger and a log level to a color. */ | ||||||
|  |     CColorMapping colorMapping; | ||||||
|  |  | ||||||
|  |     /** The shared mutex for providing synchronous thread-safe access to the log console target. */ | ||||||
|  |     mutable boost::mutex mx; | ||||||
|  | }; | ||||||
							
								
								
									
										28
									
								
								lib/Logging/CLogFileTarget.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								lib/Logging/CLogFileTarget.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CLogFileTarget.h" | ||||||
|  |  | ||||||
|  | CLogFileTarget::CLogFileTarget(const std::string & filePath) : file(filePath) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLogFileTarget::~CLogFileTarget() | ||||||
|  | { | ||||||
|  |     file.close(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogFileTarget::write(const LogRecord & record) | ||||||
|  | { | ||||||
|  |     TLockGuard _(mx); | ||||||
|  |     file << formatter.format(record) << std::endl; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const CLogFormatter & CLogFileTarget::getFormatter() const | ||||||
|  | { | ||||||
|  |     return formatter; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogFileTarget::setFormatter(const CLogFormatter & formatter) | ||||||
|  | { | ||||||
|  |     this->formatter = formatter; | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								lib/Logging/CLogFileTarget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								lib/Logging/CLogFileTarget.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * CLogFileTarget.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 "ILogTarget.h" | ||||||
|  | #include "CLogFormatter.h" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The log file target is a logging target which writes messages to a log file. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CLogFileTarget : public ILogTarget | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param filePath The file path of the log file. | ||||||
|  |      */ | ||||||
|  |     explicit CLogFileTarget(const std::string & filePath); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Destructor. | ||||||
|  |      */ | ||||||
|  |     ~CLogFileTarget(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Writes a log record. | ||||||
|  |      * | ||||||
|  |      * @param record The log record to write. | ||||||
|  |      */ | ||||||
|  |     void write(const LogRecord & record); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the log formatter. | ||||||
|  |      * | ||||||
|  |      * @return The log formatter. | ||||||
|  |      */ | ||||||
|  |     const CLogFormatter & getFormatter() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the log formatter. | ||||||
|  |      * | ||||||
|  |      * @param formatter The log formatter. | ||||||
|  |      */ | ||||||
|  |     void setFormatter(const CLogFormatter & formatter); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** The output file stream. */ | ||||||
|  |     std::ofstream file; | ||||||
|  |  | ||||||
|  |     /** The log formatter to log messages. */ | ||||||
|  |     CLogFormatter formatter; | ||||||
|  |  | ||||||
|  |     /** The shared mutex for providing synchronous thread-safe access to the log file target. */ | ||||||
|  |     mutable boost::mutex mx; | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										65
									
								
								lib/Logging/CLogFormatter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								lib/Logging/CLogFormatter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CLogFormatter.h" | ||||||
|  |  | ||||||
|  | #include "LogRecord.h" | ||||||
|  |  | ||||||
|  | CLogFormatter::CLogFormatter() : pattern("%m") | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLogFormatter::CLogFormatter(const std::string & pattern) : pattern(pattern) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string CLogFormatter::format(const LogRecord & record) const | ||||||
|  | { | ||||||
|  |     std::string message = pattern; | ||||||
|  |  | ||||||
|  |     // Format date | ||||||
|  |     std::stringstream dateStream; | ||||||
|  |     boost::posix_time::time_facet * facet = new boost::posix_time::time_facet("%d-%b-%Y %H:%M:%S"); | ||||||
|  |     dateStream.imbue(std::locale(dateStream.getloc(), facet)); | ||||||
|  |     dateStream << record.timeStamp; | ||||||
|  |     boost::algorithm::replace_all(message, "%d", dateStream.str()); | ||||||
|  |  | ||||||
|  |     // Format log level | ||||||
|  |     std::string level; | ||||||
|  |     switch(record.level) | ||||||
|  |     { | ||||||
|  |     case ELogLevel::TRACE: | ||||||
|  |         level = "TRACE"; | ||||||
|  |         break; | ||||||
|  |     case ELogLevel::DEBUG: | ||||||
|  |         level = "DEBUG"; | ||||||
|  |         break; | ||||||
|  |     case ELogLevel::INFO: | ||||||
|  |         level = "INFO"; | ||||||
|  |         break; | ||||||
|  |     case ELogLevel::WARN: | ||||||
|  |         level = "WARN"; | ||||||
|  |         break; | ||||||
|  |     case ELogLevel::ERROR: | ||||||
|  |         level = "ERROR"; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     boost::algorithm::replace_all(message, "%l", level); | ||||||
|  |  | ||||||
|  |     // Format name, thread id and message | ||||||
|  |     boost::algorithm::replace_all(message, "%n", record.domain.getName()); | ||||||
|  |     boost::algorithm::replace_all(message, "%t", boost::lexical_cast<std::string>(record.threadId)); | ||||||
|  |     boost::algorithm::replace_all(message, "%m", record.message); | ||||||
|  |  | ||||||
|  |     return message; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogFormatter::setPattern(const std::string & pattern) | ||||||
|  | { | ||||||
|  |     this->pattern = pattern; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const std::string & CLogFormatter::getPattern() const | ||||||
|  | { | ||||||
|  |     return pattern; | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								lib/Logging/CLogFormatter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								lib/Logging/CLogFormatter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * CLogFormatter.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 | ||||||
|  |  | ||||||
|  | class LogRecord; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The log formatter 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: | ||||||
|  |     /** | ||||||
|  |      * Default constructor. | ||||||
|  |      */ | ||||||
|  |     CLogFormatter(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param pattern The pattern to format the log record with. | ||||||
|  |      */ | ||||||
|  |     CLogFormatter(const std::string & pattern); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Formats a log record. | ||||||
|  |      * | ||||||
|  |      * @param record The log record to format. | ||||||
|  |      * @return the formatted log record as a string | ||||||
|  |      */ | ||||||
|  |     std::string format(const LogRecord & record) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the pattern. | ||||||
|  |      * | ||||||
|  |      * @param pattern The pattern string which describes how to format the log record. | ||||||
|  |      */ | ||||||
|  |     void setPattern(const std::string & pattern); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the pattern. | ||||||
|  |      * | ||||||
|  |      * @return the pattern string which describes how to format the log record | ||||||
|  |      */ | ||||||
|  |     const std::string & getPattern() const; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** The pattern string which describes how to format the log record. */ | ||||||
|  |     std::string pattern; | ||||||
|  | }; | ||||||
							
								
								
									
										51
									
								
								lib/Logging/CLogManager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								lib/Logging/CLogManager.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CLogManager.h" | ||||||
|  |  | ||||||
|  | #include "CLogger.h" | ||||||
|  |  | ||||||
|  | CLogManager * CLogManager::instance = nullptr; | ||||||
|  |  | ||||||
|  | boost::mutex CLogManager::smx; | ||||||
|  |  | ||||||
|  | CLogManager * CLogManager::get() | ||||||
|  | { | ||||||
|  |     TLockGuard _(smx); | ||||||
|  |     if(!instance) | ||||||
|  |     { | ||||||
|  |         instance = new CLogManager(); | ||||||
|  |     } | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLogManager::CLogManager() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLogManager::~CLogManager() | ||||||
|  | { | ||||||
|  |     BOOST_FOREACH(auto & i, loggers) | ||||||
|  |     { | ||||||
|  |         delete i.second; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CLogManager::addLogger(CGLogger * logger) | ||||||
|  | { | ||||||
|  |     TWriteLock _(mx); | ||||||
|  |     loggers[logger->getDomain().getName()] = logger; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CGLogger * CLogManager::getLogger(const CLoggerDomain & domain) | ||||||
|  | { | ||||||
|  |     TReadLock _(mx); | ||||||
|  |     auto it = loggers.find(domain.getName()); | ||||||
|  |     if(it != loggers.end()) | ||||||
|  |     { | ||||||
|  |         return it->second; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								lib/Logging/CLogManager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lib/Logging/CLogManager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * CLogManager.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 | ||||||
|  |  | ||||||
|  | class CGLogger; | ||||||
|  | class CLoggerDomain; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The log manager is a global storage of all logger objects. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CLogManager : public boost::noncopyable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Gets an instance of the log manager. | ||||||
|  |      * | ||||||
|  |      * @return an instance of the log manager | ||||||
|  |      */ | ||||||
|  |     static CLogManager * get(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Adds a logger. The log manager holds strong ownership of the logger object. | ||||||
|  |      * | ||||||
|  |      * @param logger The logger to add. | ||||||
|  |      */ | ||||||
|  |     void addLogger(CGLogger * logger); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets a logger by domain. | ||||||
|  |      * | ||||||
|  |      * @param domain The domain of the logger. | ||||||
|  |      * @return a logger by domain or nullptr if the logger was not found | ||||||
|  |      */ | ||||||
|  |     CGLogger * getLogger(const CLoggerDomain & domain); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Destructor. | ||||||
|  |      */ | ||||||
|  |     ~CLogManager(); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      */ | ||||||
|  |     CLogManager(); | ||||||
|  |  | ||||||
|  |     /** The instance of the log manager. */ | ||||||
|  |     static CLogManager * instance; | ||||||
|  |  | ||||||
|  |     /** The loggers map where the key is the logger name and the value the corresponding logger. */ | ||||||
|  |     std::map<std::string, CGLogger *> loggers; | ||||||
|  |  | ||||||
|  |     /** The shared mutex for providing synchronous thread-safe access to the log manager. */ | ||||||
|  |     mutable boost::shared_mutex mx; | ||||||
|  |  | ||||||
|  |     /** The unique mutex for providing thread-safe singleton access. */ | ||||||
|  |     static boost::mutex smx; | ||||||
|  | }; | ||||||
							
								
								
									
										165
									
								
								lib/Logging/CLogger.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								lib/Logging/CLogger.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | |||||||
|  | #include "StdInc.h" | ||||||
|  | #include "CLogger.h" | ||||||
|  | #include "LogRecord.h" | ||||||
|  | #include "ILogTarget.h" | ||||||
|  | #include "CLogManager.h" | ||||||
|  |  | ||||||
|  | boost::mutex CGLogger::smx; | ||||||
|  |  | ||||||
|  | const std::string CLoggerDomain::DOMAIN_GLOBAL = "global"; | ||||||
|  |  | ||||||
|  | CLoggerDomain::CLoggerDomain(const std::string & name) : name(name) | ||||||
|  | { | ||||||
|  |     if(name.empty()) throw std::runtime_error("Logger domain cannot be empty."); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CLoggerDomain CLoggerDomain::getParent() const | ||||||
|  | { | ||||||
|  |     if(isGlobalDomain()) return *this; | ||||||
|  |  | ||||||
|  |     size_t pos = name.find_last_of("."); | ||||||
|  |     if(pos != std::string::npos) | ||||||
|  |     { | ||||||
|  |         return CLoggerDomain(name.substr(0, pos)); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         return CLoggerDomain(DOMAIN_GLOBAL); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool CLoggerDomain::isGlobalDomain() const | ||||||
|  | { | ||||||
|  |     return name == DOMAIN_GLOBAL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string CLoggerDomain::getName() const | ||||||
|  | { | ||||||
|  |     return name; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CGLogger * CGLogger::getLogger(const CLoggerDomain & domain) | ||||||
|  | { | ||||||
|  |     TLockGuard _(smx); | ||||||
|  |     CGLogger * logger = CLogManager::get()->getLogger(domain); | ||||||
|  |     if(logger) | ||||||
|  |     { | ||||||
|  |         return logger; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         logger = new CGLogger(domain); | ||||||
|  |         if(domain.isGlobalDomain()) | ||||||
|  |         { | ||||||
|  |             logger->setLevel(ELogLevel::INFO); | ||||||
|  |         } | ||||||
|  |         CLogManager::get()->addLogger(logger); | ||||||
|  |         return logger; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CGLogger * CGLogger::getGlobalLogger() | ||||||
|  | { | ||||||
|  |     return getLogger(CLoggerDomain::DOMAIN_GLOBAL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CGLogger::CGLogger(const CLoggerDomain & domain) : domain(domain), level(ELogLevel::INFO) | ||||||
|  | { | ||||||
|  |     if(!domain.isGlobalDomain()) | ||||||
|  |     { | ||||||
|  |         parent = getLogger(domain.getParent()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CGLogger::~CGLogger() | ||||||
|  | { | ||||||
|  |     BOOST_FOREACH(ILogTarget * target, targets) | ||||||
|  |     { | ||||||
|  |         delete target; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::trace(const std::string & message) const | ||||||
|  | { | ||||||
|  |     log(ELogLevel::TRACE, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::debug(const std::string & message) const | ||||||
|  | { | ||||||
|  |     log(ELogLevel::DEBUG, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::info(const std::string & message) const | ||||||
|  | { | ||||||
|  |     log(ELogLevel::INFO, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::warn(const std::string & message) const | ||||||
|  | { | ||||||
|  |     log(ELogLevel::WARN, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::error(const std::string & message) const | ||||||
|  | { | ||||||
|  |     log(ELogLevel::ERROR, message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::log(ELogLevel::ELogLevel level, const std::string & message) const | ||||||
|  | { | ||||||
|  |     if(getEffectiveLevel() <= level) | ||||||
|  |     { | ||||||
|  |         callTargets(LogRecord(domain, level, message)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ELogLevel::ELogLevel CGLogger::getLevel() const | ||||||
|  | { | ||||||
|  |     TReadLock _(mx); | ||||||
|  |     return level; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::setLevel(ELogLevel::ELogLevel level) | ||||||
|  | { | ||||||
|  |     TWriteLock _(mx); | ||||||
|  |     if(domain.isGlobalDomain() && level == ELogLevel::NOT_SET) return; | ||||||
|  |     this->level = level; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const CLoggerDomain & CGLogger::getDomain() const | ||||||
|  | { | ||||||
|  |     return domain; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::addTarget(ILogTarget * target) | ||||||
|  | { | ||||||
|  |     TWriteLock _(mx); | ||||||
|  |     targets.push_back(target); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::list<ILogTarget *> CGLogger::getTargets() const | ||||||
|  | { | ||||||
|  |     TReadLock _(mx); | ||||||
|  |     return targets; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ELogLevel::ELogLevel CGLogger::getEffectiveLevel() const | ||||||
|  | { | ||||||
|  |     for(const CGLogger * logger = this; logger != nullptr; logger = logger->parent) | ||||||
|  |     { | ||||||
|  |         if(logger->getLevel() != ELogLevel::NOT_SET) return logger->getLevel(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // This shouldn't be reached, as the root logger must have set a log level | ||||||
|  |     return ELogLevel::INFO; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CGLogger::callTargets(const LogRecord & record) const | ||||||
|  | { | ||||||
|  |     for(const CGLogger * logger = this; logger != nullptr; logger = logger->parent) | ||||||
|  |     { | ||||||
|  |         BOOST_FOREACH(ILogTarget * target, logger->getTargets()) | ||||||
|  |         { | ||||||
|  |             target->write(record); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										230
									
								
								lib/Logging/CLogger.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								lib/Logging/CLogger.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * 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 | ||||||
|  |  | ||||||
|  | class CGLogger; | ||||||
|  | class LogRecord; | ||||||
|  | class ILogTarget; | ||||||
|  |  | ||||||
|  | namespace ELogLevel | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * The log level enum holds various log level definitions. | ||||||
|  |      */ | ||||||
|  |     enum ELogLevel | ||||||
|  |     { | ||||||
|  |         NOT_SET = 0, | ||||||
|  |         TRACE, | ||||||
|  |         DEBUG, | ||||||
|  |         INFO, | ||||||
|  |         WARN, | ||||||
|  |         ERROR | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The logger domain provides convenient access to super domains from a sub domain. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CLoggerDomain | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param domain The domain name. Sub-domains can be specified by separating domains by a dot, e.g. "ai.battle". The global domain is named "global". | ||||||
|  |      */ | ||||||
|  |     CLoggerDomain(const std::string & name); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the parent logger domain. | ||||||
|  |      * | ||||||
|  |      * @return the parent logger domain or the same domain logger if this method has been called on the global domain | ||||||
|  |      */ | ||||||
|  |     CLoggerDomain getParent() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns true if this domain is the global domain. | ||||||
|  |      * | ||||||
|  |      * @return true if this is the global domain or false if not | ||||||
|  |      */ | ||||||
|  |     bool isGlobalDomain() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the name of the domain. | ||||||
|  |      * | ||||||
|  |      * @return the name of the domain | ||||||
|  |      */ | ||||||
|  |     std::string getName() const; | ||||||
|  |  | ||||||
|  |     /** Constant to the global domain name. */ | ||||||
|  |     static const std::string DOMAIN_GLOBAL; | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** The domain name. */ | ||||||
|  |     std::string name; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The logger is used to log messages to certain targets of a specific domain/name. Temporary name is | ||||||
|  |  * CGLogger, should be renamed to CLogger after refactoring. | ||||||
|  |  */ | ||||||
|  | class DLL_LINKAGE CGLogger : public boost::noncopyable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     /** | ||||||
|  |      * Gets a logger by domain. | ||||||
|  |      * | ||||||
|  |      * @param domain The logger domain. | ||||||
|  |      * @return the logger object | ||||||
|  |      */ | ||||||
|  |     static CGLogger * getLogger(const CLoggerDomain & domain); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the global logger which is the parent of all domain-specific loggers. | ||||||
|  |      * | ||||||
|  |      * @return the global logger object | ||||||
|  |      */ | ||||||
|  |     static CGLogger * getGlobalLogger(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message with the trace level. | ||||||
|  |      * | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     void trace(const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message with the debug level. | ||||||
|  |      * | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     void debug(const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message with the info level. | ||||||
|  |      * | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     void info(const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message with the warn level. | ||||||
|  |      * | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     void warn(const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message with the error level. | ||||||
|  |      * | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     void error(const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the log level applied for this logger. The default level for the root logger is INFO. | ||||||
|  |      * | ||||||
|  |      * @return the log level | ||||||
|  |      */ | ||||||
|  |     inline ELogLevel::ELogLevel getLevel() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Sets the log level. | ||||||
|  |      * | ||||||
|  |      * @param level The log level. | ||||||
|  |      */ | ||||||
|  |     void setLevel(ELogLevel::ELogLevel level); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the logger domain. | ||||||
|  |      * | ||||||
|  |      * @return the domain of the logger | ||||||
|  |      */ | ||||||
|  |     const CLoggerDomain & getDomain() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Adds a target to this logger and indirectly to all loggers which derive from this logger. | ||||||
|  |      * The logger holds strong-ownership of the target object. | ||||||
|  |      * | ||||||
|  |      * @param target The log target to add. | ||||||
|  |      */ | ||||||
|  |     void addTarget(ILogTarget * target); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Destructor. | ||||||
|  |      */ | ||||||
|  |     ~CGLogger(); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param domain The domain of the logger. | ||||||
|  |      */ | ||||||
|  |     explicit CGLogger(const CLoggerDomain & domain); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the parent logger. | ||||||
|  |      * | ||||||
|  |      * @return the parent logger or nullptr if this is the root logger | ||||||
|  |      */ | ||||||
|  |     CGLogger * getParent() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Logs a message of the given log level. | ||||||
|  |      * | ||||||
|  |      * @param level The log level of the message to log. | ||||||
|  |      * @param message The message to log. | ||||||
|  |      */ | ||||||
|  |     inline void log(ELogLevel::ELogLevel level, const std::string & message) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the effective log level. | ||||||
|  |      * | ||||||
|  |      * @return the effective log level with respect to parent log levels | ||||||
|  |      */ | ||||||
|  |     inline ELogLevel::ELogLevel getEffectiveLevel() const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Calls all targets in the hierarchy to write the message. | ||||||
|  |      * | ||||||
|  |      * @param record The log record to write. | ||||||
|  |      */ | ||||||
|  |     inline void callTargets(const LogRecord & record) const; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets all log targets attached to this logger. | ||||||
|  |      * | ||||||
|  |      * @return all log targets as a list | ||||||
|  |      */ | ||||||
|  |     inline std::list<ILogTarget *> getTargets() const; | ||||||
|  |  | ||||||
|  |     /** The domain of the logger. */ | ||||||
|  |     CLoggerDomain domain; | ||||||
|  |  | ||||||
|  |     /** A reference to the parent logger. */ | ||||||
|  |     CGLogger * parent; | ||||||
|  |  | ||||||
|  |     /** The log level of the logger. */ | ||||||
|  |     ELogLevel::ELogLevel level; | ||||||
|  |  | ||||||
|  |     /** A list of log targets. */ | ||||||
|  |     std::list<ILogTarget *> targets; | ||||||
|  |  | ||||||
|  |     /** The shared mutex for providing synchronous thread-safe access to the logger. */ | ||||||
|  |     mutable boost::shared_mutex mx; | ||||||
|  |  | ||||||
|  |     /** The unique mutex for providing thread-safe get logger access. */ | ||||||
|  |     static boost::mutex smx; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //extern CLogger * logGlobal; | ||||||
							
								
								
									
										31
									
								
								lib/Logging/ILogTarget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/Logging/ILogTarget.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * LogRecord.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 | ||||||
|  |  | ||||||
|  | class LogRecord; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The interface log target 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: | ||||||
|  |     /** | ||||||
|  |      * Writes a log record. | ||||||
|  |      * | ||||||
|  |      * @param record The log record to write. | ||||||
|  |      */ | ||||||
|  |     virtual void write(const LogRecord & record) = 0; | ||||||
|  |  | ||||||
|  |     virtual ~ILogTarget() { }; | ||||||
|  | }; | ||||||
							
								
								
									
										44
									
								
								lib/Logging/LogRecord.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								lib/Logging/LogRecord.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * LogRecord.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 "CLogger.h" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The log records holds the log message and additional logging information. | ||||||
|  |  */ | ||||||
|  | struct DLL_LINKAGE LogRecord | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      */ | ||||||
|  |     LogRecord(const CLoggerDomain & domain, ELogLevel::ELogLevel level, const std::string & message) | ||||||
|  |         : domain(domain), level(level), message(message), timeStamp(boost::posix_time::second_clock::local_time()), threadId(boost::this_thread::get_id()) | ||||||
|  |     { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** The logger domain. */ | ||||||
|  |     CLoggerDomain domain; | ||||||
|  |  | ||||||
|  |     /** The log level. */ | ||||||
|  |     ELogLevel::ELogLevel level; | ||||||
|  |  | ||||||
|  |     /** The message. */ | ||||||
|  |     std::string message; | ||||||
|  |  | ||||||
|  |     /** The time when the message was created. */ | ||||||
|  |     boost::posix_time::ptime timeStamp; | ||||||
|  |  | ||||||
|  |     /** The thread id. */ | ||||||
|  |     boost::thread::id threadId; | ||||||
|  | }; | ||||||
		Reference in New Issue
	
	Block a user