log4rvcother.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. std::string terminalno = config.terminalno;
  145. if(log4plus_initialized) {
  146. assert(log4rvcother::instance() != &default_instance);
  147. ret_msg = "WARN: log instance has been initialized.";
  148. goto error_point;
  149. }
  150. if(IsVTMProcess()) {
  151. is_vtm_env = true;
  152. ret_msg = env_string + "INFO: vtm runtime, it's VTMers' responsibility to do initialize job.";
  153. env_log_config log_config;
  154. if(log_config.retrieve_env_value()) {
  155. env2config(log_config, &log_env_config);
  156. lhs = &log_env_config;
  157. if(!log_config.module_name.empty()) {
  158. env_string = log_config.module_name;
  159. }
  160. } else {
  161. ret_msg = env_string + " WARN: vtm runtime, retrieve config failed.";
  162. goto error_point;
  163. }
  164. } else {
  165. env_string = "";
  166. }
  167. if(!log4cplus_helper::get_instance()->set_log_append_type(lhs->log_type)) {
  168. ret_msg = env_string + " -- ERROR: set log type failed.";
  169. goto error_point;
  170. }
  171. if(!log4cplus_helper::get_instance()->set_log_level(lhs->log_level)) {
  172. ret_msg = env_string + " -- ERROR: set log level failed.";
  173. goto error_point;
  174. }
  175. if(!log4cplus_helper::get_instance()->set_log_dir(lhs->log_dir)) {
  176. ret_msg = env_string + " -- ERROR: set log dir failed.";
  177. goto error_point;
  178. }
  179. if(!log4cplus_helper::get_instance()->init(lhs->dev_name.c_str())) {
  180. ret_msg = env_string + " -- ERROR: real init failed.";
  181. goto error_point;
  182. }
  183. instance_name = lhs->dev_name;
  184. if(!env_string.empty()) {
  185. instance_name = env_string;
  186. }
  187. /*提前在这里赋值,以便让 LOG4VTM 宏生效*/
  188. log4plus_initialized = true;
  189. if (is_vtm_env && (lhs->log_type & CMB_LOG_TYPE_SOCKET) != 0) {
  190. lhs->terminalno = terminalno;
  191. log4cplus_helper::get_instance()->initialize_linklog(*lhs);
  192. }
  193. LOG4VTM(INFO, "==============Log4Vendor(" << instance_name << ") start==============");
  194. #if defined(_MSC_VER)
  195. LOG4VTM(INFO, "process id: " << GetCurrentProcessId());
  196. #else
  197. LOG4VTM(INFO, "process id: " << getpid());
  198. #endif //_MSC_VER
  199. {
  200. char ver[128] = {'\0'};
  201. DWORD sz = 128;
  202. GetCurFileVersion(ver, sz);
  203. LOG4VTM(INFO, "log4rvcother instance' s version: " << ver);
  204. }
  205. return;
  206. error_point:
  207. std::string ps = ret_msg + "\n";
  208. #if defined(_MSC_VER)
  209. OutputDebugStringA(ps.c_str());
  210. #endif //_MSC_VER
  211. }
  212. /*获取输出字符串流引用对象,不自己定义,从开源库中获取会比较安全*/
  213. std::basic_ostringstream<char>& log4rvcother::get_oss()
  214. {
  215. LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var);
  216. return var;
  217. }
  218. //////////////////////////////////////////////////////////////////////////
  219. //class log4vendor_tracer::
  220. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine)
  221. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
  222. {
  223. std::ostringstream str;
  224. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  225. log4cplus_helper::get_instance()->trace(str.str());
  226. }
  227. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet)
  228. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  229. , m_pnRet(pRet), m_pDwRet(NULL), m_pfRet(NULL), m_retType(0)
  230. {
  231. std::ostringstream str;
  232. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  233. log4cplus_helper::get_instance()->trace(str.str());
  234. }
  235. #if defined(_MSC_VER)
  236. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, unsigned long* pRet)
  237. #else
  238. log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet)
  239. #endif //_MSC_VER
  240. :m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
  241. , m_pnRet(NULL), m_pDwRet(pRet), m_pfRet(NULL), m_retType(1)
  242. {
  243. std::ostringstream str;
  244. str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  245. log4cplus_helper::get_instance()->trace(str.str());
  246. }
  247. log4vendor_tracer::~log4vendor_tracer()
  248. {
  249. std::ostringstream str;
  250. if(m_retType == 0)
  251. {
  252. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pnRet << "}.";
  253. }
  254. else if(m_retType == 1)
  255. {
  256. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pDwRet << "}.";
  257. }
  258. else if (m_retType == 2)
  259. {
  260. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pfRet << "}.";
  261. }
  262. else {
  263. str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
  264. }
  265. log4cplus_helper::get_instance()->trace(str.str());
  266. }
  267. const char* log4vendor_tracer::_get_file_name(const char* file_path)
  268. {
  269. if(file_path == NULL || strlen(file_path) == 0) {
  270. return "empty";
  271. }
  272. const char* backlash = strrchr(file_path, (int)('\\'));
  273. if(backlash == NULL) {
  274. backlash = strrchr(file_path, (int)('/'));
  275. }
  276. if(!backlash) {
  277. return file_path;
  278. }
  279. return (backlash+1);
  280. }
  281. }