#include "log4rvcother.h" #include "liblog4rvcother.h" #include "log4cplus_helper.h" #include "env_deal.h" #include #ifndef _WIN32 #include #include #include #else #include #endif //NOT _WIN32 #if defined(_MSC_VER) #define LIBRARY_POSIXNAME "DLL" #else #define LIBRARY_POSIXNAME "SO" #endif //_MSC_VER namespace cmb { static bool log4plus_initialized = false; class log4none : public log4rvcother { public: log4none() {} void log(int log_level, const std::string& text) {/*do nothing.*/} ~log4none() { /*通过全局静态变量的销毁函数中释放有效的日志实例对象*/ if(log4plus_initialized) { LOG4VTM(INFO, "release log instance auto."); log4cplus_helper::get_instance()->uninit(); } } }; /*在有效日志类实例没被初始化前返回的一个替代品*/ static log4none default_instance; log4rvcother* log4rvcother::instance() { if(!log4plus_initialized) return &default_instance; return log4cplus_helper::get_instance(); } std::vector split(std::string str, char split_char) { std::vector strs; std::string::size_type pos1, pos2; pos2 = str.find(split_char); pos1 = 0; while (std::string::npos != pos2) { strs.push_back(str.substr(pos1, pos2 - pos1)); pos1 = pos2 + 1; pos2 = str.find(split_char, pos1); } strs.push_back(str.substr(pos1)); return strs; } std::string toupper(const std::string str) { std::string dest; dest.resize(str.size()); std::transform(str.begin(), str.end(), dest.begin(), ::toupper); return dest; } bool start_with(std::string const& s, std::string const& prefix) { return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); } /*从环境变量中提取的信息转换成日志配置结构体信息*/ static void env2config(const env_log_config& env, log_init_config* config) { config->dev_name = ""; config->log_dir = ""; config->log_level = CMB_LOG_LEVEL_OFF; config->log_type = 0; /*OFF*/ //if(env.record_type.find("CONSOLE") != std::string::npos) // config->log_type |= CMB_LOG_TYPE_CONSOLE; const std::string record_type = toupper(env.record_type); if(record_type.find("FILE") != std::string::npos) config->log_type |= CMB_LOG_TYPE_FILE; if (record_type.find("UPLOAD") != std::string::npos) config->log_type |= CMB_LOG_TYPE_SOCKET; /*get log level*/ const std::string record_level = toupper(env.record_level); if(record_level.find("TRACE") != std::string::npos) config->log_level = CMB_LOG_LEVEL_TRACE; else if(record_level.find("INFO") != std::string::npos) config->log_level = CMB_LOG_LEVEL_INFO; else if(record_level.find("WARN") != std::string::npos) config->log_level = CMB_LOG_LEVEL_WARN; else if(record_level.find("ERROR") != std::string::npos) config->log_level = CMB_LOG_LEVEL_ERROR; else if(record_level.find("FATAL") != std::string::npos) config->log_level = CMB_LOG_LEVEL_FATAL; else if(record_level.find("ALL") != std::string::npos) config->log_level = CMB_LOG_LEVEL_ALL; auto dev_infos = split(env.module_name, '.'); //TODO: comfirm the name's validity. {DeviceName}.{VendorName}.{X}.{Y}.dll if(dev_infos.size() == 5 && toupper(dev_infos[4]) == LIBRARY_POSIXNAME) { config->dev_name = "vendor_"; #if defined(_MSC_VER) config->dev_name += dev_infos[0]; #else { auto lib_name = toupper(dev_infos[0]); auto lib_prefix = std::string("LIB"); if (start_with(lib_name, lib_prefix)) { lib_name = dev_infos[0].substr(lib_prefix.length()); } else { lib_name = dev_infos[0]; } config->dev_name += lib_name; } #endif //_MSC_VER } else { config->dev_name = env.module_name; } config->log_dir = env.record_path; } #ifndef _WIN32 void log4rvcother::initp(const log_init_config_c* pconfig, char pret_msg[RVCOTHER_BUFF_SIZE]) { std::string msg(""); if (pconfig != nullptr) { log_init_config config1; config1.dev_name = pconfig->dev_name; config1.log_dir = pconfig->log_dir; config1.log_level = pconfig->log_level; config1.log_type = pconfig->log_type; init(config1, msg); if (!msg.empty()) { strcpy(pret_msg, msg.c_str()); } } else { std::strcpy(pret_msg, "error param: nullptr"); } } #endif //NOT _WIN32 void log4rvcother::init(const log_init_config& config, std::string& ret_msg) { ret_msg.clear(); std::string env_string = "[RVC] "; log_init_config* lhs = const_cast(&config); log_init_config log_env_config; std::string instance_name; bool is_vtm_env(false); std::string terminalno = config.terminalno; if(log4plus_initialized) { assert(log4rvcother::instance() != &default_instance); ret_msg = "WARN: log instance has been initialized."; goto error_point; } if(IsVTMProcess()) { is_vtm_env = true; ret_msg = env_string + "INFO: vtm runtime, it's VTMers' responsibility to do initialize job."; env_log_config log_config; if(log_config.retrieve_env_value()) { env2config(log_config, &log_env_config); lhs = &log_env_config; if(!log_config.module_name.empty()) { env_string = log_config.module_name; } } else { ret_msg = env_string + " WARN: vtm runtime, retrieve config failed."; goto error_point; } } else { env_string = ""; } if(!log4cplus_helper::get_instance()->set_log_append_type(lhs->log_type)) { ret_msg = env_string + " -- ERROR: set log type failed."; goto error_point; } if(!log4cplus_helper::get_instance()->set_log_level(lhs->log_level)) { ret_msg = env_string + " -- ERROR: set log level failed."; goto error_point; } if(!log4cplus_helper::get_instance()->set_log_dir(lhs->log_dir)) { ret_msg = env_string + " -- ERROR: set log dir failed."; goto error_point; } if(!log4cplus_helper::get_instance()->init(lhs->dev_name.c_str())) { ret_msg = env_string + " -- ERROR: real init failed."; goto error_point; } instance_name = lhs->dev_name; if(!env_string.empty()) { instance_name = env_string; } /*提前在这里赋值,以便让 LOG4VTM 宏生效*/ log4plus_initialized = true; if (is_vtm_env && (lhs->log_type & CMB_LOG_TYPE_SOCKET) != 0) { lhs->terminalno = terminalno; log4cplus_helper::get_instance()->initialize_linklog(*lhs); } LOG4VTM(INFO, "==============Log4Vendor(" << instance_name << ") start=============="); #if defined(_MSC_VER) LOG4VTM(INFO, "process id: " << GetCurrentProcessId()); #else LOG4VTM(INFO, "process id: " << getpid()); #endif //_MSC_VER { char ver[128] = {'\0'}; DWORD sz = 128; GetCurFileVersion(ver, sz); LOG4VTM(INFO, "log4rvcother instance' s version: " << ver); } return; error_point: std::string ps = ret_msg + "\n"; #if defined(_MSC_VER) OutputDebugStringA(ps.c_str()); #endif //_MSC_VER } /*获取输出字符串流引用对象,不自己定义,从开源库中获取会比较安全*/ std::basic_ostringstream& log4rvcother::get_oss() { LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var); return var; } ////////////////////////////////////////////////////////////////////////// //class log4vendor_tracer:: log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine) :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1) { std::ostringstream str; str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}."; log4cplus_helper::get_instance()->trace(str.str()); } log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet) :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine) , m_pnRet(pRet), m_pDwRet(NULL), m_pfRet(NULL), m_retType(0) { std::ostringstream str; str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}."; log4cplus_helper::get_instance()->trace(str.str()); } #if defined(_MSC_VER) log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, unsigned long* pRet) #else log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet) #endif //_MSC_VER :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine) , m_pnRet(NULL), m_pDwRet(pRet), m_pfRet(NULL), m_retType(1) { std::ostringstream str; str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}."; log4cplus_helper::get_instance()->trace(str.str()); } log4vendor_tracer::~log4vendor_tracer() { std::ostringstream str; if(m_retType == 0) { str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pnRet << "}."; } else if(m_retType == 1) { str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pDwRet << "}."; } else if (m_retType == 2) { str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pfRet << "}."; } else { str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}."; } log4cplus_helper::get_instance()->trace(str.str()); } const char* log4vendor_tracer::_get_file_name(const char* file_path) { if(file_path == NULL || strlen(file_path) == 0) { return "empty"; } const char* backlash = strrchr(file_path, (int)('\\')); if(backlash == NULL) { backlash = strrchr(file_path, (int)('/')); } if(!backlash) { return file_path; } return (backlash+1); } }