log4rvcother.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #include "log4rvcother.h"
  2. #include "liblog4rvcother.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 log4rvcother
  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. log4rvcother* log4rvcother::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. if (record_type.find("UPLOAD") != std::string::npos)
  79. config->log_type |= CMB_LOG_TYPE_SOCKET;
  80. /*get log level*/
  81. const std::string record_level = toupper(env.record_level);
  82. if(record_level.find("TRACE") != std::string::npos)
  83. config->log_level = CMB_LOG_LEVEL_TRACE;
  84. else if(record_level.find("INFO") != std::string::npos)
  85. config->log_level = CMB_LOG_LEVEL_INFO;
  86. else if(record_level.find("WARN") != std::string::npos)
  87. config->log_level = CMB_LOG_LEVEL_WARN;
  88. else if(record_level.find("ERROR") != std::string::npos)
  89. config->log_level = CMB_LOG_LEVEL_ERROR;
  90. else if(record_level.find("FATAL") != std::string::npos)
  91. config->log_level = CMB_LOG_LEVEL_FATAL;
  92. else if(record_level.find("ALL") != std::string::npos)
  93. config->log_level = CMB_LOG_LEVEL_ALL;
  94. auto dev_infos = split(env.module_name, '.');
  95. //TODO: comfirm the name's validity. {DeviceName}.{VendorName}.{X}.{Y}.dll
  96. if(dev_infos.size() == 5 && toupper(dev_infos[4]) == LIBRARY_POSIXNAME) {
  97. config->dev_name = "vendor_";
  98. #if defined(_MSC_VER)
  99. config->dev_name += dev_infos[0];
  100. #else
  101. {
  102. auto lib_name = toupper(dev_infos[0]);
  103. auto lib_prefix = std::string("LIB");
  104. if (start_with(lib_name, lib_prefix)) {
  105. lib_name = dev_infos[0].substr(lib_prefix.length());
  106. } else {
  107. lib_name = dev_infos[0];
  108. }
  109. config->dev_name += lib_name;
  110. }
  111. #endif //_MSC_VER
  112. } else {
  113. config->dev_name = env.module_name;
  114. }
  115. config->log_dir = env.record_path;
  116. }
  117. #ifndef _WIN32
  118. void log4rvcother::initp(const log_init_config_c* pconfig, char pret_msg[RVCOTHER_BUFF_SIZE])
  119. {
  120. std::string msg("");
  121. if (pconfig != nullptr) {
  122. log_init_config config1;
  123. config1.dev_name = pconfig->dev_name;
  124. config1.log_dir = pconfig->log_dir;
  125. config1.log_level = pconfig->log_level;
  126. config1.log_type = pconfig->log_type;
  127. init(config1, msg);
  128. if (!msg.empty()) {
  129. strcpy(pret_msg, msg.c_str());
  130. }
  131. } else {
  132. std::strcpy(pret_msg, "error param: nullptr");
  133. }
  134. }
  135. #endif //NOT _WIN32
  136. void log4rvcother::init(const log_init_config& config, std::string& ret_msg)
  137. {
  138. ret_msg.clear();
  139. std::string env_string = "[RVC] ";
  140. log_init_config* lhs = const_cast<log_init_config*>(&config);
  141. log_init_config log_env_config;
  142. std::string instance_name;
  143. bool is_vtm_env(false);
  144. if(log4plus_initialized) {
  145. assert(log4rvcother::instance() != &default_instance);
  146. ret_msg = "WARN: log instance has been initialized.";
  147. goto error_point;
  148. }
  149. if(IsVTMProcess()) {
  150. is_vtm_env = true;
  151. ret_msg = env_string + "INFO: vtm runtime, it's VTMers' responsibility to do initialize job.";
  152. env_log_config log_config;
  153. if(log_config.retrieve_env_value()) {
  154. env2config(log_config, &log_env_config);
  155. lhs = &log_env_config;
  156. if(!log_config.module_name.empty()) {
  157. env_string = log_config.module_name;
  158. }
  159. } else {
  160. ret_msg = env_string + " WARN: vtm runtime, retrieve config failed.";
  161. goto error_point;
  162. }
  163. } else {
  164. env_string = "";
  165. }
  166. if(!log4cplus_helper::get_instance()->set_log_append_type(lhs->log_type)) {
  167. ret_msg = env_string + " -- ERROR: set log type failed.";
  168. goto error_point;
  169. }
  170. if(!log4cplus_helper::get_instance()->set_log_level(lhs->log_level)) {
  171. ret_msg = env_string + " -- ERROR: set log level failed.";
  172. goto error_point;
  173. }
  174. if(!log4cplus_helper::get_instance()->set_log_dir(lhs->log_dir)) {
  175. ret_msg = env_string + " -- ERROR: set log dir failed.";
  176. goto error_point;
  177. }
  178. if(!log4cplus_helper::get_instance()->init(lhs->dev_name.c_str())) {
  179. ret_msg = env_string + " -- ERROR: real init failed.";
  180. goto error_point;
  181. }
  182. instance_name = lhs->dev_name;
  183. if(!env_string.empty()) {
  184. instance_name = env_string;
  185. }
  186. /*提前在这里赋值,以便让 LOG4VTM 宏生效*/
  187. log4plus_initialized = true;
  188. if (is_vtm_env && (lhs->log_type & CMB_LOG_TYPE_SOCKET) != 0) {
  189. log4cplus_helper::get_instance()->initialize_linklog(*lhs);
  190. }
  191. LOG4VTM(INFO, "==============Log4Vendor(" << instance_name << ") start==============");
  192. #if defined(_MSC_VER)
  193. LOG4VTM(INFO, "process id: " << GetCurrentProcessId());
  194. #else
  195. LOG4VTM(INFO, "process id: " << getpid());
  196. #endif //_MSC_VER
  197. {
  198. char ver[128] = {'\0'};
  199. DWORD sz = 128;
  200. GetCurFileVersion(ver, sz);
  201. LOG4VTM(INFO, "log4rvcother instance' s version: " << ver);
  202. }
  203. return;
  204. error_point:
  205. std::string ps = ret_msg + "\n";
  206. #if defined(_MSC_VER)
  207. OutputDebugStringA(ps.c_str());
  208. #endif //_MSC_VER
  209. }
  210. /*获取输出字符串流引用对象,不自己定义,从开源库中获取会比较安全*/
  211. std::basic_ostringstream<char>& log4rvcother::get_oss()
  212. {
  213. LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var);
  214. return var;
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. //class log4vendor_tracer::
  218. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine)
  219. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
  220. {
  221. std::ostringstream str;
  222. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  223. log4cplus_helper::get_instance()->trace(str.str());
  224. }
  225. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet)
  226. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  227. , m_pnRet(pRet), m_pDwRet(NULL), m_pfRet(NULL), m_retType(0)
  228. {
  229. std::ostringstream str;
  230. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  231. log4cplus_helper::get_instance()->trace(str.str());
  232. }
  233. #if defined(_MSC_VER)
  234. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, unsigned long* pRet)
  235. #else
  236. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet)
  237. #endif //_MSC_VER
  238. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  239. , m_pnRet(NULL), m_pDwRet(pRet), m_pfRet(NULL), m_retType(1)
  240. {
  241. std::ostringstream str;
  242. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  243. log4cplus_helper::get_instance()->trace(str.str());
  244. }
  245. log4vendor_tracer::~log4vendor_tracer()
  246. {
  247. std::ostringstream str;
  248. if(m_retType == 0)
  249. {
  250. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pnRet << "}.";
  251. }
  252. else if(m_retType == 1)
  253. {
  254. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pDwRet << "}.";
  255. }
  256. else if (m_retType == 2)
  257. {
  258. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pfRet << "}.";
  259. }
  260. else {
  261. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  262. }
  263. log4cplus_helper::get_instance()->trace(str.str());
  264. }
  265. const char* log4vendor_tracer::_get_file_name(const char* file_path)
  266. {
  267. if(file_path == NULL || strlen(file_path) == 0) {
  268. return "empty";
  269. }
  270. const char* backlash = strrchr(file_path, (int)('\\'));
  271. if(backlash == NULL) {
  272. backlash = strrchr(file_path, (int)('/'));
  273. }
  274. if(!backlash) {
  275. return file_path;
  276. }
  277. return (backlash+1);
  278. }
  279. }