/***********************************//** * @file log4vendor.h * @email guifaliao@gmail.com * @version 0.0.0.2 * @date 2020-08-26 * @copyright China Merchants Bank Co.,Ltd All rights reserved * * @brief Log class for VTM device vendor for developing device adapter * @details * 2020-4-28: strip log component from SpAgent Project and adjust it. * 2020-11-11: add log_init_config_c structure and new init api: log4vendor::initp **************************************/ #ifndef _VTM_LOG4VENDOR_H_ #define _VTM_LOG4VENDOR_H_ #pragma once #include #include #include #ifdef _WIN32 #ifdef LIBLOG4VENDOR_EXPORTS #define LOG4VENDOR_API __declspec(dllexport) #else #define LOG4VENDOR_API __declspec(dllimport) #endif #else #if ( defined(__GNUC__) && __GNUC__ >= 4 ) #define LOG4VENDOR_API __attribute__((visibility("default"))) #else #define LOG4VENDOR_API #endif #endif #ifdef UNICODE #error This version is not support {UNICODE} char set!! #define LOG4VTM_TEXT2(STRING) L##STRING typedef std::wstring vtm_string; typedef wchar_t vtm_char; #else #define LOG4VTM_TEXT2(STRING) STRING typedef std::string vtm_string; typedef char vtm_char; #endif // UNICODE #define LOG4VTM_TEXT(STRING) LOG4VTM_TEXT2(STRING) #ifndef RVC_VENDOE_BUILDIN_TYPE #if (defined(_WIN32) || defined(_WIN64)) typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef unsigned long* PDWORD; #else typedef uint8_t BYTE; typedef uint8_t* LPBYTE; typedef uint16_t WORD; typedef uint32_t DWORD; typedef uint32_t* PDWORD; typedef char CHAR; #endif #define RVC_VENDOE_BUILDIN_TYPE #endif // !RVC_VENDOE_BUILDIN_TYPE #if defined(_MSC_VER) #define LOG4VTM_START_DOWHILE_WARNING() \ __pragma (warning (push)) \ __pragma (warning (disable:4127)) #define LOG4VTM_END_DOWHILE_WARNING() \ __pragma (warning (pop)) #else #define LOG4VTM_START_DOWHILE_WARNING() #define LOG4VTM_END_DOWHILE_WARNING() #endif #define CMB_LOG_TYPE_CONSOLE 1 /*控制台输出*/ #define CMB_LOG_TYPE_FILE 2 /*文件记录输出*/ #define CMB_LOG_TYPE_SOCKET 4 /*TCP传输输出,暂未实现*/ #define CMB_LOG_LEVEL_OFF 6 /*关闭任何日志输出*/ #define CMB_LOG_LEVEL_FATAL 5 /*非常严重类型的日志输出*/ #define CMB_LOG_LEVEL_ERROR 4 /*错误类型的日志输出*/ #define CMB_LOG_LEVEL_WARN 3 /*告警类型的日志输出*/ #define CMB_LOG_LEVEL_INFO 2 /*普通日志输出*/ #define CMB_LOG_LEVEL_DEBUG 1 /*调试日志输出*/ #define CMB_LOG_LEVEL_TRACE 0 /*跟踪函数进出等输出*/ #define CMB_LOG_LEVEL_ALL CMB_LOG_LEVEL_TRACE #define CMB_LOG_TRACE 1 #define CMB_LOG_DEBUG 2 #define CMB_LOG_INFO 3 #define CMB_LOG_WARN 4 #define CMB_LOG_ERROR 5 #define CMB_LOG_FATAL 6 //#define CMB_LOG_ASSERT 7 #define CMB_INSTANTIATE_OSTRINGSTREAM(var) \ std::basic_ostringstream& var \ = cmb::log4vendor::get_oss() #define CMB_LOG_BODY(logLevel, logEvent) \ LOG4VTM_START_DOWHILE_WARNING() \ do { \ cmb::log4vendor* _l \ = cmb::log4vendor::instance(); \ CMB_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \ _log4cplus_buf << logEvent; \ _l->log(logLevel, _log4cplus_buf.str()); \ } while (0) \ LOG4VTM_END_DOWHILE_WARNING() /*! * @brief 打印日志的函数,所有等级的日志打印均通过该宏调用实现 * @param[in] * severity: 日志等级 TRACE, INFO, WARN, ERROR, FATAL, ASSERT * ostr: 要打印的内容,支持 << 连续输出 */ #define LOG4VTM(severity, ostr) \ CMB_LOG_BODY(CMB_LOG_ ## severity, ostr) /*! * @brief: 用于记录函数进出的宏定义,在进入目的函数时立即调用,在该函数退出时会打印日志 */ #define LOG4VTM_FUNCTION() cmb::log4vendor_tracer _FunctionTraceLogger(\ __FUNCTION__, cmb::log4vendor_tracer::_get_file_name(__FILE__), __LINE__) /*! * @brief 类似于 LOG4VTM_FUNCTION(),除外还添加一个入参用于打印返回值,注意该入参的生命周期为整个函数内!! * @param[in]: pValue - 仅支持传入 int* 或 DWORD* 类型,在日志中会打印指针所存储的值 */ #define TRACE4VTM_FUNCTION(pValue) cmb::log4vendor_tracer _FunctionTraceLogger(\ __FUNCTION__, cmb::log4vendor_tracer::_get_file_name(__FILE__), __LINE__, (pValue)) #define VENDOR_BUFF_SIZE 256 namespace cmb { struct log_init_config_c { short log_type; /*见上面 CMB_LOG_TYPE_FILE 等定义*/ short log_level; /*见上面 CMB_LOG_TRACE 等定义*/ char dev_name[VENDOR_BUFF_SIZE]; /*硬件名称,用于作为子目录的区分*/ char log_dir[VENDOR_BUFF_SIZE]; /*在 log_type 包含 CMB_LOG_TYPE_FILE 时,该参数才有效,用于记录日志的目录*/ }; struct LOG4VENDOR_API log_init_config { short log_type; /*见上面 CMB_LOG_TYPE_FILE 等定义*/ short log_level; /*见上面 CMB_LOG_TRACE 等定义*/ std::string dev_name; /*硬件名称,用于作为子目录的区分*/ std::string log_dir; /*在 log_type 包含 CMB_LOG_TYPE_FILE 时,该参数才有效,用于记录日志的目录*/ log_init_config() :log_type(CMB_LOG_TYPE_FILE) ,log_level(CMB_LOG_TRACE) ,dev_name(LOG4VTM_TEXT("VTM")),log_dir(LOG4VTM_TEXT("")){} log_init_config(const log_init_config& rhs) :log_type(rhs.log_type) , log_level(rhs.log_level) , dev_name(rhs.dev_name), log_dir(rhs.log_dir) { } }; class LOG4VENDOR_API log4vendor { public: static log4vendor* instance(); /*! * @brief 在调用打印日志的相关宏时,请先调用此函数进行初始化,否则将不会打印任何形式的日志内容 * * @param[in] * config: 日志初始化的配置参数 * ret_msg: 防止传入的参数有误,在必要的时候记录错误信息,供上层打印排查 * * 如传入的参数依次为:"PinPad", CMB_LOG_TYPE_FILE|CMB_LOG_TYPE_CONSOLE, "C:\\rvc\\dbg" * 那么将会日志记在 "C:\\rvc\\dbg\\PinPad\\{YYYYMMDD}.log" 内,并将支持控制台输出 * */ static void init(const log_init_config& config, vtm_string& ret_msg); static void initp(const log_init_config_c* pconfig, char pret_msg[VENDOR_BUFF_SIZE]); virtual void log(int log_level, const vtm_string& text) = 0; static std::basic_ostringstream& get_oss(); //static std::basic_ostringstream& get_woss(); #ifdef LIBLOG4VENDOR_EXPORTS public: #else private: #endif log4vendor() {} virtual ~log4vendor(){} private: log4vendor(const log4vendor& rhs); }; ////////////////////////////////////////////////////////////////////////// class LOG4VENDOR_API log4vendor_tracer { public: log4vendor_tracer(const char* message, const char* fileName, int nLine); log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet); log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet); ~log4vendor_tracer(); static const char* _get_file_name(const char* file_path); private: log4vendor_tracer (log4vendor_tracer const &); log4vendor_tracer & operator = (log4vendor_tracer const &); const char* m_pszMes; const char* m_pszFileN; int m_nLine; int* m_pnRet; PDWORD m_pDwRet; int* m_pfRet; int m_retType; }; } #endif //_VTM_LOG4VENDOR_H_