log4cplus_helper.cpp 15 KB

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