log4vendor.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "log4vendor.h"
  2. #include "liblog4vendor.h"
  3. #include "log4cplus_helper.h"
  4. #include "env_deal.h"
  5. #include <vector>
  6. #ifndef _WIN32
  7. #include<sys/types.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #else
  11. #include <process.h>
  12. #endif //NOT _WIN32
  13. #if defined(_MSC_VER)
  14. #define LIBRARY_POSIXNAME "DLL"
  15. #else
  16. #define LIBRARY_POSIXNAME "SO"
  17. #endif //_MSC_VER
  18. namespace cmb {
  19. static bool log4plus_initialized = false;
  20. class log4none : public log4vendor
  21. {
  22. public:
  23. log4none() {}
  24. void log(int log_level, const std::string& text) {/*do nothing.*/}
  25. ~log4none() {
  26. /*通过全局静态变量的销毁函数中释放有效的日志实例对象*/
  27. if(log4plus_initialized) {
  28. LOG4VTM(INFO, "release log instance auto.");
  29. log4cplus_helper::get_instance()->uninit();
  30. }
  31. }
  32. };
  33. /*在有效日志类实例没被初始化前返回的一个替代品*/
  34. static log4none default_instance;
  35. log4vendor* log4vendor::instance()
  36. {
  37. if(!log4plus_initialized)
  38. return &default_instance;
  39. return log4cplus_helper::get_instance();
  40. }
  41. std::vector<std::string> split(std::string str, char split_char)
  42. {
  43. std::vector<std::string> strs;
  44. std::string::size_type pos1, pos2;
  45. pos2 = str.find(split_char);
  46. pos1 = 0;
  47. while (std::string::npos != pos2) {
  48. strs.push_back(str.substr(pos1, pos2 - pos1));
  49. pos1 = pos2 + 1;
  50. pos2 = str.find(split_char, pos1);
  51. }
  52. strs.push_back(str.substr(pos1));
  53. return strs;
  54. }
  55. std::string toupper(const std::string str)
  56. {
  57. std::string dest;
  58. dest.resize(str.size());
  59. std::transform(str.begin(), str.end(), dest.begin(), ::toupper);
  60. return dest;
  61. }
  62. bool start_with(std::string const& s, std::string const& prefix)
  63. {
  64. return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
  65. }
  66. /*从环境变量中提取的信息转换成日志配置结构体信息*/
  67. static void env2config(const env_log_config& env, log_init_config* config)
  68. {
  69. config->dev_name = "";
  70. config->log_dir = "";
  71. config->log_level = CMB_LOG_LEVEL_OFF;
  72. config->log_type = 0; /*OFF*/
  73. //if(env.record_type.find("CONSOLE") != std::string::npos)
  74. // config->log_type |= CMB_LOG_TYPE_CONSOLE;
  75. const std::string record_type = toupper(env.record_type);
  76. if(record_type.find("FILE") != std::string::npos)
  77. config->log_type |= CMB_LOG_TYPE_FILE;
  78. /*get log level*/
  79. const std::string record_level = toupper(env.record_level);
  80. if(record_level.find("TRACE") != std::string::npos)
  81. config->log_level = CMB_LOG_LEVEL_TRACE;
  82. else if(record_level.find("INFO") != std::string::npos)
  83. config->log_level = CMB_LOG_LEVEL_INFO;
  84. else if(record_level.find("WARN") != std::string::npos)
  85. config->log_level = CMB_LOG_LEVEL_WARN;
  86. else if(record_level.find("ERROR") != std::string::npos)
  87. config->log_level = CMB_LOG_LEVEL_ERROR;
  88. else if(record_level.find("FATAL") != std::string::npos)
  89. config->log_level = CMB_LOG_LEVEL_FATAL;
  90. else if(record_level.find("ALL") != std::string::npos)
  91. config->log_level = CMB_LOG_LEVEL_ALL;
  92. auto dev_infos = split(env.module_name, '.');
  93. //TODO: comfirm the name's validity. {DeviceName}.{VendorName}.{X}.{Y}.dll
  94. if(dev_infos.size() == 5 && toupper(dev_infos[4]) == LIBRARY_POSIXNAME) {
  95. config->dev_name = "vendor_";
  96. {
  97. auto lib_name = toupper(dev_infos[0]);
  98. auto lib_prefix = std::string("LIB");
  99. if (start_with(lib_name, lib_prefix)) {
  100. lib_name = dev_infos[0].substr(lib_prefix.length());
  101. } else {
  102. lib_name = dev_infos[0];
  103. }
  104. config->dev_name += lib_name;
  105. }
  106. }
  107. config->log_dir = env.record_path;
  108. }
  109. void log4vendor::initp(const log_init_config_c* pconfig, char pret_msg[VENDOR_BUFF_SIZE])
  110. {
  111. std::string msg("");
  112. if (pconfig != nullptr) {
  113. log_init_config config1;
  114. config1.dev_name = pconfig->dev_name;
  115. config1.log_dir = pconfig->log_dir;
  116. config1.log_level = pconfig->log_level;
  117. config1.log_type = pconfig->log_type;
  118. init(config1, msg);
  119. if (!msg.empty()) {
  120. strcpy(pret_msg, msg.c_str());
  121. }
  122. } else {
  123. std::strcpy(pret_msg, "error param: nullptr");
  124. }
  125. }
  126. void log4vendor::init(const log_init_config& config, std::string& ret_msg)
  127. {
  128. ret_msg.clear();
  129. std::string env_string = "[RVC] ";
  130. log_init_config* lhs = const_cast<log_init_config*>(&config);
  131. log_init_config log_env_config;
  132. std::string instance_name;
  133. if(log4plus_initialized) {
  134. assert(log4vendor::instance() != &default_instance);
  135. ret_msg = "WARN: log instance has been initialized.";
  136. goto error_point;
  137. }
  138. if(IsVTMProcess()) {
  139. ret_msg = env_string + "INFO: vtm runtime, it's VTMers' responsibility to do initialize job.";
  140. env_log_config log_config;
  141. if(log_config.retrieve_env_value()) {
  142. env2config(log_config, &log_env_config);
  143. lhs = &log_env_config;
  144. if(!log_config.module_name.empty()) {
  145. env_string = log_config.module_name;
  146. }
  147. } else {
  148. ret_msg = env_string + " WARN: vtm runtime, retrieve config failed.";
  149. goto error_point;
  150. }
  151. } else {
  152. env_string = "";
  153. }
  154. if(!log4cplus_helper::get_instance()->set_log_append_type(lhs->log_type)) {
  155. ret_msg = env_string + " -- ERROR: set log type failed.";
  156. goto error_point;
  157. }
  158. if(!log4cplus_helper::get_instance()->set_log_level(lhs->log_level)) {
  159. ret_msg = env_string + " -- ERROR: set log level failed.";
  160. goto error_point;
  161. }
  162. if(!log4cplus_helper::get_instance()->set_log_dir(lhs->log_dir)) {
  163. ret_msg = env_string + " -- ERROR: set log dir failed.";
  164. goto error_point;
  165. }
  166. if(!log4cplus_helper::get_instance()->init(lhs->dev_name.c_str())) {
  167. ret_msg = env_string + " -- ERROR: real init failed.";
  168. goto error_point;
  169. }
  170. instance_name = lhs->dev_name;
  171. if(!env_string.empty()) {
  172. instance_name = env_string;
  173. }
  174. /*提前在这里赋值,以便让 LOG4VTM 宏生效*/
  175. log4plus_initialized = true;
  176. LOG4VTM(INFO, "==============Log4Vendor(" << instance_name << ") start==============");
  177. LOG4VTM(INFO, "process id: " << getpid());
  178. {
  179. char ver[128] = {'\0'};
  180. DWORD sz = 128;
  181. GetCurFileVersion(ver, sz);
  182. LOG4VTM(INFO, "log4vendor instance' s version: " << ver);
  183. }
  184. return;
  185. error_point:
  186. std::string ps = ret_msg + "\n";
  187. #if defined(_MSC_VER)
  188. OutputDebugStringA(ps.c_str());
  189. #endif //_MSC_VER
  190. }
  191. /*获取输出字符串流引用对象,不自己定义,从开源库中获取会比较安全*/
  192. std::basic_ostringstream<char>& log4vendor::get_oss()
  193. {
  194. LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var);
  195. return var;
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. //class log4vendor_tracer::
  199. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine)
  200. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
  201. {
  202. std::ostringstream str;
  203. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  204. log4cplus_helper::get_instance()->trace(str.str());
  205. }
  206. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet)
  207. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  208. , m_pnRet(pRet), m_pDwRet(NULL), m_pfRet(NULL), m_retType(0)
  209. {
  210. std::ostringstream str;
  211. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  212. log4cplus_helper::get_instance()->trace(str.str());
  213. }
  214. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet)
  215. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  216. , m_pnRet(NULL), m_pDwRet(pRet), m_pfRet(NULL), m_retType(1)
  217. {
  218. std::ostringstream str;
  219. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  220. log4cplus_helper::get_instance()->trace(str.str());
  221. }
  222. log4vendor_tracer::~log4vendor_tracer()
  223. {
  224. std::ostringstream str;
  225. if(m_retType == 0)
  226. {
  227. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pnRet << "}.";
  228. }
  229. else if(m_retType == 1)
  230. {
  231. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pDwRet << "}.";
  232. }
  233. else if (m_retType == 2)
  234. {
  235. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pfRet << "}.";
  236. }
  237. else {
  238. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  239. }
  240. log4cplus_helper::get_instance()->trace(str.str());
  241. }
  242. const char* log4vendor_tracer::_get_file_name(const char* file_path)
  243. {
  244. if(file_path == NULL || strlen(file_path) == 0) {
  245. return "empty";
  246. }
  247. const char* backlash = strrchr(file_path, (int)('\\'));
  248. if(backlash == NULL) {
  249. backlash = strrchr(file_path, (int)('/'));
  250. }
  251. if(!backlash) {
  252. return file_path;
  253. }
  254. return (backlash+1);
  255. }
  256. }