log4cplus_helper.cpp 13 KB

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