//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Логирование информации. \en Information logging. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __TOOL_LOG_H #define __TOOL_LOG_H #include #include #include namespace c3d //namespace c3d { //------------------------------------------------------------------------------ // \ru Потокобезопасные интерфейсы для ведения журнала сообщений и записи его в файл. // Для каждого потока ведется отдельный лог. // Затем накопленные сообщения, сортированные по потокам записываются в файл. // Интерфейсы доступны в дебаге. // \en Thread-safe interfaces for logging messages and writing the log to the file. // A separate log is maintained for each thread. // The collected messages, sorted by threads, are then written to a file. // The interfaces are available in debug configuration. // /* \ru Пример использования. int k = 0; SetLogDir( _T("C:\\AnoherDir") ); // Меняем умолчательную директорию для лог-файлов. START_LOGGING; // Начинаем логирование. LOG_MSG( _T("My sample log") ); // Добавляем указанную строку в лог. ... // Форматируем строку лога и добавляем ее в лог с помощью оператора << Logger::Endl. c3d::Logger::Get() << _T("Value: ") << k << Logger::Endl; ... WRITE_LOG_FILE( _T("sample") ); // Записываем лог в файл sample.log. END_LOGGING; // Отключаем логирование. \en Usage sample. int k = 0; SetLogDir( _T("C:\\AnoherDir") ); // Change default directory for log-files. START_LOGGING; // Start logging. LOG_MSG( _T("My sample log") ); // Put a specified string to the log. ... // Format a log line and puts it to the log using operator << Logger::Endl. c3d::Logger::Get() << _T("Value: ") << k << Logger::Endl; ... WRITE_LOG_FILE( _T("sample") ); // Write the log to the file sample.log. END_LOGGING; // Stop logging. */ // --- //------------------------------------------------------------------------------ // \ru Класс позволяет форматировать строку для лога и добавлять ее в лог. // \en Class allows to format a line to the log and put it to the log. // --- class MATH_CLASS Logger { public: // \ru Тип сообщения. \en The message type. enum MsgType { ms_info, ms_warn, ms_err }; public: // \ru Получить логгер. \en Get the logger. static Logger & Get(); // \ru Следующие методы позволяют форматировать строку для лога. Работают с текущей строкой лога. // \en Next methods can be used to format a log line. Work with the current line of the log. #ifdef _UNICODE // \ru Добавить строку в текущую строку лога. \en Add a string to the current line of the log. virtual Logger & operator << ( const TCHAR * ) = 0; #endif // \ru Добавить строку в текущую строку лога. \en Add a string to the current line of the log. virtual Logger & operator << ( const char * ) = 0; // \ru Добавить integer в текущую строку лога. \en Add integer to the current line of the log. virtual Logger & operator << ( const int & ) = 0; #if defined(PLATFORM_64) // \ru x32 совпадение типов ptrdiff_t и int \en x32 coincidence of ptrdiff_t and int types // \ru Добавить ptrdiff_t в текущую строку лога. \en Add ptrdiff_t to the current line of the log. virtual Logger & operator << ( const ptrdiff_t & ) = 0; #endif // \ru Добавить size_t в текущую строку лога. \en Add size_t to the current line of the log. virtual Logger & operator << ( const size_t & ) = 0; // \ru Добавить double в текущую строку лога. \en Add double to the current line of the log. virtual Logger & operator << ( const double & ) = 0; // \ru Добавить признак тип сообщения в текущую строку лога. \en Add message type to the current line of the log. virtual Logger & operator << ( MsgType type ) = 0; // \ru Завершить форматирование текущей строки и добавить ее в лог. Следующий вызов оператора << создаст новую текущую строку. // \en Finish formatting of the current line and add it to the log. Next call to the operator << will create new current line. virtual Logger & operator << ( Logger& (*man)( Logger& ) ) = 0; // \ru Манипулятор-признак завершения форматирования текущей строки лога. // \en Manipulator-indicator of finishing formatting of the current line of the log. static Logger & Endl( Logger& ); }; //------------------------------------------------------------------------------ /** \brief \ru Переключатель логирования в области видимости. \en Logging switch in a scope. \~ \details \ru Вспомогательный класс для логирования в области видимости. В конструкторе логирование включается, в деструкторе - отключается. Если в конструкторе было указано имя файла, то перед отключением логирования деструктор записывает накопленный лог в файл. \en Helper class for the logging in the scope. The logging starts in the constructor and ends in the destructor. If a file name was defined in the constructor, then before ending the logging, the destructor writes the collected log to the file. \ru Пример использования: { // Начинаем логирование, лог будет записан в файл myLogFile.log. c3d::LogHelper log( true, _T("myLogFile") ); // Добавляем указанную строку в лог. LOG_MSG( _T("My formatted message") ); ... // Форматируем строку лога и добавляем ее в лог с помощью оператора << Logger::Endl. c3d::Logger::Get() << _T("Value ") << k << Logger::Endl; ... } // При выходе из области кода логирование заканчивается и лог записывается в файл. \en Example of use: { // Start logging, the log will be written to the file myLogFile.log. c3d::LogHelper log( true, _T("myLogFile") ); // Put a specified string to the log. LOG_MSG( _T("My formatted message") ); ... // Format a log line and put it to the log using the operator << Logger::Endl. c3d::Logger::Get() << _T("Value ") << k << Logger::Endl; ... } // When leaving the code scope the logging stops and the log is written to the file. \ingroup Base_Tools */ // --- class MATH_CLASS LogHelper { #ifdef C3D_DEBUG bool _enabled; c3d::string_t _file; #endif public: #ifdef C3D_DEBUG // \ru Параметр enable определяет, стартовать ли логирование. // \en The enable parameter defines whether to start logging. LogHelper( bool enable = true, const TCHAR* file = nullptr ); // \ru Если в конструкторе было указано имя файла, то деструктор записывает накопленный лог в файл. // \en If a file name was defined in the contructor, the destructor writes the collected log to the file. \~ ~LogHelper(); #else LogHelper( bool, const TCHAR * ) {} ~LogHelper() {} #endif }; #ifdef C3D_DEBUG //------------------------------------------------------------------------------ // \ru Функции логирования. \en Logging functions. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /** \brief \ru Установить директорию для логов. \en Set log directory. \~ \details \ru По умолчанию лог-файлы сохраняются в директорию, установленную переменной LOG_PATH. Функция позволяет изменить директорию для логов. \en By default log-files are saved to the directory< defined by LOG_PATH variable. The function allows changing the directory for logs. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) SetLogDir( const TCHAR * name ); //------------------------------------------------------------------------------ /** \brief \ru Начать или закончить логирование. \en Start or stop logging. \~ \details \ru Начать или закончить логирование. \en Start or stop logging. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) SetLogging( bool enable ); //------------------------------------------------------------------------------ /** \brief \ru Записать лог в файл. \en Write the log to the file. \~ \details \ru Записываются в файл сообщения, сортированные по потокам. \en Write messages, sorted by threads, to the file. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) WriteLog( const TCHAR *fileName ); //------------------------------------------------------------------------------ /** \brief \ru Записать указанную строку в лог. \en Write a specified string to the log. \~ \details \ru Записать указанную строку в лог. \en Write a specified string to the log. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) LogMessage( const c3d::string_t &msg ); //------------------------------------------------------------------------------ /** \brief \ru Записать указанную строку и тип сообщения в лог. \en Write a specified string and the message type to the log. \~ \details \ru Записать указанную строку и тип сообщения в лог. \en Write a specified string and the message type to the log. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) LogMessage( const c3d::string_t &msg, Logger::MsgType type ); //------------------------------------------------------------------------------ // \ru Макросы для операций логирования. \en Logging macros. //------------------------------------------------------------------------------ // \ru Информация о месте. \en The place information. #ifdef C3D_WINDOWS #define __LOCATION__ __FILE__ "(" __DEFTOSTR__(__LINE__) "): function " __FUNCTION__ "(): " #else inline std::string __location() { std::string s( __FILE__ "(" __DEFTOSTR__( __LINE__ ) "): function " ); return s + std::string( __PRETTY_FUNCTION__ ) + "(): "; } #define __LOCATION__ __location().c_str() #endif // \ru Начать логирование. \en Start logging. #define START_LOGGING c3d::SetLogging( true ); // \ru Закончить логирование. \en Stop logging. #define END_LOGGING c3d::SetLogging( false ); // \ru Записать лог в файл. Лог для каждого потока записывается в отдельный файл. // \en Write the log to the file. Log of each thread writes to a separate file. #define WRITE_LOG_FILE(fileName) c3d::WriteLog( fileName ); // \ru Положить в лог форматированную строку. \en Put a formatted string to the log. #define LOG_MSG(msg) c3d::LogMessage( msg ); // \ru Положить в лог форматированную строку с указанием места. \en Put a formatted string with the place info to the log. #define LOG_MSG_PLACE(msg) c3d::Logger::Get() << __LOCATION__ << msg << Logger::Endl; // \ru Положить в лог форматированную строку с типом сообщения и указанием места. \en Put a formatted string with the message type and the place to the log. #define LOG_MSG_PLACE_TYPE(msg,type) c3d::Logger::Get() << __LOCATION__ << type << msg << Logger::Endl; #else //------------------------------------------------------------------------------ // \ru Логирование работает только в Debug. \en Logging works in Debug Only. //------------------------------------------------------------------------------ inline void CALL_DECLARATION SetLogDir( const TCHAR * ) {} inline void CALL_DECLARATION SetLogging( bool ){} inline void CALL_DECLARATION WriteLog( const TCHAR * ){} inline void CALL_DECLARATION LogMessage( const c3d::string_t & ){} inline void CALL_DECLARATION LogMessage( const c3d::string_t &, Logger::MsgType ){} #define __LOCATION__ "" #define START_LOGGING c3d::SetLogging( true ); #define END_LOGGING c3d::SetLogging( false ); #define WRITE_LOG_FILE(fileName) c3d::WriteLog( fileName ); #define LOG_MSG(msg) c3d::LogMessage( msg ); #define LOG_MSG_PLACE(msg) LOG_MSG(msg) #define LOG_MSG_PLACE_TYPE(msg,type) LOG_MSG(msg) #endif //------------------------------------------------------------------------------ /** \brief \ru Включить контроль утечек памяти. \en Enable memory leakage control. \~ \details \ru Включить контроль утечек памяти. \en Enable memory leakage control. \~ \ingroup Base_Tools */ // --- MATH_FUNC(void) EnableMemoryLeakDump(); } //namespace c3d #endif // __TOOL_LOG_H