|
@@ -0,0 +1,467 @@
|
|
|
+#include "log4cplus_helper.h"
|
|
|
+#include <iostream>
|
|
|
+#include <string>
|
|
|
+
|
|
|
+#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
|
|
|
+#include <log4cplus/win32consoleappender.h>
|
|
|
+#define WIN32_CONSOLE 1
|
|
|
+#endif
|
|
|
+
|
|
|
+#if defined(ANDROID)
|
|
|
+#include <android/log.h>
|
|
|
+static const char* TAG = "lib";
|
|
|
+#endif
|
|
|
+
|
|
|
+using namespace log4cplus;
|
|
|
+using namespace log4cplus::helpers;
|
|
|
+
|
|
|
+#define MAX_BUFFER_LENGTH 4096
|
|
|
+
|
|
|
+#define LOG4PLUS_LOG(TYPE, LOGGER, msg) \
|
|
|
+ LOG4CPLUS_##TYPE(LOGGER, msg);
|
|
|
+
|
|
|
+
|
|
|
+static inline vtm_string w2s(const std::wstring wstr)
|
|
|
+{
|
|
|
+ char* str = NULL;
|
|
|
+ int n = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
|
|
|
+ if (n > 0) {
|
|
|
+ str = new char[n+1];
|
|
|
+ if(str == NULL) {
|
|
|
+ return vtm_string();
|
|
|
+ }
|
|
|
+ std::memset(str, 0, sizeof(char)*(n+1));
|
|
|
+ ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], n, NULL, NULL);
|
|
|
+ vtm_string strr(str);
|
|
|
+ delete str;
|
|
|
+ return strr;
|
|
|
+ }
|
|
|
+ return vtm_string();
|
|
|
+}
|
|
|
+
|
|
|
+namespace cmb {
|
|
|
+
|
|
|
+ log4cplus_helper* log4cplus_helper::_instance = NULL;
|
|
|
+ mutex log4cplus_helper::_mutex;
|
|
|
+
|
|
|
+ log4cplus_helper::log4cplus_helper(void)
|
|
|
+ :_append_console(NULL),_append_file(NULL),_append_socket(NULL),_append_none(NULL)
|
|
|
+ ,_socket_send_running(false)
|
|
|
+ ,_initialized(false),_append_type(0),_log_server_port(0),_log_listen_port(0)
|
|
|
+ ,_initilzed_zip(false),_cur_upload_log(""),_cur_upload_offset(0),_log_level(NOT_SET_LOG_LEVEL)
|
|
|
+ {
|
|
|
+ _log_dir.clear();
|
|
|
+ _log_server_ip.clear();
|
|
|
+ _log_server_port = 0;
|
|
|
+ _log_key_name = "vtm";
|
|
|
+ }
|
|
|
+
|
|
|
+ log4cplus_helper::~log4cplus_helper(void)
|
|
|
+ {
|
|
|
+ uninit();
|
|
|
+ while(!_zip_logs.empty()) {
|
|
|
+ _zip_logs.pop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log4cplus_helper* log4cplus_helper::get_instance()
|
|
|
+ {
|
|
|
+ if(_instance == NULL) {
|
|
|
+ unique_lock lock_(_mutex);
|
|
|
+ if(_instance == NULL) {
|
|
|
+ _instance = new log4cplus_helper();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return _instance;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool log4cplus_helper::init(const char* name)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if(name == NULL || strlen(name) == 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if((_append_type & log_append_file) && _log_dir.empty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ _log_key_name = name;
|
|
|
+ log4cplus::initialize();
|
|
|
+#ifdef _DEBUG
|
|
|
+ LogLog::getLogLog()->setInternalDebugging(true);
|
|
|
+#else
|
|
|
+ LogLog::getLogLog()->setInternalDebugging(false);
|
|
|
+#endif
|
|
|
+ log4cplus::Logger& logger = get_logger();
|
|
|
+ logger.setLogLevel(_log_level);
|
|
|
+
|
|
|
+ if ((_append_type & log_append_console) == log_append_console)
|
|
|
+ {
|
|
|
+ _append_console = new ConsoleAppender(false, true);
|
|
|
+ log4cplus::tstring pattern = LOG4CPLUS_TEXT("%d{%H:%M:%S,%Q} [%t] %-5p %c{2} - %m%n");
|
|
|
+ _append_console->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
|
|
|
+ logger.addAppender(_append_console);
|
|
|
+ _append_console->setName(LOG4CPLUS_TEXT("console"));
|
|
|
+ }
|
|
|
+ if ((_append_type & log_append_file) == log_append_file)
|
|
|
+ {
|
|
|
+ tostringstream propsOStream;
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("CreateDirs=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("Append=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("MaxHistory=999\n")
|
|
|
+ << LOG4CPLUS_TEXT("ImmediateFlush=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("RollOnClose=false\n");
|
|
|
+ vtm_string log_path(_log_dir);
|
|
|
+ assert(!log_path.empty());
|
|
|
+ log_path += name;
|
|
|
+ log_path += LOG4CPLUS_TEXT("\\");
|
|
|
+ tstring str(LOG4CPLUS_TEXT("FilenamePattern="));
|
|
|
+ str += log_path;
|
|
|
+ str += LOG4CPLUS_TEXT("%d{yyyyMMdd}.log\n");
|
|
|
+ propsOStream << str;
|
|
|
+ tistringstream propsStream (propsOStream.str());
|
|
|
+ helpers::Properties props (propsStream);
|
|
|
+ _append_file = new TimeBasedRollingFileAppender(props);
|
|
|
+ log4cplus::tstring pattern = LOG4CPLUS_TEXT("[%D{%H:%M:%S.%Q}][%-5p][%t] %m %n");
|
|
|
+ //<%x> - %X{key}
|
|
|
+ _append_file->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
|
|
|
+ logger.addAppender(_append_file);
|
|
|
+ _append_file->setName(LOG4CPLUS_TEXT("file_log"));
|
|
|
+ }
|
|
|
+ if (_append_type <= log_append_none || _append_type > log_append_all)
|
|
|
+ {
|
|
|
+ _append_none = new NullAppender();
|
|
|
+ _append_none->setLayout( std::auto_ptr<Layout>(new log4cplus::TTCCLayout()) );
|
|
|
+ logger.addAppender(_append_none);
|
|
|
+ _append_none->setName(LOG4CPLUS_TEXT("none_log"));
|
|
|
+ }
|
|
|
+ _initialized = true;
|
|
|
+ return _initialized;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ void log4cplus_helper::config_remote_logger(const char* remote_name)
|
|
|
+ {
|
|
|
+ LOG4VTM(INFO, "Enter config remote logger: " << remote_name);
|
|
|
+ if(remote_name == NULL || strlen(remote_name) == 0) {
|
|
|
+ LOG4VTM(ERROR, "remote log name is empty, config remote logger failed!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(strcmp(remote_name, _log_key_name.c_str()) == 0) {
|
|
|
+ LOG4VTM(WARN, "the remote name is the same with the local key name, use local config.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(remote_name));
|
|
|
+ //todo
|
|
|
+ logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
|
|
|
+ if ((_append_type & log_append_console) == log_append_console)
|
|
|
+ {
|
|
|
+#ifdef WIN32_CONSOLE
|
|
|
+ static SharedAppenderPtr append_1(new Win32ConsoleAppender(false, false,
|
|
|
+ FOREGROUND_GREEN | FOREGROUND_INTENSITY));
|
|
|
+#else
|
|
|
+ static SharedAppenderPtr append_1(new ConsoleAppender(false, true));
|
|
|
+#endif
|
|
|
+ log4cplus::tstring pattern = LOG4CPLUS_TEXT("%d{%H:%M:%S,%Q} [%t] %-5p %c{2} - %m%n");
|
|
|
+ append_1->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
|
|
|
+ logger.addAppender(append_1);
|
|
|
+ append_1->setName(LOG4CPLUS_TEXT("android_console"));
|
|
|
+ }
|
|
|
+ if ((_append_type & log_append_file) == log_append_file)
|
|
|
+ {
|
|
|
+ tostringstream propsOStream;
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("CreateDirs=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("Append=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("MaxHistory=999\n")
|
|
|
+ << LOG4CPLUS_TEXT("ImmediateFlush=true\n")
|
|
|
+ << LOG4CPLUS_TEXT("RollOnClose=false\n");
|
|
|
+ vtm_string log_path(_log_dir);
|
|
|
+ assert(!log_path.empty());
|
|
|
+ log_path += remote_name;
|
|
|
+ log_path += "\\";
|
|
|
+ tstring str(LOG4CPLUS_TEXT("FilenamePattern="));
|
|
|
+ str += log_path;
|
|
|
+ str += LOG4CPLUS_TEXT("%d{yyyyMMdd}.log\n");
|
|
|
+ propsOStream << str;
|
|
|
+ tistringstream propsStream (propsOStream.str());
|
|
|
+ helpers::Properties props (propsStream);
|
|
|
+ static SharedAppenderPtr append_2(new TimeBasedRollingFileAppender(props));
|
|
|
+ log4cplus::tstring pattern = LOG4CPLUS_TEXT("[%D{%H:%M:%S.%Q}][%-5p] %m %n");
|
|
|
+ append_2->setLayout( std::auto_ptr<Layout>(new PatternLayout(pattern)) );
|
|
|
+ logger.addAppender(append_2);
|
|
|
+ append_2->setName(LOG4CPLUS_TEXT("android_file_log"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ int log4cplus_helper::run_log_sender(const vtm_string& ip,const unsigned short port)
|
|
|
+ {
|
|
|
+ unique_lock lock_(_mutex_4_update_socket);
|
|
|
+ LOG4VTM(INFO, "Enter run_log_sender...");
|
|
|
+ if(!_initialized) {
|
|
|
+ LOG4VTM(WARN, "log4cplus helper has not been initialized");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_append_type & log_append_socket) == log_append_socket)
|
|
|
+ {
|
|
|
+ if(ip == _log_server_ip && _log_server_port == port) {
|
|
|
+ LOG4VTM(WARN, "log4cplus has been set as the same server ip and port!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ip.empty() && port != 0) {
|
|
|
+ if(_socket_send_running) {
|
|
|
+ LOG4VTM(INFO, "remove appender");
|
|
|
+ get_logger().removeAppender(_append_socket);
|
|
|
+ _append_socket->close();
|
|
|
+ _append_socket = NULL;
|
|
|
+ }
|
|
|
+ LOG4VTM(INFO, "new socket appender");
|
|
|
+ tostringstream propsOStream;
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("Appender=log4cplus::SocketAppender\n")
|
|
|
+ << LOG4CPLUS_TEXT("QueueLimit=10000\n");
|
|
|
+ {
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("Appender.host=");
|
|
|
+ propsOStream << ip << "\n";
|
|
|
+ }
|
|
|
+ {
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("Appender.port=");
|
|
|
+ propsOStream << port << "\n";
|
|
|
+ }
|
|
|
+ {
|
|
|
+ propsOStream << LOG4CPLUS_TEXT("Appender.ServerName=");
|
|
|
+ propsOStream << _log_key_name << "\n";
|
|
|
+ }
|
|
|
+ tistringstream propsStream (propsOStream.str());
|
|
|
+ helpers::Properties props (propsStream);
|
|
|
+ _append_socket = new AsyncAppender(props);
|
|
|
+ LOG4VTM(INFO, "new socket appender done");
|
|
|
+ _append_socket->setLayout( std::auto_ptr<Layout>(new log4cplus::TTCCLayout()) );
|
|
|
+ _append_socket->setName(LOG4CPLUS_TEXT("socket_log"));
|
|
|
+ LOG4VTM(INFO, "add appender");
|
|
|
+ get_logger().addAppender(_append_socket);
|
|
|
+ LOG4VTM(INFO, "add appender done");
|
|
|
+ _socket_send_running = true;
|
|
|
+ _log_server_ip = ip;
|
|
|
+ _log_server_port = port;
|
|
|
+ LOG4VTM(INFO, "update log sender successfully: " << ip << "::" << port);
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ LOG4VTM(ERROR, "the remote log ip or port are not config !");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ LOG4VTM(ERROR, "the current log type is not supported ! " << _append_type);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::uninit()
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ get_logger().removeAllAppenders();
|
|
|
+ _append_console = NULL;
|
|
|
+ _append_file = NULL;
|
|
|
+ _append_none = NULL;
|
|
|
+ _append_socket = NULL;
|
|
|
+ log4cplus::Logger::shutdown();
|
|
|
+ _initialized = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::ostream& log4cplus_helper::stream()
|
|
|
+ {
|
|
|
+ LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf);
|
|
|
+ return _log4cplus_buf;
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::trace(const vtm_string& text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(TRACE, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::trace(const char* text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(TRACE, get_logger(), text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::info(const vtm_string& text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(INFO, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::info(const char* text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(INFO, get_logger(), text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::debug(const vtm_string& text)
|
|
|
+ {
|
|
|
+#if !defined(NDEBUG)
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(INFO, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+#endif //!defined(NDEBUG)
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::debug(const char* text)
|
|
|
+ {
|
|
|
+#if !defined(NDEBUG)
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(DEBUG, get_logger(), text);
|
|
|
+ }
|
|
|
+#endif //!defined(NDEBUG)
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::warn(const vtm_string& text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(WARN, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::warn(const char* text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(WARN, get_logger(), text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::error(const vtm_string& text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(ERROR, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::error(const char* text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(ERROR, get_logger(), text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::fatal(const vtm_string& text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(FATAL, get_logger(), text.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::fatal(const char* text)
|
|
|
+ {
|
|
|
+ if(_initialized) {
|
|
|
+ LOG4PLUS_LOG(FATAL, get_logger(), text);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ vtm_string log4cplus_helper::format(const char *ft, ...)
|
|
|
+ {
|
|
|
+ va_list arg;
|
|
|
+ va_start (arg, ft);
|
|
|
+ vtm_string formatted = format(ft, arg);
|
|
|
+ return formatted;
|
|
|
+ }
|
|
|
+
|
|
|
+ vtm_string log4cplus_helper::format(const char *ft,va_list& arg)
|
|
|
+ {
|
|
|
+ int len = 0;
|
|
|
+ vtm_string formatted = "";
|
|
|
+ char* buffer = NULL;
|
|
|
+ len = _vscprintf( ft, arg ) + 1;
|
|
|
+ buffer = (char*)malloc( len * sizeof(char) );
|
|
|
+ len = vsprintf_s(buffer,len,ft, arg);
|
|
|
+ formatted = buffer ;
|
|
|
+ free(buffer);
|
|
|
+ return formatted;
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::log(const char *file_name, const char *func_name, int line,
|
|
|
+ const char* ft, int type /*= log_level_debug*/)
|
|
|
+ {
|
|
|
+ std::stringstream sstream;
|
|
|
+ sstream << file_name << " " << func_name << " " << line << " " << ft << std::endl;
|
|
|
+ switch(type) {
|
|
|
+ case log_level_debug:
|
|
|
+ debug(sstream.str());
|
|
|
+ break;
|
|
|
+ case log_level_trace:
|
|
|
+ trace(sstream.str());
|
|
|
+ break;
|
|
|
+ case log_level_info:
|
|
|
+ info(sstream.str());
|
|
|
+ break;
|
|
|
+ case log_level_warn:
|
|
|
+ warn(sstream.str());
|
|
|
+ break;
|
|
|
+ case log_level_error:
|
|
|
+ error(sstream.str());
|
|
|
+ break;
|
|
|
+ case log_level_fatal:
|
|
|
+ fatal(sstream.str());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ trace(sstream.str());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::log(int log_level, const vtm_string& text)
|
|
|
+ {
|
|
|
+ switch (log_level) {
|
|
|
+ case CMB_LOG_TRACE:
|
|
|
+ trace(text);
|
|
|
+ break;
|
|
|
+ case CMB_LOG_DEBUG:
|
|
|
+ debug(text);
|
|
|
+ break;
|
|
|
+ case CMB_LOG_INFO:
|
|
|
+ info(text);
|
|
|
+ break;
|
|
|
+ case CMB_LOG_WARN:
|
|
|
+ warn(text);
|
|
|
+ break;
|
|
|
+ case CMB_LOG_ERROR:
|
|
|
+ error(text);
|
|
|
+ break;
|
|
|
+ case CMB_LOG_FATAL:
|
|
|
+ fatal(text);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ trace(text);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::log(const char *file_name, const char *func_name, int line,
|
|
|
+ int type ,const char *ft /*= ""*/, ...)
|
|
|
+ {
|
|
|
+ va_list arg;
|
|
|
+ va_start (arg, ft);
|
|
|
+ vtm_string formatted = format(ft, arg);
|
|
|
+ va_end (arg);
|
|
|
+ log(file_name, func_name, line, formatted.c_str(),type);
|
|
|
+ }
|
|
|
+
|
|
|
+ void log4cplus_helper::logw(int log_level, const std::wstring& wtext)
|
|
|
+ {
|
|
|
+ auto text = ::w2s(wtext);
|
|
|
+ log(log_level, text);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|