#include "log4cplus_helper.h" #include #include #include #include #include "log4link.h" #include "exLog/skyeyeLog.h" #if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) #include #define WIN32_CONSOLE 1 #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) { #if defined(_MSC_VER) 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(); #else if (wstr.empty()) { return ""; } unsigned len = wcstombs(NULL, wstr.c_str(), 0) + 1; if (NULL == setlocale(LC_ALL, "zh_CN.gbk")) { } char* p = new char[len]; wcstombs(p, wstr.c_str(), len); p[len - 1] = '\0'; std::string str(p); delete[] p; return str; #endif // _MSC_VER } 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), _initialize_uploaded(false) { _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(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; #if defined(_MSC_VER) log_path += LOG4CPLUS_TEXT("\\"); #else log_path += LOG4CPLUS_TEXT("/"); #endif //_MSC_VER 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(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(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(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; #if defined(_MSC_VER) log_path += "\\"; #else log_path += "/"; #endif //_MSC_VER 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(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(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(); #ifndef USE_SKYEYELOG _upload_helper.unitialize(); #endif _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()); loglink(LOG_LEVEL_DEBUG, text); } } void log4cplus_helper::trace(const char* text) { if(_initialized) { LOG4PLUS_LOG(TRACE, get_logger(), text); loglink(LOG_LEVEL_DEBUG, text); } } void log4cplus_helper::info(const vtm_string& text) { if(_initialized) { LOG4PLUS_LOG(INFO, get_logger(), text.c_str()); loglink(LOG_LEVEL_INFO, text); } } void log4cplus_helper::info(const char* text) { if(_initialized) { LOG4PLUS_LOG(INFO, get_logger(), text); loglink(LOG_LEVEL_INFO, text); } } void log4cplus_helper::debug(const vtm_string& text) { #if !defined(NDEBUG) if(_initialized) { LOG4PLUS_LOG(DEBUG, get_logger(), text.c_str()); loglink(LOG_LEVEL_DEBUG, text); } #endif //!defined(NDEBUG) } void log4cplus_helper::debug(const char* text) { #if !defined(NDEBUG) if(_initialized) { LOG4PLUS_LOG(DEBUG, get_logger(), text); loglink(LOG_LEVEL_DEBUG, text); } #endif //!defined(NDEBUG) } void log4cplus_helper::warn(const vtm_string& text) { if(_initialized) { LOG4PLUS_LOG(WARN, get_logger(), text.c_str()); loglink(LOG_LEVEL_WARN, text); } } void log4cplus_helper::warn(const char* text) { if(_initialized) { LOG4PLUS_LOG(WARN, get_logger(), text); loglink(LOG_LEVEL_WARN, text); } } void log4cplus_helper::error(const vtm_string& text) { if(_initialized) { LOG4PLUS_LOG(ERROR, get_logger(), text.c_str()); loglink(LOG_LEVEL_ERROR, text); } } void log4cplus_helper::error(const char* text) { if(_initialized) { LOG4PLUS_LOG(ERROR, get_logger(), text); loglink(LOG_LEVEL_ERROR, text); } } void log4cplus_helper::fatal(const vtm_string& text) { if(_initialized) { LOG4PLUS_LOG(FATAL, get_logger(), text.c_str()); loglink(LOG_LEVEL_FATAL, text); } } void log4cplus_helper::fatal(const char* text) { if(_initialized) { LOG4PLUS_LOG(FATAL, get_logger(), text); loglink(LOG_LEVEL_FATAL, 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; #if defined(_WIN32) len = _vscprintf(ft, arg) + 1; buffer = (char*)malloc(len * sizeof(char)); len = vsprintf_s(buffer, len, ft, arg); #else buffer = (char*)malloc(MAX_BUFFER_LENGTH + 1); sprintf(buffer, ft, arg); #endif 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); } void log4cplus_helper::initialize_linklog(const log_init_config& config) { #ifdef USE_SKYEYELOG CreateDefaultLogger(config.terminalno, RVC_VERSION_STR, config.dev_name, "100"); #else _upload_helper.initialize(config); #endif } void log4cplus_helper::loglink(LOG_LEVEL_E level, vtm_string text) { #ifdef USE_SKYEYELOG static std::mutex logMtx; logMtx.lock(); GetDefaultLogger()(level, text.c_str()); logMtx.unlock(); #else if (_upload_helper.is_initialized()) { /*LOG_LEVEL_DEBUG = 0, LOG_LEVEL_INFO = 1, LOG_LEVEL_WARN = 2, LOG_LEVEL_ERROR = 3, LOG_LEVEL_FATAL = 4*/ const int converted_ll = ((int)(level)+1) * 10000; if (_log_level <= converted_ll) { log_link link_item((VENDORLOG_LEVEL_E)(int)(level), VENDORLOG_TYPE_SYSTEM); log_item logitem; long cur_time = time(NULL); link_item.result_msg(text).with_extend_log_or_not(false).fetch_log_item(logitem); _upload_helper.pinst_log_producer_client_add_log(_upload_helper._client, &logitem, 1, cur_time); } } #endif } }