log4vendor.cpp 9.6 KB

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