log4cplus_helper.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. #include "log4cplus_helper.h"
  2. #include <iostream>
  3. #include <string>
  4. #if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
  5. #include <log4cplus/win32consoleappender.h>
  6. #define WIN32_CONSOLE 1
  7. #endif
  8. #if defined(ANDROID)
  9. #include <android/log.h>
  10. static const char* TAG = "lib";
  11. #endif
  12. using namespace log4cplus;
  13. using namespace log4cplus::helpers;
  14. #define MAX_BUFFER_LENGTH 4096
  15. #define LOG4PLUS_LOG(TYPE, LOGGER, msg) \
  16. LOG4CPLUS_##TYPE(LOGGER, msg);
  17. static inline vtm_string w2s(const std::wstring wstr)
  18. {
  19. char* str = NULL;
  20. int n = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  21. if (n > 0) {
  22. str = new char[n+1];
  23. if(str == NULL) {
  24. return vtm_string();
  25. }
  26. std::memset(str, 0, sizeof(char)*(n+1));
  27. ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], n, NULL, NULL);
  28. vtm_string strr(str);
  29. delete str;
  30. return strr;
  31. }
  32. return vtm_string();
  33. }
  34. namespace cmb {
  35. log4cplus_helper* log4cplus_helper::_instance = NULL;
  36. mutex log4cplus_helper::_mutex;
  37. log4cplus_helper::log4cplus_helper(void)
  38. :_append_console(NULL),_append_file(NULL),_append_socket(NULL),_append_none(NULL)
  39. ,_socket_send_running(false)
  40. ,_initialized(false),_append_type(0),_log_server_port(0),_log_listen_port(0)
  41. ,_initilzed_zip(false),_cur_upload_log(""),_cur_upload_offset(0),_log_level(NOT_SET_LOG_LEVEL)
  42. {
  43. _log_dir.clear();
  44. _log_server_ip.clear();
  45. _log_server_port = 0;
  46. _log_key_name = "vtm";
  47. }
  48. log4cplus_helper::~log4cplus_helper(void)
  49. {
  50. uninit();
  51. while(!_zip_logs.empty()) {
  52. _zip_logs.pop();
  53. }
  54. }
  55. log4cplus_helper* log4cplus_helper::get_instance()
  56. {
  57. if(_instance == NULL) {
  58. unique_lock lock_(_mutex);
  59. if(_instance == NULL) {
  60. _instance = new log4cplus_helper();
  61. }
  62. }
  63. return _instance;
  64. }
  65. bool log4cplus_helper::init(const char* name)
  66. {
  67. if(_initialized) {
  68. return true;
  69. }
  70. if(name == NULL || strlen(name) == 0)
  71. return false;
  72. if((_append_type & log_append_file) && _log_dir.empty()) {
  73. return false;
  74. }
  75. _log_key_name = name;
  76. log4cplus::initialize();
  77. #ifdef _DEBUG
  78. LogLog::getLogLog()->setInternalDebugging(true);
  79. #else
  80. LogLog::getLogLog()->setInternalDebugging(false);
  81. #endif
  82. log4cplus::Logger& logger = get_logger();
  83. logger.setLogLevel(_log_level);
  84. if ((_append_type & log_append_console) == log_append_console)
  85. {
  86. _append_console = new ConsoleAppender(false, true);
  87. log4cplus::tstring pattern = LOG4CPLUS_TEXT("%d{%H:%M:%S,%Q} [%t] %-5p %c{2} - %m%n");
  88. _append_console->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
  89. logger.addAppender(_append_console);
  90. _append_console->setName(LOG4CPLUS_TEXT("console"));
  91. }
  92. if ((_append_type & log_append_file) == log_append_file)
  93. {
  94. tostringstream propsOStream;
  95. propsOStream << LOG4CPLUS_TEXT("CreateDirs=true\n")
  96. << LOG4CPLUS_TEXT("Append=true\n")
  97. << LOG4CPLUS_TEXT("MaxHistory=999\n")
  98. << LOG4CPLUS_TEXT("ImmediateFlush=true\n")
  99. << LOG4CPLUS_TEXT("RollOnClose=false\n");
  100. vtm_string log_path(_log_dir);
  101. assert(!log_path.empty());
  102. log_path += name;
  103. log_path += LOG4CPLUS_TEXT("\\");
  104. tstring str(LOG4CPLUS_TEXT("FilenamePattern="));
  105. str += log_path;
  106. str += LOG4CPLUS_TEXT("%d{yyyyMMdd}.log\n");
  107. propsOStream << str;
  108. tistringstream propsStream (propsOStream.str());
  109. helpers::Properties props (propsStream);
  110. _append_file = new TimeBasedRollingFileAppender(props);
  111. log4cplus::tstring pattern = LOG4CPLUS_TEXT("[%D{%H:%M:%S.%Q}][%-5p][%t] %m %n");
  112. //<%x> - %X{key}
  113. _append_file->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
  114. logger.addAppender(_append_file);
  115. _append_file->setName(LOG4CPLUS_TEXT("file_log"));
  116. }
  117. if (_append_type <= log_append_none || _append_type > log_append_all)
  118. {
  119. _append_none = new NullAppender();
  120. _append_none->setLayout( std::auto_ptr<Layout>(new log4cplus::TTCCLayout()) );
  121. logger.addAppender(_append_none);
  122. _append_none->setName(LOG4CPLUS_TEXT("none_log"));
  123. }
  124. _initialized = true;
  125. return _initialized;
  126. }
  127. void log4cplus_helper::config_remote_logger(const char* remote_name)
  128. {
  129. LOG4VTM(INFO, "Enter config remote logger: " << remote_name);
  130. if(remote_name == NULL || strlen(remote_name) == 0) {
  131. LOG4VTM(ERROR, "remote log name is empty, config remote logger failed!");
  132. return;
  133. }
  134. if(strcmp(remote_name, _log_key_name.c_str()) == 0) {
  135. LOG4VTM(WARN, "the remote name is the same with the local key name, use local config.");
  136. return;
  137. }
  138. log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(remote_name));
  139. //todo
  140. logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
  141. if ((_append_type & log_append_console) == log_append_console)
  142. {
  143. #ifdef WIN32_CONSOLE
  144. static SharedAppenderPtr append_1(new Win32ConsoleAppender(false, false,
  145. FOREGROUND_GREEN | FOREGROUND_INTENSITY));
  146. #else
  147. static SharedAppenderPtr append_1(new ConsoleAppender(false, true));
  148. #endif
  149. log4cplus::tstring pattern = LOG4CPLUS_TEXT("%d{%H:%M:%S,%Q} [%t] %-5p %c{2} - %m%n");
  150. append_1->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
  151. logger.addAppender(append_1);
  152. append_1->setName(LOG4CPLUS_TEXT("android_console"));
  153. }
  154. if ((_append_type & log_append_file) == log_append_file)
  155. {
  156. tostringstream propsOStream;
  157. propsOStream << LOG4CPLUS_TEXT("CreateDirs=true\n")
  158. << LOG4CPLUS_TEXT("Append=true\n")
  159. << LOG4CPLUS_TEXT("MaxHistory=999\n")
  160. << LOG4CPLUS_TEXT("ImmediateFlush=true\n")
  161. << LOG4CPLUS_TEXT("RollOnClose=false\n");
  162. vtm_string log_path(_log_dir);
  163. assert(!log_path.empty());
  164. log_path += remote_name;
  165. log_path += "\\";
  166. tstring str(LOG4CPLUS_TEXT("FilenamePattern="));
  167. str += log_path;
  168. str += LOG4CPLUS_TEXT("%d{yyyyMMdd}.log\n");
  169. propsOStream << str;
  170. tistringstream propsStream (propsOStream.str());
  171. helpers::Properties props (propsStream);
  172. static SharedAppenderPtr append_2(new TimeBasedRollingFileAppender(props));
  173. log4cplus::tstring pattern = LOG4CPLUS_TEXT("[%D{%H:%M:%S.%Q}][%-5p] %m %n");
  174. append_2->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
  175. logger.addAppender(append_2);
  176. append_2->setName(LOG4CPLUS_TEXT("android_file_log"));
  177. }
  178. }
  179. int log4cplus_helper::run_log_sender(const vtm_string& ip,const unsigned short port)
  180. {
  181. unique_lock lock_(_mutex_4_update_socket);
  182. LOG4VTM(INFO, "Enter run_log_sender...");
  183. if(!_initialized) {
  184. LOG4VTM(WARN, "log4cplus helper has not been initialized");
  185. return -1;
  186. }
  187. if ((_append_type & log_append_socket) == log_append_socket)
  188. {
  189. if(ip == _log_server_ip && _log_server_port == port) {
  190. LOG4VTM(WARN, "log4cplus has been set as the same server ip and port!");
  191. return -1;
  192. }
  193. if (!ip.empty() && port != 0) {
  194. if(_socket_send_running) {
  195. LOG4VTM(INFO, "remove appender");
  196. get_logger().removeAppender(_append_socket);
  197. _append_socket->close();
  198. _append_socket = NULL;
  199. }
  200. LOG4VTM(INFO, "new socket appender");
  201. tostringstream propsOStream;
  202. propsOStream << LOG4CPLUS_TEXT("Appender=log4cplus::SocketAppender\n")
  203. << LOG4CPLUS_TEXT("QueueLimit=10000\n");
  204. {
  205. propsOStream << LOG4CPLUS_TEXT("Appender.host=");
  206. propsOStream << ip << "\n";
  207. }
  208. {
  209. propsOStream << LOG4CPLUS_TEXT("Appender.port=");
  210. propsOStream << port << "\n";
  211. }
  212. {
  213. propsOStream << LOG4CPLUS_TEXT("Appender.ServerName=");
  214. propsOStream << _log_key_name << "\n";
  215. }
  216. tistringstream propsStream (propsOStream.str());
  217. helpers::Properties props (propsStream);
  218. _append_socket = new AsyncAppender(props);
  219. LOG4VTM(INFO, "new socket appender done");
  220. _append_socket->setLayout( std::auto_ptr<Layout>(new log4cplus::TTCCLayout()) );
  221. _append_socket->setName(LOG4CPLUS_TEXT("socket_log"));
  222. LOG4VTM(INFO, "add appender");
  223. get_logger().addAppender(_append_socket);
  224. LOG4VTM(INFO, "add appender done");
  225. _socket_send_running = true;
  226. _log_server_ip = ip;
  227. _log_server_port = port;
  228. LOG4VTM(INFO, "update log sender successfully: " << ip << "::" << port);
  229. return 0;
  230. } else {
  231. LOG4VTM(ERROR, "the remote log ip or port are not config !");
  232. return -1;
  233. }
  234. } else {
  235. LOG4VTM(ERROR, "the current log type is not supported ! " << _append_type);
  236. return -1;
  237. }
  238. return 0;
  239. }
  240. void log4cplus_helper::uninit()
  241. {
  242. if(_initialized) {
  243. get_logger().removeAllAppenders();
  244. _append_console = NULL;
  245. _append_file = NULL;
  246. _append_none = NULL;
  247. _append_socket = NULL;
  248. log4cplus::Logger::shutdown();
  249. _initialized = false;
  250. }
  251. }
  252. std::ostream& log4cplus_helper::stream()
  253. {
  254. LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf);
  255. return _log4cplus_buf;
  256. }
  257. void log4cplus_helper::trace(const vtm_string& text)
  258. {
  259. if(_initialized) {
  260. LOG4PLUS_LOG(TRACE, get_logger(), text.c_str());
  261. }
  262. }
  263. void log4cplus_helper::trace(const char* text)
  264. {
  265. if(_initialized) {
  266. LOG4PLUS_LOG(TRACE, get_logger(), text);
  267. }
  268. }
  269. void log4cplus_helper::info(const vtm_string& text)
  270. {
  271. if(_initialized) {
  272. LOG4PLUS_LOG(INFO, get_logger(), text.c_str());
  273. }
  274. }
  275. void log4cplus_helper::info(const char* text)
  276. {
  277. if(_initialized) {
  278. LOG4PLUS_LOG(INFO, get_logger(), text);
  279. }
  280. }
  281. void log4cplus_helper::debug(const vtm_string& text)
  282. {
  283. #if !defined(NDEBUG)
  284. if(_initialized) {
  285. LOG4PLUS_LOG(INFO, get_logger(), text.c_str());
  286. }
  287. #endif //!defined(NDEBUG)
  288. }
  289. void log4cplus_helper::debug(const char* text)
  290. {
  291. #if !defined(NDEBUG)
  292. if(_initialized) {
  293. LOG4PLUS_LOG(DEBUG, get_logger(), text);
  294. }
  295. #endif //!defined(NDEBUG)
  296. }
  297. void log4cplus_helper::warn(const vtm_string& text)
  298. {
  299. if(_initialized) {
  300. LOG4PLUS_LOG(WARN, get_logger(), text.c_str());
  301. }
  302. }
  303. void log4cplus_helper::warn(const char* text)
  304. {
  305. if(_initialized) {
  306. LOG4PLUS_LOG(WARN, get_logger(), text);
  307. }
  308. }
  309. void log4cplus_helper::error(const vtm_string& text)
  310. {
  311. if(_initialized) {
  312. LOG4PLUS_LOG(ERROR, get_logger(), text.c_str());
  313. }
  314. }
  315. void log4cplus_helper::error(const char* text)
  316. {
  317. if(_initialized) {
  318. LOG4PLUS_LOG(ERROR, get_logger(), text);
  319. }
  320. }
  321. void log4cplus_helper::fatal(const vtm_string& text)
  322. {
  323. if(_initialized) {
  324. LOG4PLUS_LOG(FATAL, get_logger(), text.c_str());
  325. }
  326. }
  327. void log4cplus_helper::fatal(const char* text)
  328. {
  329. if(_initialized) {
  330. LOG4PLUS_LOG(FATAL, get_logger(), text);
  331. }
  332. }
  333. vtm_string log4cplus_helper::format(const char *ft, ...)
  334. {
  335. va_list arg;
  336. va_start (arg, ft);
  337. vtm_string formatted = format(ft, arg);
  338. return formatted;
  339. }
  340. vtm_string log4cplus_helper::format(const char *ft,va_list& arg)
  341. {
  342. int len = 0;
  343. vtm_string formatted = "";
  344. char* buffer = NULL;
  345. len = _vscprintf( ft, arg ) + 1;
  346. buffer = (char*)malloc( len * sizeof(char) );
  347. len = vsprintf_s(buffer,len,ft, arg);
  348. formatted = buffer ;
  349. free(buffer);
  350. return formatted;
  351. }
  352. void log4cplus_helper::log(const char *file_name, const char *func_name, int line,
  353. const char* ft, int type /*= log_level_debug*/)
  354. {
  355. std::stringstream sstream;
  356. sstream << file_name << " " << func_name << " " << line << " " << ft << std::endl;
  357. switch(type) {
  358. case log_level_debug:
  359. debug(sstream.str());
  360. break;
  361. case log_level_trace:
  362. trace(sstream.str());
  363. break;
  364. case log_level_info:
  365. info(sstream.str());
  366. break;
  367. case log_level_warn:
  368. warn(sstream.str());
  369. break;
  370. case log_level_error:
  371. error(sstream.str());
  372. break;
  373. case log_level_fatal:
  374. fatal(sstream.str());
  375. break;
  376. default:
  377. trace(sstream.str());
  378. break;
  379. }
  380. return;
  381. }
  382. void log4cplus_helper::log(int log_level, const vtm_string& text)
  383. {
  384. switch (log_level) {
  385. case CMB_LOG_TRACE:
  386. trace(text);
  387. break;
  388. case CMB_LOG_DEBUG:
  389. debug(text);
  390. break;
  391. case CMB_LOG_INFO:
  392. info(text);
  393. break;
  394. case CMB_LOG_WARN:
  395. warn(text);
  396. break;
  397. case CMB_LOG_ERROR:
  398. error(text);
  399. break;
  400. case CMB_LOG_FATAL:
  401. fatal(text);
  402. break;
  403. default:
  404. trace(text);
  405. break;
  406. }
  407. return;
  408. }
  409. void log4cplus_helper::log(const char *file_name, const char *func_name, int line,
  410. int type ,const char *ft /*= ""*/, ...)
  411. {
  412. va_list arg;
  413. va_start (arg, ft);
  414. vtm_string formatted = format(ft, arg);
  415. va_end (arg);
  416. log(file_name, func_name, line, formatted.c_str(),type);
  417. }
  418. void log4cplus_helper::logw(int log_level, const std::wstring& wtext)
  419. {
  420. auto text = ::w2s(wtext);
  421. log(log_level, text);
  422. }
  423. }