瀏覽代碼

#IQRV #comment 复制厂商日志库工程为log4rvcother 为应用其他模块使用

80374374 2 年之前
父節點
當前提交
48724c01e6

+ 2 - 0
Other/CMakeLists.txt

@@ -19,6 +19,8 @@ add_subdirectory(libaudions)
 add_subdirectory(libvideorecord)
 add_subdirectory(libCMBPrint)
 
+add_subdirectory(liblog4rvcother)
+
 if(MSVC)
    add_subdirectory(libimgplayer)
    add_subdirectory(libwmpplayer)

+ 41 - 0
Other/liblog4rvcother/CMakeLists.txt

@@ -0,0 +1,41 @@
+set(MODULE_NAME "log4rvcother")
+set(MODULE_PREFIX "LIB_LOG4RVCOTHER")
+
+set(RAW_VERSION_STRING "2.0.0")
+
+set(${MODULE_PREFIX}_SRCS
+    liblog4rvcother.cpp
+    log4cplus_helper.cpp
+    log4rvcother.cpp
+    mutex.cpp
+	env_deal.cpp
+    log4upload.cpp
+    log4link.cpp
+    )
+
+
+add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
+target_include_directories(${MODULE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+set_target_properties(${MODULE_NAME} PROPERTIES COMPILE_DEFINITIONS "LIBLOG4RVCOTHER_EXPORTS")
+set_target_properties(${MODULE_NAME} PROPERTIES DEBUG_POSTFIX "d")
+
+if(MSVC)
+    list(APPEND OTHER_LIBS Psapi)
+endif(MSVC)
+target_link_libraries(${MODULE_NAME} CONAN_PKG::log4cplus ${OTHER_LIBS})
+
+if(MSVC)
+	install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}" COMPONENT libraries
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT develops EXCLUDE_FROM_ALL
+    LIBRARY DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT libraries
+    )
+else(MSVC)
+install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"
+    LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
+    COMPONENT libraries)
+endif(MSVC)
+
+

+ 44 - 0
Other/liblog4rvcother/ReadMe.txt

@@ -0,0 +1,44 @@
+========================================================================
+    动态链接库:liblog4rvcother 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 liblog4rvcother DLL。
+
+本文件概要介绍组成 liblog4rvcother 应用程序的每个文件的内容。
+
+
+liblog4rvcother.vcxproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 
+    的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+liblog4rvcother.vcxproj.filters
+    这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。 
+    它包含有关项目文件与筛选器之间的关联信息。 在 IDE 
+    中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。
+    例如,“.cpp”文件与“源文件”筛选器关联。
+
+liblog4rvcother.cpp
+    这是主 DLL 源文件。
+
+	此 DLL 在创建时不导出任何符号。 因此,在生成此 DLL 时
+ 	生成时不会产生 .lib 文件。 如果希望此项目
+ 	成为其他某个项目的项目依赖项,则需要
+ 	添加代码以从 DLL 导出某些符号,
+ 	以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
+ 	“链接器”文件夹中,将“常规”属性页上的
+ 	“忽略输入库”属性设置为“是”。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h,StdAfx.cpp
+    这些文件用于生成名为 liblog4rvcother.pch 的预编译头 (PCH) 文件和
+    名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 83 - 0
Other/liblog4rvcother/env_deal.cpp

@@ -0,0 +1,83 @@
+#if defined(_MSC_VER)
+#include "stdafx.h"
+#endif //_MSC_VER
+#include "log4rvcother.h"
+#include <string.h>
+#include "env_deal.h"
+
+namespace cmb {
+
+	env_deal::env_deal(const std::string& name):str_(name)
+	{
+	}
+
+	bool env_deal::set(const std::string& value)
+	{
+#if defined(_MSC_VER)
+        DWORD dwResult = SetEnvironmentVariableA(str_.c_str(), value.c_str());
+        return (dwResult != 0);
+#else
+        if (setenv(str_.c_str(), value.c_str(), 1) != 0)
+            return false;
+        return true;
+#endif //_MSC_VER
+
+	}
+
+	bool env_deal::get(std::string& value)
+	{
+#if defined(_MSC_VER)
+        bool res = false;
+        DWORD dwSize;
+        value.clear();
+        dwSize = GetEnvironmentVariableA(str_.c_str(), NULL, 0);
+        if (dwSize > 0) {
+            char* buf = new char[dwSize + 1];
+            if (buf == NULL) {
+                return false;
+            }
+            memset(buf, '\0', sizeof(char) * (dwSize + 1));
+            dwSize = GetEnvironmentVariableA(str_.c_str(), buf, dwSize);
+            if (dwSize > 0) {
+                value = buf;
+                res = true;
+            }
+            delete[] buf;
+        }
+        return res;
+#else
+        bool res = false;
+        value.clear();
+        char* var = getenv(str_.c_str());
+        if (var == NULL)
+            return false;
+
+        size_t len = strlen(var);
+        if (len > 0) {
+            char* buf = new char[len + 1];
+            if (buf == NULL) {
+                return false;
+            }
+            memset(buf, '\0', sizeof(char) * (len + 1));
+            memcpy(buf, var, len);
+            value = buf;
+            res = true;
+            delete[] buf;
+        }
+        return res;
+#endif //_MSC_VER
+	}
+
+	env_deal::~env_deal(void)
+	{
+	}
+
+	bool env_log_config::retrieve_env_value()
+	{
+		env_deal("VENDOR_RECODE_TYPE").get(record_type);
+		env_deal("VENDOR_RECODE_LEVEL").get(record_level);
+		env_deal("VENDOR_DLL_NAME").get(module_name);
+		env_deal("VENDOR_LOG_PATH").get(record_path);
+        return true;
+	}
+}

+ 39 - 0
Other/liblog4rvcother/env_deal.h

@@ -0,0 +1,39 @@
+#ifndef _VTM_ENV_DEAL_H_
+#define _VTM_ENV_DEAL_H_
+
+#pragma once
+
+#ifdef _WIN32
+#include <Windows.h>
+#endif
+#include <string>
+
+namespace cmb {
+
+	class env_deal
+	{
+	public:
+		env_deal(const std::string& name);
+		bool set(const std::string& value);
+		bool get(std::string& value);
+		~env_deal(void);
+	private:
+		std::string str_;
+	};
+
+	class env_log_config 
+	{
+	public:
+		std::string record_level;
+		std::string record_type;
+		std::string record_path;
+		std::string module_name;
+
+		bool retrieve_env_value();
+	};
+}
+
+
+
+#endif //_VTM_ENV_DEAL_H_
+

+ 155 - 0
Other/liblog4rvcother/liblog4rvcother.cpp

@@ -0,0 +1,155 @@
+// liblog4rvcother.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "liblog4rvcother.h"
+#include <stdio.h>
+
+#if OS_WIN
+#include <Psapi.h>
+#pragma comment(lib, "Psapi.lib")
+#define CUR_PROCESS_NAME "sphost.exe"
+static HMODULE gModule = NULL;
+#else
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#define CUR_PROCESS_NAME "sphost"
+#endif
+static int IsSphostExe = -1;
+
+BOOL GetCurProcessPath(char szPath[], DWORD dwPathSize);
+
+ /*!
+ * @brief detect current process is created by VTM
+ * @return : TRUE: created by VTM; FALSE: created by vendor
+ * TODO: need to enforce it for safety.
+ */
+EXTERN_C BOOL IsVTMProcess()
+{
+	if(IsSphostExe == -1) {
+		char szPath[4096] = {'\0'};
+		DWORD dwPathSize = 4096;
+		if(GetCurProcessPath(szPath, dwPathSize)) {
+			const int pathLen = strlen(szPath);
+			int index;
+			for(index=0; index<pathLen; ++index) {
+				if(szPath[index] >= 'A' && szPath[index] <= 'Z')
+					szPath[index] = 'a' + (szPath[index] - 'A');
+			}
+			char* pos = strstr(szPath, CUR_PROCESS_NAME);
+			dwPathSize = strlen(szPath);
+			if(pos != NULL && ((pos-szPath) + strlen(CUR_PROCESS_NAME)) == dwPathSize) {
+				IsSphostExe = TRUE;
+			} else {
+				IsSphostExe = FALSE;
+			}
+		} else {
+			/*If failed, regard it as VTM environment.*/
+			IsSphostExe = TRUE;
+		}
+	}
+	return IsSphostExe;
+}
+
+EXTERN_C BOOL GetCurFileVersion(char szVerion[], DWORD dwVerionSize)
+{
+
+#if OS_WIN
+
+	HRSRC hsrc=FindResourceA(gModule, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
+	HGLOBAL hgbl = LoadResource(gModule, hsrc);
+	BYTE *pBt = (BYTE *)LockResource(hgbl);
+	VS_FIXEDFILEINFO* pFinfo = (VS_FIXEDFILEINFO*)(pBt + 40);
+	sprintf_s(szVerion, dwVerionSize, "%d.%d.%d.%d",
+		(pFinfo->dwFileVersionMS >> 16) & 0xFF,
+		(pFinfo->dwFileVersionMS) & 0xFF,
+		(pFinfo->dwFileVersionLS >> 16) & 0xFF,
+		(pFinfo->dwFileVersionLS) & 0xFF);
+
+#endif
+
+	return TRUE;
+}
+
+#if OS_WIN
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+	DWORD  ul_reason_for_call,
+	LPVOID lpReserved
+	)
+{
+	switch (ul_reason_for_call)
+	{
+	case DLL_PROCESS_ATTACH:
+		gModule = hModule;
+		IsVTMProcess();
+		break;
+	case DLL_THREAD_ATTACH:
+	case DLL_THREAD_DETACH:
+	case DLL_PROCESS_DETACH:
+		break;
+	}
+	return TRUE;
+}
+
+BOOL GetCurProcessPath(char szPath[], DWORD dwPathSize)
+{
+	ZeroMemory(szPath, sizeof(char)*dwPathSize);
+	const DWORD PID = GetCurrentProcessId();
+	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 
+		FALSE, PID);
+
+	if (hProcess == NULL) {
+		return FALSE;
+	}
+	
+	if (GetModuleFileNameExA(hProcess, (HMODULE)0, szPath, dwPathSize) == 0) {
+		printf("GetModuleFileNameExA failed: %d\n", GetLastError());
+		DWORD dwSize = dwPathSize;
+		if(QueryFullProcessImageNameA(hProcess, 0, szPath, &dwSize) == 0)
+		{
+			printf("QueryFullProcessImageNameA failed: %d\n", GetLastError());
+			if (!GetProcessImageFileNameA(hProcess, szPath, dwSize)) {
+				printf("GetProcessImageFileNameA failed: %d\n", GetLastError());
+				CloseHandle(hProcess);
+				return FALSE;
+			}
+		}
+	}
+	
+	CloseHandle(hProcess);
+
+	printf("process image name: %s\n", szPath);
+	return TRUE;
+
+}
+
+#else
+
+BOOL GetCurProcessPath(char szPath[], DWORD dwPathSize)
+{
+    int status;
+    size_t length;
+    char path[64];
+    char buffer[4096];
+	snprintf(path, 64, "/proc/%d/exe", getpid());
+    status = readlink(path, buffer, sizeof(buffer));
+    if (status < 0) {
+        return FALSE;
+    }
+
+    buffer[status] = '\0';
+    length = strnlen(buffer, sizeof(buffer));
+	memset(szPath, '\0', sizeof(szPath[0]) * dwPathSize);
+    if (length < dwPathSize) {
+		memcpy(szPath, buffer, length);
+		szPath[length] = '\0';
+        return TRUE;
+    }
+
+	memcpy(szPath, buffer, dwPathSize - 1);
+	szPath[dwPathSize - 1] = '\0';
+    return FALSE;
+}
+
+#endif

+ 54 - 0
Other/liblog4rvcother/liblog4rvcother.h

@@ -0,0 +1,54 @@
+#ifndef RVC_VENDOR_LOG4RVCOTHER_H_
+#define RVC_VENDOR_LOG4RVCOTHER_H_
+
+#pragma once
+
+#if (defined(_WIN32) || defined(_WIN64))
+#define OS_WIN 1
+#else
+#define OS_WIN 0
+#endif
+
+#ifndef _WIN32
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#define EXTERN_C       extern "C"
+#define EXTERN_C_START extern "C" {
+#define EXTERN_C_END   }
+#else
+#define EXTERN_C       extern
+#define EXTERN_C_START
+#define EXTERN_C_END
+#endif
+
+typedef uint8_t BYTE;
+typedef uint8_t* LPBYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef char CHAR;
+typedef uint8_t BOOL;
+
+#define TRUE 1
+#define FALSE 0
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+#else
+
+#include <SDKDDKVer.h>
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
+#endif
+// Windows 头文件:
+#include <windows.h>
+#endif
+
+EXTERN_C BOOL IsVTMProcess();
+
+EXTERN_C BOOL GetCurFileVersion(char szVerion[], DWORD dwVerionSize);
+
+#endif

+ 532 - 0
Other/liblog4rvcother/log4cplus_helper.cpp

@@ -0,0 +1,532 @@
+#include "log4cplus_helper.h"
+#include <iostream>
+#include <string>
+#include <string.h>
+
+#include "log4link.h"
+
+#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
+#include <log4cplus/win32consoleappender.h>
+#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)
+	{
+		_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;
+#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<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;
+#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<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();
+			_upload_helper.unitialize();
+			_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(INFO, 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)
+    {
+		_upload_helper.initialize(config);
+    }
+
+    void log4cplus_helper::loglink(LOG_LEVEL_E level, vtm_string text)
+    {
+        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;
+                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);
+			}
+        }
+    }
+}

+ 185 - 0
Other/liblog4rvcother/log4cplus_helper.h

@@ -0,0 +1,185 @@
+#ifndef _VTM_LOG4CPLUS_HELPER_H_
+#define _VTM_LOG4CPLUS_HELPER_H_
+
+#pragma once
+
+#include "log4rvcother.h"
+#include <cstdint>
+#include <iostream>
+#include <set>
+#include <queue>
+
+#include <log4cplus/consoleappender.h>
+#include <log4cplus/fileappender.h>
+#include <log4cplus/socketappender.h>
+#include <log4cplus/asyncappender.h>
+#include <log4cplus/nullappender.h>
+#include <log4cplus/appender.h>
+#include <log4cplus/layout.h>
+#include <log4cplus/logger.h>
+#include <log4cplus/ndc.h>
+#include <log4cplus/helpers/loglog.h>
+#include <log4cplus/streams.h>
+#include <log4cplus/loggingmacros.h>
+#include <log4cplus/configurator.h>
+
+#include "log4upload.h"
+
+#include "mutex.h"
+
+namespace cmb {
+
+	enum cpluslog_level
+	{
+		log_level_debug = 0,
+		log_level_trace,
+		log_level_info,
+		log_level_warn,
+		log_level_error,
+		log_level_fatal,
+		log_level_end
+	};
+
+	enum cpluslog_append_type
+	{
+		log_append_none = 0,
+		log_append_console = 1,
+		log_append_file = 2,
+		log_append_console_file = 3,
+		log_append_socket = 4,
+		log_append_console_socket = 5,
+		log_append_file_socket = 6,
+		log_append_all = 7
+	};
+
+	class log4cplus_helper : public log4rvcother
+	{
+	public:
+		~log4cplus_helper(void);
+		static log4cplus_helper* get_instance();
+		bool init(const char* name);
+		void uninit();
+		std::ostream& stream();
+
+		void trace(const vtm_string& text);
+		void info(const vtm_string& text);
+		void debug(const vtm_string& text);
+		void warn(const vtm_string& text);
+		void error(const vtm_string& text);
+		void fatal(const vtm_string& text);
+
+		void trace(const char* text);
+		void info(const char* text);
+		void debug(const char* text);
+		void warn(const char* text);
+		void error(const char* text);
+		void fatal(const char* text);
+
+		bool set_log_append_type(int type) {
+			if((type & log_append_console) || (type & log_append_file) || (type & log_append_socket)) {
+				_append_type = type;
+				return true;
+			}
+			return false;
+		}
+
+		 /*!
+		 * @brief 设置日志文件存储的路径文件夹
+		 * @param[in] 存储的文件夹路径,兼容不加 '\\' 的情况  
+		 * @return : 
+		 */
+		bool set_log_dir(const vtm_string& log_file) {
+
+			vtm_string tmp(log_file);
+			if(tmp.empty()) 
+				return false;
+			if(tmp[tmp.size()-1] != '\\' && tmp[tmp.size()-1] != '/') {
+#if defined(_MSC_VER)
+				tmp.push_back('\\');
+#else
+				tmp.push_back('/');
+#endif //_MSC_VER
+			} 
+			_log_dir = tmp;
+			return true;
+		}
+
+		bool set_log_level(const int level) {
+			const int ll = level * 10000;
+			if(ll < 0 || ll > log4cplus::OFF_LOG_LEVEL) {
+				return false;
+			}
+			_log_level = ll;
+			return true;
+		}
+
+		void update_map_value(const vtm_string& value) {
+			if(!value.empty()) {
+				log4cplus::getMDC ().put("key", value);
+			}
+		}
+
+		vtm_string get_map_value() {
+			vtm_string value("");
+			if(!log4cplus::getMDC().get(&value, "key")) {
+				return vtm_string("");
+			}
+			return value;
+		}
+		int run_log_sender(const vtm_string& ip, const unsigned short port);
+
+		vtm_string format(const char *ft, ...);
+		vtm_string format(const char *ft,va_list& arg);
+
+		void log( const char *file_name, const char *func_name, int line, const char* ft, int type = log_level_debug);
+		void log( const char *file_name, const char *func_name, int line, int type ,const char *ft = "", ...);
+		void log(int log_level, const vtm_string& text);
+
+		void logw(int log_level, const std::wstring& wtext);
+
+		log4cplus::Logger get_logger() {
+			return log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(_log_key_name.c_str()));
+		}
+
+		void initialize_linklog(const log_init_config& config);
+		void loglink(LOG_LEVEL_E level, vtm_string text);
+	private:
+		static log4cplus_helper* _instance;
+		log4cplus_helper(void);
+
+		void config_remote_logger(const char* remote_name);
+
+		log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> _append_console;
+		log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> _append_file;
+		log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> _append_socket;
+		log4cplus::helpers::SharedObjectPtr<log4cplus::Appender> _append_none;
+
+		log4cplus::tstring _log_dir;
+		log4cplus::tstring _log_server_ip;
+		unsigned short _log_server_port;
+		vtm_string _log_client_key_name;
+
+		int _append_type;
+		vtm_string _log_key_name;
+		bool _socket_send_running;
+		static mutex _mutex;
+		bool _initialized;
+
+		unsigned short _log_listen_port;
+		mutex _mutex_4_update_socket;
+
+		bool _initilzed_zip;
+		std::queue<vtm_string> _zip_logs;
+		vtm_string _cur_upload_log;
+		uint64_t _cur_upload_offset;
+
+		int _log_level;
+
+		upload_helper _upload_helper;
+	};
+}
+
+
+
+
+#endif //_VTM_LOG4CPLUS_HELPER_H_

+ 155 - 0
Other/liblog4rvcother/log4link.cpp

@@ -0,0 +1,155 @@
+#include "log4link.h"
+
+#define MAX_LOG_LEN 2000
+
+log_link::log_link(VENDORLOG_LEVEL_E t_level, VENDORLOG_TYPE_E t_type)
+    :m_private(new log_link_private(t_level, t_type))
+{
+
+}
+
+log_link::~log_link()
+{
+    if (m_private) delete m_private;
+}
+
+log_link& log_link::result_code(std::string value)
+{
+    if(m_private != nullptr)
+        m_private->result_code = value;
+    return *this;
+}
+
+log_link& log_link::trace_id(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->trace_id = value;
+    return *this;
+}
+
+log_link& log_link::result_msg(std::string value)
+{
+    if (m_private != nullptr) {
+        if (value.length() > MAX_LOG_LEN)
+            m_private->result_msg = value.substr(0, MAX_LOG_LEN);
+        else 
+            m_private->result_msg = value;
+    }
+    return *this;
+}
+
+log_link& log_link::log_code(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->log_code = value;
+    return *this;
+}
+
+log_link& log_link::api(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->apii = value;
+    return *this;
+}
+
+log_link& log_link::business_id(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->business_id = value;
+    return *this;
+}
+
+log_link& log_link::tip_msg(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->tip_msg = value;
+    return *this;
+}
+
+log_link& log_link::src_type(std::string value)
+{
+    if (m_private != nullptr)
+        m_private->src_type = value;
+    return *this;
+}
+
+log_link& log_link::begin_time(long value)
+{
+    if (m_private != nullptr)
+        m_private->begin_time = value;
+    return *this;
+}
+
+log_link& log_link::end_time(long value)
+{
+    if (m_private != nullptr)
+        m_private->end_time = value;
+    return *this;
+}
+
+log_link& log_link::cost_time(long value)
+{
+	if (m_private != nullptr)
+		m_private->cost_time = value;
+	return *this;
+}
+
+log_link& log_link::log_producer(void* producer)
+{
+    if (m_private != nullptr)
+        m_private->log_producer = producer;
+    return *this;
+}
+
+log_link& log_link::with_extend_log_or_not(bool value)
+{
+    if (m_private != nullptr)
+        m_private->do_log = value;
+    return *this;
+}
+
+void log_link::operator()() const
+{
+    if (!m_private->IsAllowToRecord()) {
+        return;
+    }
+    log_item log;
+    log.Level = (LOG_LEVEL_E)(int)m_private->level;
+    log.Type = (LOG_TYPE_E)(int)m_private->type;
+    log.LogCode = (char*)m_private->log_code.c_str();
+    log.API = (char*)m_private->apii.c_str();
+    log.ResultCode = (char*)m_private->result_code.c_str();
+    log.ResultMsg = (char*)m_private->result_msg.c_str();
+    log.TipMsg = (char*)m_private->tip_msg.c_str();
+    log.BeginTime = m_private->begin_time;
+    log.EndTime = m_private->end_time;
+    log.CostTime = m_private->cost_time;
+    log.TraceID = (char*)m_private->trace_id.c_str();
+    log.BussID = (char*)m_private->business_id.c_str();
+    log.SourceType = (char*)m_private->src_type.c_str();
+
+    log_producer_client* cur = NULL;
+    if (m_private->log_producer != nullptr) {
+        cur = (log_producer_client*)m_private->log_producer;
+    } else {
+        return;
+    }
+}
+
+void log_link::fetch_log_item(log_item& log)
+{
+    log.Level = (LOG_LEVEL_E)(int)m_private->level;
+    log.Type = (LOG_TYPE_E)(int)m_private->type;
+    log.LogCode = (char*)m_private->log_code.c_str();
+    log.API = (char*)m_private->apii.c_str();
+    log.ResultCode = (char*)m_private->result_code.c_str();
+    log.ResultMsg = (char*)m_private->result_msg.c_str();
+    log.TipMsg = (char*)m_private->tip_msg.c_str();
+    log.BeginTime = m_private->begin_time;
+    log.EndTime = m_private->end_time;
+    log.CostTime = m_private->cost_time;
+    log.TraceID = (char*)m_private->trace_id.c_str();
+    log.BussID = (char*)m_private->business_id.c_str();
+    log.SourceType = (char*)m_private->src_type.c_str();
+}
+

+ 93 - 0
Other/liblog4rvcother/log4link.h

@@ -0,0 +1,93 @@
+#ifndef RVC_VENDOR_LOG4LINK_H_
+#define RVC_VENDOR_LOG4LINK_H_
+
+#include <string>
+#include "log4upload.h"
+
+typedef enum
+{
+    VENDORLOG_TYPE_SYSTEM = 0/*系统日志*/,
+    VENDORLOG_TYPE_USER = 1/*用户日志*/,
+    VENDORLOG_TYPE_BUSINESS_SYSTEM = 2,
+    VENDORLOG_TYPE_BUSINESS_USER = 3
+} VENDORLOG_TYPE_E;
+
+typedef enum
+{
+    VENDORLOG_LEVEL_DEBUG = 0,
+    VENDORLOG_LEVEL_INFO = 1,
+    VENDORLOG_LEVEL_WARN = 2,
+    VENDORLOG_LEVEL_ERROR = 3,
+    VENDORLOG_LEVEL_FATAL = 4
+} VENDORLOG_LEVEL_E;
+
+typedef int vendorlog_producer_result;
+
+class log_link_private 
+{
+public:
+    VENDORLOG_LEVEL_E level;
+    VENDORLOG_TYPE_E type;
+    std::string result_code;
+    std::string trace_id;
+    std::string result_msg;
+    std::string log_code;
+    std::string apii;
+
+    long begin_time;
+    long end_time;
+    long cost_time;
+
+    std::string business_id;
+    std::string tip_msg;
+    std::string src_type;
+    void* log_producer;
+    bool do_log;
+
+    log_link_private(VENDORLOG_LEVEL_E t_level, VENDORLOG_TYPE_E t_type)
+        : level(t_level), type(t_type)
+        , result_code("SUC0000"),trace_id(""), result_msg(""), log_code(""), apii("")
+        , begin_time(0), end_time(0), cost_time(0)
+        , business_id(""), tip_msg(""), src_type(""), log_producer(nullptr), do_log(true)
+    {
+    }
+    bool IsAllowToRecord()
+     {
+        return (this->level >= VENDORLOG_LEVEL_INFO);
+    }
+};
+
+class log_link
+{
+public:
+    log_link(VENDORLOG_LEVEL_E t_level, VENDORLOG_TYPE_E t_type);
+    ~log_link();
+    //用户、系统日志均必填,交易处理结果代码,0表示处理成功,其他表示失败,可为系统本身的错误码,也可为后台系统返回的错误码
+    log_link& result_code(std::string value);
+    //用户、系统日志均必填,业务跟踪ID, 32字节长度的字符串,唯一识别每笔请求
+    log_link& trace_id(std::string value);
+    //用户、系统日志LOG_LEVEL_WARN以上必填
+    //交易处理结果信息,包括成功与失败信息,可为系统本身的成功/失败信息,也可为后台系统返回的成功/失败信息.
+    log_link& result_msg(std::string value);
+    //用户日志必填,日志码
+    //终端中标识各个交易如读卡、读取身份证等。如果终端由于客观原因无法识别交易场景,则可字段由上游传入。
+    log_link& log_code(std::string value);
+    log_link& api(std::string value);//用户日志必填,请求路径/接口名称.
+    log_link& business_id(std::string value);//用户日志必填,请求业务ID
+    log_link& tip_msg(std::string value);//用户日志LOG_LEVEL_WARN以上必填,直接向客户展示的报错信息.
+    log_link& src_type(std::string value);//系统日志LOG_LEVEL_FATAL必填,异常来源类型
+    log_link& begin_time(long value);//用户日志必填, 请求发送/接收时间
+    log_link& end_time(long value);//用户日志必填, 响应接收 / 应答时间
+    log_link& cost_time(long value);//消耗时间,自定义字段,单位ms
+    log_link& log_producer(void* producer);
+    log_link& with_extend_log_or_not(bool value);//是否log到文件中,并行阶段需要log到文件
+    void operator () ()  const;
+    void fetch_log_item(log_item& log);
+private:
+    log_link_private* const m_private;
+private:
+    log_link(const log_link&) : m_private(nullptr) {};
+    const log_link& operator=(const log_link&) { return *this; };
+};
+
+#endif //RVC_VENDOR_LOG4LINK_H_

+ 308 - 0
Other/liblog4rvcother/log4rvcother.cpp

@@ -0,0 +1,308 @@
+#include "log4rvcother.h"
+#include "liblog4rvcother.h"
+#include "log4cplus_helper.h"
+#include "env_deal.h"
+#include <vector>
+#ifndef _WIN32
+#include<sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#else
+#include <process.h>
+#endif //NOT _WIN32
+
+#if defined(_MSC_VER)
+#define LIBRARY_POSIXNAME "DLL"
+#else
+#define LIBRARY_POSIXNAME "SO"
+
+#endif //_MSC_VER
+
+namespace cmb {
+
+	static bool log4plus_initialized = false;
+
+	class log4none : public log4rvcother
+	{
+	public:
+		log4none() {}
+		void log(int log_level, const std::string& text) {/*do nothing.*/}
+		~log4none() {
+			/*通过全局静态变量的销毁函数中释放有效的日志实例对象*/
+			if(log4plus_initialized) {
+				LOG4VTM(INFO, "release log instance auto.");
+				log4cplus_helper::get_instance()->uninit();
+			}
+		}
+	};
+	/*在有效日志类实例没被初始化前返回的一个替代品*/
+	static log4none default_instance;
+
+	log4rvcother* log4rvcother::instance()
+	{
+		if(!log4plus_initialized)
+			return &default_instance;
+
+		return log4cplus_helper::get_instance();
+	}
+
+	std::vector<std::string> split(std::string str, char split_char)
+	{
+		std::vector<std::string> strs;
+		std::string::size_type pos1, pos2;
+		pos2 = str.find(split_char);
+		pos1 = 0;
+		while (std::string::npos != pos2) {
+
+			strs.push_back(str.substr(pos1, pos2 - pos1));
+			pos1 = pos2 + 1;
+			pos2 = str.find(split_char, pos1);
+		}
+		strs.push_back(str.substr(pos1));
+		return strs;
+	}
+	std::string toupper(const std::string str)
+	{
+		std::string dest;
+		dest.resize(str.size());
+		std::transform(str.begin(), str.end(), dest.begin(), ::toupper);
+		return dest;
+	}
+
+    bool start_with(std::string const& s, std::string const& prefix)
+    {
+        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
+    }
+
+	/*从环境变量中提取的信息转换成日志配置结构体信息*/
+	static void env2config(const env_log_config& env, log_init_config* config)
+	{
+		config->dev_name = "";
+		config->log_dir = "";
+		config->log_level = CMB_LOG_LEVEL_OFF;
+		config->log_type = 0; /*OFF*/
+
+		//if(env.record_type.find("CONSOLE") != std::string::npos)
+		//	config->log_type |= CMB_LOG_TYPE_CONSOLE;
+		const std::string record_type = toupper(env.record_type);
+		if(record_type.find("FILE") != std::string::npos)
+			config->log_type |= CMB_LOG_TYPE_FILE;
+
+		/*get log level*/
+		const std::string record_level = toupper(env.record_level);
+		if(record_level.find("TRACE") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_TRACE;
+		else if(record_level.find("INFO") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_INFO;
+		else if(record_level.find("WARN") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_WARN;
+		else if(record_level.find("ERROR") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_ERROR;
+		else if(record_level.find("FATAL") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_FATAL;
+		else if(record_level.find("ALL") != std::string::npos)
+			config->log_level = CMB_LOG_LEVEL_ALL;
+
+		auto dev_infos = split(env.module_name, '.');
+		//TODO: comfirm the name's validity. {DeviceName}.{VendorName}.{X}.{Y}.dll
+		if(dev_infos.size() == 5 && toupper(dev_infos[4]) == LIBRARY_POSIXNAME) {
+			config->dev_name = "vendor_";
+#if defined(_MSC_VER)
+			config->dev_name += dev_infos[0];
+#else
+            {
+                auto lib_name = toupper(dev_infos[0]);
+                auto lib_prefix = std::string("LIB");
+                if (start_with(lib_name, lib_prefix)) {
+                    lib_name = dev_infos[0].substr(lib_prefix.length());
+                } else {
+                    lib_name = dev_infos[0];
+                }
+                config->dev_name += lib_name;
+            }
+#endif //_MSC_VER
+		}
+		config->log_dir = env.record_path;
+	}
+
+#ifndef _WIN32
+    void log4rvcother::initp(const log_init_config_c* pconfig, char pret_msg[RVCOTHER_BUFF_SIZE])
+    {
+        std::string msg("");
+        if (pconfig != nullptr) {
+            log_init_config config1;
+            config1.dev_name = pconfig->dev_name;
+            config1.log_dir = pconfig->log_dir;
+            config1.log_level = pconfig->log_level;
+            config1.log_type = pconfig->log_type;
+
+            init(config1, msg);
+            if (!msg.empty()) {
+                strcpy(pret_msg, msg.c_str());
+            }
+        } else {
+            std::strcpy(pret_msg, "error param: nullptr");
+        }
+    }
+#endif //NOT _WIN32
+
+	void log4rvcother::init(const log_init_config& config, std::string& ret_msg)
+	{
+		ret_msg.clear();
+		std::string env_string = "[RVC] ";
+		log_init_config* lhs = const_cast<log_init_config*>(&config);
+		log_init_config log_env_config;
+		std::string instance_name;
+		bool is_vtm_env(false);
+
+		if(log4plus_initialized) {
+			assert(log4rvcother::instance() != &default_instance);
+			ret_msg = "WARN: log instance has been initialized.";
+			goto error_point;
+		}
+
+		if(IsVTMProcess()) {
+			is_vtm_env = true;
+			ret_msg = env_string + "INFO: vtm runtime, it's VTMers' responsibility to do initialize job.";
+			env_log_config log_config;
+			if(log_config.retrieve_env_value()) {
+				env2config(log_config, &log_env_config);
+				lhs = &log_env_config;
+				if(!log_config.module_name.empty()) {
+					env_string = log_config.module_name;
+				}
+			} else {
+				ret_msg = env_string + " WARN: vtm runtime, retrieve config failed.";
+				goto error_point;
+			}
+		} else {
+			env_string = "";
+		}
+
+		if(!log4cplus_helper::get_instance()->set_log_append_type(lhs->log_type)) {
+			ret_msg = env_string + " -- ERROR: set log type failed.";
+			goto error_point;
+		}
+
+		if(!log4cplus_helper::get_instance()->set_log_level(lhs->log_level)) {
+			ret_msg = env_string + " -- ERROR: set log level failed.";
+			goto error_point;
+		}
+
+		if(!log4cplus_helper::get_instance()->set_log_dir(lhs->log_dir)) {
+			ret_msg = env_string + " -- ERROR: set log dir failed.";
+			goto error_point;
+		}
+
+		if(!log4cplus_helper::get_instance()->init(lhs->dev_name.c_str())) {
+			ret_msg = env_string + " -- ERROR: real init failed.";
+			goto error_point;
+		}
+		instance_name = lhs->dev_name;
+		if(!env_string.empty()) {
+			instance_name = env_string;
+		}
+
+		/*提前在这里赋值,以便让 LOG4VTM 宏生效*/
+		log4plus_initialized = true;
+        if (is_vtm_env) {
+            log4cplus_helper::get_instance()->initialize_linklog(*lhs);
+        }
+		LOG4VTM(INFO, "==============Log4Vendor(" << instance_name << ") start==============");
+#if defined(_MSC_VER)
+		LOG4VTM(INFO, "process id: " << GetCurrentProcessId());
+#else
+		LOG4VTM(INFO, "process id: " << getpid());
+#endif //_MSC_VER
+		{
+			char ver[128] = {'\0'};
+			DWORD sz = 128;
+			GetCurFileVersion(ver, sz);
+			LOG4VTM(INFO, "log4rvcother instance' s version: " << ver);
+		}
+		return;
+
+error_point:
+
+		std::string ps = ret_msg + "\n";
+#if defined(_MSC_VER)
+		OutputDebugStringA(ps.c_str());
+#endif //_MSC_VER
+	}
+
+	/*获取输出字符串流引用对象,不自己定义,从开源库中获取会比较安全*/
+	std::basic_ostringstream<char>& log4rvcother::get_oss()
+	{
+		LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var);
+		return var;
+	}
+
+	//////////////////////////////////////////////////////////////////////////
+
+		//class log4vendor_tracer::
+
+
+	log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine)
+		:m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine), m_pnRet(NULL), m_pDwRet(NULL), m_retType(-1)
+	{
+		std::ostringstream str;
+		str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
+		log4cplus_helper::get_instance()->trace(str.str());
+	}
+	log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet)
+		:m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
+		, m_pnRet(pRet), m_pDwRet(NULL), m_pfRet(NULL), m_retType(0)
+	{
+		std::ostringstream str;
+		str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
+		log4cplus_helper::get_instance()->trace(str.str());
+	}
+#if defined(_MSC_VER)
+	log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, unsigned long* pRet)
+#else
+    log4vendor_tracer::log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet)
+#endif //_MSC_VER
+		:m_pszMes(message), m_pszFileN(fileName), m_nLine(nLine)
+		, m_pnRet(NULL), m_pDwRet(pRet), m_pfRet(NULL), m_retType(1)
+	{
+		std::ostringstream str;
+		str << "==> Enter {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
+		log4cplus_helper::get_instance()->trace(str.str());
+	}
+	log4vendor_tracer::~log4vendor_tracer()
+	{
+		std::ostringstream str;
+		if(m_retType == 0)
+		{
+			str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pnRet << "}.";
+		}
+		else if(m_retType == 1)
+		{
+			str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pDwRet << "}.";
+		}
+		else if (m_retType == 2)
+		{
+			str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}, return: {" << *m_pfRet << "}.";
+		}
+		else {
+			str << "<== Leave {" << m_pszMes << "}, file: {" << m_pszFileN << "}, line: {" << m_nLine << "}.";
+		}
+		log4cplus_helper::get_instance()->trace(str.str());
+	}
+
+	const char* log4vendor_tracer::_get_file_name(const char* file_path)
+	{
+		if(file_path == NULL || strlen(file_path) == 0) {
+			return "empty";
+		}
+		const char* backlash = strrchr(file_path, (int)('\\'));
+		if(backlash == NULL) {
+			backlash = strrchr(file_path, (int)('/'));
+		}
+		if(!backlash) {
+			return file_path;
+		}
+		return (backlash+1);
+	}
+}
+

+ 233 - 0
Other/liblog4rvcother/log4rvcother.h

@@ -0,0 +1,233 @@
+#ifndef _VTM_LOG4RVCOTHER_H_
+#define _VTM_LOG4RVCOTHER_H_
+
+#pragma once
+
+#include <sstream>
+#include <string>
+#include <cstring>
+
+#ifdef _WIN32
+#ifdef LIBLOG4RVCOTHER_EXPORTS
+#define LOG4RVCOTHER_API __declspec(dllexport)
+#else
+#define LOG4RVCOTHER_API __declspec(dllimport)
+#endif
+#else
+#if ( defined(__GNUC__) &&  __GNUC__ >= 4 )
+#define LOG4RVCOTHER_API __attribute__((visibility("default")))
+#else
+#define LOG4RVCOTHER_API
+#endif
+#endif
+
+#ifdef UNICODE
+#error This version is not support {UNICODE} char set!!
+#define LOG4VTM_TEXT2(STRING) L##STRING
+typedef std::wstring vtm_string;
+typedef wchar_t vtm_char;
+#else
+#define LOG4VTM_TEXT2(STRING) STRING
+typedef std::string vtm_string;
+typedef char vtm_char;
+#endif // UNICODE
+#define LOG4VTM_TEXT(STRING) LOG4VTM_TEXT2(STRING)
+
+#ifndef RVC_VENDOE_BUILDIN_TYPE
+#if (defined(_WIN32) || defined(_WIN64))
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef unsigned long* PDWORD;
+#else
+typedef uint8_t BYTE;
+typedef uint8_t* LPBYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef uint32_t* PDWORD;
+typedef char CHAR;
+#endif
+#define RVC_VENDOE_BUILDIN_TYPE
+#endif // !RVC_VENDOE_BUILDIN_TYPE
+
+#if defined(_MSC_VER)
+#define LOG4VTM_START_DOWHILE_WARNING()  \
+    __pragma (warning (push))                 \
+    __pragma (warning (disable:4127))           
+
+#define LOG4VTM_END_DOWHILE_WARNING()   \
+    __pragma (warning (pop))
+
+#else
+#define LOG4VTM_START_DOWHILE_WARNING()
+#define LOG4VTM_END_DOWHILE_WARNING()
+#endif
+
+#define CMB_LOG_TYPE_CONSOLE 1   /*控制台输出*/
+#define CMB_LOG_TYPE_FILE    2   /*文件记录输出*/
+#define CMB_LOG_TYPE_SOCKET  4   /*TCP传输输出,暂未实现*/
+
+#define CMB_LOG_LEVEL_OFF     6  /*关闭任何日志输出*/
+#define CMB_LOG_LEVEL_FATAL   5  /*非常严重类型的日志输出*/
+#define CMB_LOG_LEVEL_ERROR   4  /*错误类型的日志输出*/
+#define CMB_LOG_LEVEL_WARN    3  /*告警类型的日志输出*/
+#define CMB_LOG_LEVEL_INFO    2  /*普通日志输出*/
+#define CMB_LOG_LEVEL_DEBUG   1  /*调试日志输出*/
+#define CMB_LOG_LEVEL_TRACE   0  /*跟踪函数进出等输出*/
+#define CMB_LOG_LEVEL_ALL     CMB_LOG_LEVEL_TRACE
+
+#define CMB_LOG_TRACE   1
+#define CMB_LOG_DEBUG   2
+#define CMB_LOG_INFO    3
+#define CMB_LOG_WARN    4
+#define CMB_LOG_ERROR   5
+#define CMB_LOG_FATAL   6
+//#define CMB_LOG_ASSERT  7
+
+#define CMB_INSTANTIATE_OSTRINGSTREAM(var)                              \
+	std::basic_ostringstream<char>& var                                 \
+	= cmb::log4rvcother::get_oss()
+
+#define CMB_LOG_BODY(logLevel, logEvent)                                         \
+	LOG4VTM_START_DOWHILE_WARNING()                                          \
+    do {                                                                                                       \
+        cmb::log4rvcother* _l                                                                         \
+            = cmb::log4rvcother::instance();                                                    \
+		CMB_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf);               \
+		_log4cplus_buf << logEvent;                                                          \
+        _l->log(logLevel, _log4cplus_buf.str());                                           \
+    } while (0)                                                                                            \
+    LOG4VTM_END_DOWHILE_WARNING()
+
+
+ /*!
+ * @brief 打印日志的函数,所有等级的日志打印均通过该宏调用实现
+ * @param[in]
+ *		severity: 日志等级 TRACE, INFO, WARN, ERROR, FATAL, ASSERT
+ *		ostr:     要打印的内容,支持 << 连续输出
+ */
+#define LOG4VTM(severity, ostr)                                        \
+    CMB_LOG_BODY(CMB_LOG_ ## severity, ostr)
+
+ /*!
+ * @brief: 用于记录函数进出的宏定义,在进入目的函数时立即调用,在该函数退出时会打印日志
+/**/
+#define LOG4VTM_FUNCTION() cmb::log4vendor_tracer _FunctionTraceLogger(\
+	__FUNCTION__, cmb::log4vendor_tracer::_get_file_name(__FILE__), __LINE__)
+
+/*!
+* @brief 类似于 LOG4VTM_FUNCTION(),除外还添加一个入参用于打印返回值,注意该入参的生命周期为整个函数内!!
+* @param[in]: pValue - 仅支持传入 int* 或 DWORD* 类型,在日志中会打印指针所存储的值
+*/
+#define TRACE4VTM_FUNCTION(pValue) cmb::log4vendor_tracer _FunctionTraceLogger(\
+	__FUNCTION__, cmb::log4vendor_tracer::_get_file_name(__FILE__), __LINE__, (pValue))
+
+#define RVCOTHER_BUFF_SIZE 256
+
+namespace cmb
+{
+	struct log_init_config_c
+	{
+		short log_type;       /*见上面 CMB_LOG_TYPE_FILE 等定义*/
+		short log_level;      /*见上面 CMB_LOG_TRACE 等定义*/
+		char dev_name[RVCOTHER_BUFF_SIZE];  /*硬件名称,用于作为子目录的区分*/
+		char log_dir[RVCOTHER_BUFF_SIZE];  /*在 log_type 包含 CMB_LOG_TYPE_FILE 时,该参数才有效,用于记录日志的目录*/
+	};
+
+	struct LOG4RVCOTHER_API log_init_config
+	{
+		short log_type;       /*见上面 CMB_LOG_TYPE_FILE 等定义*/
+		short log_level;      /*见上面 CMB_LOG_TRACE 等定义*/
+		std::string dev_name;  /*硬件名称,用于作为子目录的区分*/
+		std::string log_dir;  /*在 log_type 包含 CMB_LOG_TYPE_FILE 时,该参数才有效,用于记录日志的目录*/
+
+		log_init_config()
+			:log_type(CMB_LOG_TYPE_FILE)
+			, log_level(CMB_LOG_TRACE)
+			, dev_name(LOG4VTM_TEXT("VTM")), log_dir(LOG4VTM_TEXT(""))
+		{
+		}
+
+		log_init_config(const log_init_config& rhs)
+			:log_type(rhs.log_type)
+			, log_level(rhs.log_level)
+			, dev_name(rhs.dev_name), log_dir(rhs.log_dir)
+		{
+		}
+	};
+
+	class LOG4RVCOTHER_API log4rvcother
+	{
+	public:
+
+		static log4rvcother* instance();
+
+		/*!
+		* @brief 在调用打印日志的相关宏时,请先调用此函数进行初始化,否则将不会打印任何形式的日志内容
+		*
+		* @param[in]
+		*		config: 日志初始化的配置参数
+		*		ret_msg: 防止传入的参数有误,在必要的时候记录错误信息,供上层打印排查
+		*
+		*	如传入的参数依次为:"PinPad", CMB_LOG_TYPE_FILE|CMB_LOG_TYPE_CONSOLE, "C:\\rvc\\dbg"
+		*  那么将会日志记在 "C:\\rvc\\dbg\\PinPad\\{YYYYMMDD}.log" 内,并将支持控制台输出
+		*
+		*/
+		static void init(const log_init_config& config, vtm_string& ret_msg);
+
+		static void initp(const log_init_config_c* pconfig, char pret_msg[RVCOTHER_BUFF_SIZE]);
+
+		virtual void log(int log_level, const vtm_string& text) = 0;
+
+		static std::basic_ostringstream<char>& get_oss();
+
+		//static std::basic_ostringstream<wchar_t>& get_woss();
+
+#ifdef LIBLOG4RVCOTHER_EXPORTS
+	public:
+#else
+	private:
+#endif
+		log4rvcother() {}
+		virtual ~log4rvcother() {}
+	private:
+		log4rvcother(const log4rvcother& rhs);
+	};
+
+
+	//////////////////////////////////////////////////////////////////////////
+
+
+
+	class LOG4RVCOTHER_API log4vendor_tracer
+	{
+	public:
+
+		log4vendor_tracer(const char* message, const char* fileName, int nLine);
+
+		log4vendor_tracer(const char* message, const char* fileName, int nLine, int* pRet);
+
+		log4vendor_tracer(const char* message, const char* fileName, int nLine, PDWORD pRet);
+
+		~log4vendor_tracer();
+
+
+		static const char* _get_file_name(const char* file_path);
+
+	private:
+
+		log4vendor_tracer(log4vendor_tracer const&);
+		log4vendor_tracer& operator = (log4vendor_tracer const&);
+
+		const char* m_pszMes;
+		const char* m_pszFileN;
+		int m_nLine;
+
+		int* m_pnRet;
+		PDWORD m_pDwRet;
+		int* m_pfRet;
+		int m_retType;
+	};
+}
+
+#endif //_VTM_LOG4RVCOTHER_H_

+ 287 - 0
Other/liblog4rvcother/log4upload.cpp

@@ -0,0 +1,287 @@
+#include "log4upload.h"
+#include "log4rvcother.h"
+#include <algorithm>
+#include <string>
+#include <cctype>
+
+#if defined(_MSC_VER)
+#include <Windows.h>
+#define LOG_SDKNAME "RvcLogSdk.dll"
+
+static void log4vendor__format_fallback_error(log4vendor_lib_t* lib, int errorno) 
+{
+	static const CHAR fallback_error[] = "error: %1!d!";
+	DWORD_PTR args[1];
+	args[0] = (DWORD_PTR)errorno;
+
+	FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
+		FORMAT_MESSAGE_ARGUMENT_ARRAY |
+		FORMAT_MESSAGE_ALLOCATE_BUFFER,
+		fallback_error, 0, 0,
+		(LPSTR)&lib->errmsg,
+		0, (va_list*)args);
+}
+
+int log4vendor__dlerror(log4vendor_lib_t* lib, const char* filename, DWORD errorno)
+{
+		DWORD_PTR arg;
+	DWORD res;
+	char* msg;
+
+	if (lib->errmsg) {
+		LocalFree(lib->errmsg);
+		lib->errmsg = NULL;
+	}
+
+	if (errorno == 0)
+		return 0;
+
+	res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+		MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+		(LPSTR)&lib->errmsg, 0, NULL);
+
+	if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||
+		GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {
+		res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			FORMAT_MESSAGE_FROM_SYSTEM |
+			FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+			0, (LPSTR)&lib->errmsg, 0, NULL);
+	}
+
+	if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) {
+		msg = lib->errmsg;
+		lib->errmsg = NULL;
+		arg = (DWORD_PTR)filename;
+		res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			FORMAT_MESSAGE_ARGUMENT_ARRAY |
+			FORMAT_MESSAGE_FROM_STRING,
+			msg,
+			0, 0, (LPSTR)&lib->errmsg, 0, (va_list*)&arg);
+		LocalFree(msg);
+	}
+
+	if (!res)
+		log4vendor__format_fallback_error(lib, errorno);
+
+	return -1;
+}
+
+int log4vendor_dlopen(const char* filename, log4vendor_lib_t* lib)
+{
+	WCHAR filename_w[1024];
+
+	lib->handle = NULL;
+	lib->errmsg = NULL;
+
+	if (!MultiByteToWideChar(CP_UTF8,
+		0,
+		filename,
+		-1,
+		filename_w,
+		(sizeof(filename_w)/sizeof((filename_w)[0])))) {
+		return log4vendor__dlerror(lib, filename, GetLastError());
+	}
+
+	lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+	if (lib->handle == NULL) {
+		return log4vendor__dlerror(lib, filename, GetLastError());
+	}
+
+	return 0;
+}
+
+void log4vendor_dlclose(log4vendor_lib_t* lib)
+{
+	if (lib->errmsg) {
+		LocalFree((void*)lib->errmsg);
+		lib->errmsg = NULL;
+	}
+
+	if (lib->handle) {
+		/* Ignore errors. No good way to signal them without leaking memory. */
+		FreeLibrary(lib->handle);
+		lib->handle = NULL;
+	}
+}
+
+int log4vendor_dlsym(log4vendor_lib_t* lib, const char* name, void** ptr)
+{
+	*ptr = (void*)(uintptr_t)GetProcAddress(lib->handle, name);
+	return log4vendor__dlerror(lib, "", *ptr ? 0 : GetLastError());
+}
+
+#else
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+#include <locale.h>
+
+
+#define LOG_SDKNAME "libRVCLogSDK.so"
+
+int log4vendor__dlerror(log4vendor_lib_t* lib)
+{
+    const char* errmsg;
+    free(lib->errmsg);
+    errmsg = dlerror();
+    if (errmsg) {
+        lib->errmsg = strdup(errmsg);
+        return -1;
+    } else {
+        lib->errmsg = NULL;
+        return 0;
+    }
+}
+
+int log4vendor_dlopen(const char* filename, log4vendor_lib_t* lib)
+{
+    dlerror(); /* Reset error status. */
+    lib->errmsg = NULL;
+    lib->handle = dlopen(filename, RTLD_LAZY);
+    return lib->handle ? 0 : log4vendor__dlerror(lib);
+}
+
+void log4vendor_dlclose(log4vendor_lib_t* lib)
+{
+    if (lib->errmsg) {
+        free(lib->errmsg);
+        lib->errmsg = NULL;
+    }
+    if (lib->handle) {
+        /* Ignore errors. No good way to signal them without leaking memory. */
+        dlclose(lib->handle);
+        lib->handle = NULL;
+    }
+}
+
+int log4vendor_dlsym(log4vendor_lib_t* lib, const char* name, void** ptr)
+{
+    dlerror(); /* Reset error status. */
+    *ptr = dlsym(lib->handle, name);
+    return log4vendor__dlerror(lib);
+}
+
+
+#endif //_MSC_VER
+
+const char* log4vendor_dlerror(const log4vendor_lib_t* lib)
+{
+    return lib->errmsg ? lib->errmsg : "no error";
+}
+
+std::string to_lower(std::string str)
+{
+    std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) {
+        return static_cast<char>(std::tolower(c));
+                   });
+    return str;
+}
+
+bool upload_helper::initialize(const cmb::log_init_config& cfg)
+{
+    if (is_initialized()) return false;
+
+    bool res = (0 == load_logsdk());
+    if (res) {
+        log_producer_config* config = pinst_create_log_producer_config();
+        pinst_log_producer_config_set_packet_log_bytes(config, 4 * 1024 * 1024);
+        pinst_log_producer_config_set_packet_log_count(config, 24);//最大发送条数
+        pinst_log_producer_config_set_max_buffer_limit(config, 64 * 1024 * 1024);
+        //set send thread count
+        pinst_log_producer_config_set_send_thread_count(config, 2);
+        pinst_log_producer_config_set_persistent_max_log_count(config, 50 * 1000);
+        pinst_log_producer_config_set_skyeye_servname(config, (char*)"Terminal");
+        pinst_log_producer_config_set_skyeye_cmptId(config, (char*)"LR04");
+        pinst_log_producer_config_set_skyeye_cmptname(config, (char*)"FrameworkLib");
+        pinst_log_producer_config_set_skyeye_version(config, (char*)"1.0");
+        pinst_log_producer_config_set_persistent(config, 1);
+
+        //本地日志开关
+        //pinst_log_producer_config_switch_debug_mode(config, 1);
+
+        char value[128] = { '\0' };
+        strcpy(value, to_lower(cfg.dev_name).c_str());
+        pinst_log_producer_config_set_skyeye_entityname(config, value);
+
+        memset(value, '\0', sizeof(value));
+        strcpy(value, "0");
+        pinst_log_producer_config_set_skyeye_item(config, value);
+#if defined(_MSC_VER)
+		pinst_log_producer_config_set_persistent_file_path(config, "C:\\rvc\\terminaldbstorage");
+#else
+		pinst_log_producer_config_set_persistent_file_path(config, "/opt/rvc/terminaldbstorage");
+#endif
+
+        //新加统一日志配置
+        pinst_log_producer_config_set_united_appname(config, (char*)"LR04");
+        pinst_log_producer_config_set_united_version(config, (char*)"2.0");
+        pinst_log_producer_config_set_united_needArchived(config, 0);
+        pinst_log_producer_config_set_united_deployUnitId(config, (char*)"LR04.02@FrameworkLib_PRD_PRD");
+        pinst_log_producer_config_set_united_serviceUnitId(config, (char*)"LR04.02_FrameworkLib");
+
+        _client = pinst_create_log_producer_client(config, NULL, NULL);
+        res = (_client != nullptr);
+
+        if (!res) {
+            unload_logsdk();
+        }
+    }
+
+    _initialized = res;
+
+    return res;
+}
+
+int upload_helper::load_logsdk()
+{
+    LOG4VTM(DEBUG, "pre load sdk...");
+    int res = log4vendor_dlopen(LOG_SDKNAME, &m_lib);
+    if (res != 0) {
+        LOG4VTM(ERROR, ("log4vendor_dlopen failed with error") << LOG_SDKNAME << log4vendor_dlerror(&m_lib));
+        return res;
+    }
+    do {
+        res = -1;
+
+        if (log4vendor_dlsym(&m_lib, "create_log_producer_config", (void**)&pinst_create_log_producer_config) != 0 || pinst_create_log_producer_config == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_packet_log_bytes", (void**)&pinst_log_producer_config_set_packet_log_bytes) != 0 || pinst_log_producer_config_set_packet_log_bytes == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_packet_log_count", (void**)&pinst_log_producer_config_set_packet_log_count) != 0 || pinst_log_producer_config_set_packet_log_count == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_max_buffer_limit", (void**)&pinst_log_producer_config_set_max_buffer_limit) != 0 || pinst_log_producer_config_set_max_buffer_limit == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_send_thread_count", (void**)&pinst_log_producer_config_set_send_thread_count) != 0 || pinst_log_producer_config_set_send_thread_count == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_persistent_max_log_count", (void**)&pinst_log_producer_config_set_persistent_max_log_count) != 0 || pinst_log_producer_config_set_persistent_max_log_count == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_servname", (void**)&pinst_log_producer_config_set_skyeye_servname) != 0 || pinst_log_producer_config_set_skyeye_servname == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_cmptId", (void**)&pinst_log_producer_config_set_skyeye_cmptId) != 0 || pinst_log_producer_config_set_skyeye_cmptId == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_cmptname", (void**)&pinst_log_producer_config_set_skyeye_cmptname) != 0 || pinst_log_producer_config_set_skyeye_cmptname == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_version", (void**)&pinst_log_producer_config_set_skyeye_version) != 0 || pinst_log_producer_config_set_skyeye_version == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_persistent", (void**)&pinst_log_producer_config_set_persistent) != 0 || pinst_log_producer_config_set_persistent == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_entityname", (void**)&pinst_log_producer_config_set_skyeye_entityname) != 0 || pinst_log_producer_config_set_skyeye_entityname == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_skyeye_item", (void**)&pinst_log_producer_config_set_skyeye_item) != 0 || pinst_log_producer_config_set_skyeye_item == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_persistent_file_path", (void**)&pinst_log_producer_config_set_persistent_file_path) != 0 || pinst_log_producer_config_set_persistent_file_path == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_united_appname", (void**)&pinst_log_producer_config_set_united_appname) != 0 || pinst_log_producer_config_set_united_appname == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_united_version", (void**)&pinst_log_producer_config_set_united_version) != 0 || pinst_log_producer_config_set_united_version == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_united_needArchived", (void**)&pinst_log_producer_config_set_united_needArchived) != 0 || pinst_log_producer_config_set_united_needArchived == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_united_deployUnitId", (void**)&pinst_log_producer_config_set_united_deployUnitId) != 0 || pinst_log_producer_config_set_united_deployUnitId == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_set_united_serviceUnitId", (void**)&pinst_log_producer_config_set_united_serviceUnitId) != 0 || pinst_log_producer_config_set_united_serviceUnitId == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "create_log_producer_client", (void**)&pinst_create_log_producer_client) != 0 || pinst_create_log_producer_client == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_client_add_log", (void**)&pinst_log_producer_client_add_log) != 0 || pinst_log_producer_client_add_log == nullptr) break;
+        if (log4vendor_dlsym(&m_lib, "log_producer_config_switch_debug_mode", (void**)&pinst_log_producer_config_switch_debug_mode) != 0 || pinst_log_producer_config_switch_debug_mode == nullptr) break;
+
+        res = 0;
+    } while (false);
+
+    if (0 != res) {
+        LOG4VTM(ERROR, ("get funcs' address failed with error ") << log4vendor_dlerror(&m_lib));
+        log4vendor_dlclose(&m_lib);
+    } else {
+        LOG4VTM(DEBUG, "load_logsdk succ");
+    }
+    return res;
+}
+
+int upload_helper::unload_logsdk()
+{
+    log4vendor_dlclose(&m_lib);
+    return 0;
+}

+ 280 - 0
Other/liblog4rvcother/log4upload.h

@@ -0,0 +1,280 @@
+#ifndef RVC_VENDOR_LOG4UPLOAD_H_
+#define RVC_VENDOR_LOG4UPLOAD_H_
+
+#pragma once
+
+#include <stdint.h>
+#include "log4rvcother.h"
+
+
+#if defined(_MSC_VER)
+
+#include <Windows.h>
+
+typedef struct {
+	HMODULE handle;
+	char* errmsg;
+} log4vendor_lib_t;
+#else
+typedef struct
+{
+    void* handle;
+    char* errmsg;
+} log4vendor_lib_t;
+#endif
+
+struct log_producer_config
+{
+    //守护上传:代替其他实体上传日志
+    int enableGuarder;
+    //天眼要求字段
+    char* skyeyeServName;
+    char* skyeyeCmptId;
+    char* skyeyeCmptName;
+    char* skyeyeTerminalNo;
+    char* skyeyeVersion;
+    char* skyeyeSn;
+    char* skyeyeItem;
+    char* skyeyeEntityName;
+    //统一日志要求字段
+    char* unitedAppName;
+    char* unitedVersion;
+    int unitedNeedArchived;
+    char* unitedDeployUnitId;
+    char* unitedServiceUnitId;
+
+    char* endpoint;
+    char* skyeye_user_topic;
+    char* skyeye_sys_topic;
+    char* beidou_topic;
+    char* business_user_topic;
+    char* business_sys_topic;
+
+    int32_t sendThreadCount;
+
+    int32_t logCountPerPackage;
+    int32_t logBytesPerPackage;
+    int32_t maxBufferBytes;
+
+    int32_t connectTimeoutSec;
+    int32_t sendTimeoutSec;
+    int32_t destroyFlusherWaitTimeoutSec;
+    int32_t destroySenderWaitTimeoutSec;
+
+    int32_t compressType; // 0 no compress, 1 lz4
+    int32_t ntpTimeOffset;
+    int using_https; // 0 http, 1 https
+
+    // for persistent feature
+    int32_t usePersistent; // 0 no, 1 yes
+    char* persistentFilePath;
+    int32_t maxPersistentLogCount;
+    int32_t usePersistentEncrypt; // 0 no, 1 yes
+    char* PersistentEncryptPassword;
+    int32_t debugMode;
+} ;
+
+struct log_producer_client
+{
+    volatile int32_t valid_flag;
+    int32_t log_level;
+    void* private_data;
+} ;
+
+typedef enum
+{
+    LOG_TYPE_SYSTEM = 0/*系统日志*/, LOG_TYPE_USER = 1/*用户日志*/, LOG_TYPE_BUSINESS_SYSTEM = 2, LOG_TYPE_BUSINESS_USER = 3
+}LOG_TYPE_E;
+
+typedef enum
+{
+    LOG_LEVEL_DEBUG = 0, LOG_LEVEL_INFO = 1, LOG_LEVEL_WARN = 2, LOG_LEVEL_ERROR = 3, LOG_LEVEL_FATAL = 4
+}LOG_LEVEL_E;
+/**
+ * 天眼log item
+ */
+typedef struct _log_item
+{
+    /***************************必填begin**********************/
+    LOG_LEVEL_E Level;
+    LOG_TYPE_E Type;
+    //用户、系统日志均必填,交易处理结果代码,0表示处理成功,其他表示失败,可为系统本身的错误码,也可为后台系统返回的错误码
+    char* ResultCode;
+    //用户、系统日志均必填,业务跟踪ID, 32字节长度的字符串,唯一识别每笔请求
+    char* TraceID;
+    //用户、系统日志LOG_LEVEL_WARN以上必填
+    //交易处理结果信息,包括成功与失败信息,可为系统本身的成功/失败信息,也可为后台系统返回的成功/失败信息.
+    char* ResultMsg;
+
+    /***************************用户日志必填必填begin**********************/
+    //用户日志必填,日志码
+    //终端中标识各个交易如读卡、读取身份证等。如果终端由于客观原因无法识别交易场景,则可字段由上游传入。
+    char* LogCode;
+    //用户日志必填,请求路径/接口名称.
+    char* API;
+    //用户日志必填, 请求发送/接收时间
+    long BeginTime;
+    //用户日志必填, 响应接收 / 应答时间
+    long EndTime;
+	//自定义字段,消耗时间
+	long CostTime;
+    //用户日志必填,请求业务ID
+    char* BussID;
+    //用户日志LOG_LEVEL_WARN以上必填,直接向客户展示的报错信息.
+    char* TipMsg;
+
+    /***************************系统日志必填begin**********************/
+    //系统日志LOG_LEVEL_FATAL必填,异常来源类型
+    char* SourceType;
+} log_item;
+
+typedef int log_producer_result;
+typedef void(*pfn_on_log_producer_send_done)(log_producer_result, int, int, const char*, const char*, const unsigned char*, void*);
+
+#ifdef _WIN32
+
+typedef log_producer_config* (*pfn_create_log_producer_config)();
+typedef void(*pfn_log_producer_config_set_packet_log_bytes)(log_producer_config*, int32_t);
+typedef void(*pfn_log_producer_config_set_packet_log_count)(log_producer_config*, int32_t);
+
+typedef void(*pfn_log_producer_config_set_max_buffer_limit)(log_producer_config*, int64_t);
+typedef void(*pfn_log_producer_config_set_send_thread_count)(log_producer_config*, int32_t);
+typedef void(*pfn_log_producer_config_set_persistent_max_log_count)(log_producer_config*, int32_t);
+typedef void(*pfn_log_producer_config_set_skyeye_servname)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_skyeye_cmptId)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_skyeye_cmptname)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_skyeye_version)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_persistent)(log_producer_config*, int32_t);
+typedef void(*pfn_log_producer_config_set_skyeye_entityname)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_skyeye_item)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_persistent_file_path)(log_producer_config*, const char*);
+
+typedef void(*pfn_log_producer_config_set_united_appname)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_united_version)(log_producer_config*, char*);
+
+typedef void(*pfn_log_producer_config_set_united_needArchived)(log_producer_config*, int);
+typedef void(*pfn_log_producer_config_set_united_deployUnitId)(log_producer_config*, char*);
+typedef void(*pfn_log_producer_config_set_united_serviceUnitId)(log_producer_config*, char*);
+
+typedef log_producer_client*(*pfn_create_log_producer_client)(log_producer_config*, pfn_on_log_producer_send_done, void*);
+typedef log_producer_result(*pfn_log_producer_client_add_log)(log_producer_client*, log_item*, int);
+
+typedef void(*pfn_log_producer_config_switch_debug_mode)(log_producer_config*, int32_t);
+
+#else
+
+using pfn_create_log_producer_config = log_producer_config*(*)();
+using pfn_log_producer_config_set_packet_log_bytes = void(*)(log_producer_config*, int32_t);
+using pfn_log_producer_config_set_packet_log_count = void(*)(log_producer_config*, int32_t);
+
+using pfn_log_producer_config_set_max_buffer_limit = void(*)(log_producer_config*, int64_t);
+using pfn_log_producer_config_set_send_thread_count = void(*)(log_producer_config*, int32_t);
+using pfn_log_producer_config_set_persistent_max_log_count = void(*)(log_producer_config*, int32_t);
+using pfn_log_producer_config_set_skyeye_servname = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_skyeye_cmptId = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_skyeye_cmptname = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_skyeye_version = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_persistent = void(*)(log_producer_config*, int32_t);
+using pfn_log_producer_config_set_skyeye_entityname = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_skyeye_item = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_persistent_file_path = void(*)(log_producer_config*, const char*);
+
+using pfn_log_producer_config_set_united_appname = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_united_version = void(*)(log_producer_config*, char*);
+
+using pfn_log_producer_config_set_united_needArchived = void(*)(log_producer_config*, int);
+using pfn_log_producer_config_set_united_deployUnitId = void(*)(log_producer_config*, char*);
+using pfn_log_producer_config_set_united_serviceUnitId = void(*)(log_producer_config*, char*);
+
+using pfn_create_log_producer_client = log_producer_client*(*)(log_producer_config*, pfn_on_log_producer_send_done, void*);
+using pfn_log_producer_client_add_log = log_producer_result(*)(log_producer_client*, log_item*, int);
+
+using pfn_log_producer_config_switch_debug_mode = void(*)(log_producer_config*, int32_t);
+
+#endif //_WIN32
+
+
+
+class upload_helper
+{
+public:
+    upload_helper() :_initialized(false)
+        , pinst_on_log_producer_send_done(nullptr)
+        , pinst_create_log_producer_config(nullptr)
+        , pinst_log_producer_config_set_packet_log_bytes(nullptr)
+        , pinst_log_producer_config_set_packet_log_count(nullptr)
+        , pinst_log_producer_config_set_max_buffer_limit(nullptr)
+        , pinst_log_producer_config_set_send_thread_count(nullptr)
+        , pinst_log_producer_config_set_persistent_max_log_count(nullptr)
+        , pinst_log_producer_config_set_skyeye_servname(nullptr)
+        , pinst_log_producer_config_set_skyeye_cmptId(nullptr)
+        , pinst_log_producer_config_set_skyeye_cmptname(nullptr)
+        , pinst_log_producer_config_set_skyeye_version(nullptr)
+        , pinst_log_producer_config_set_persistent(nullptr)
+        , pinst_log_producer_config_set_skyeye_entityname(nullptr)
+        , pinst_log_producer_config_set_skyeye_item(nullptr)
+        , pinst_log_producer_config_set_persistent_file_path(nullptr)
+        , pinst_log_producer_config_set_united_appname(nullptr)
+        , pinst_log_producer_config_set_united_version(nullptr)
+        , pinst_log_producer_config_set_united_needArchived(nullptr)
+        , pinst_log_producer_config_set_united_deployUnitId(nullptr)
+        , pinst_log_producer_config_set_united_serviceUnitId(nullptr)
+        , pinst_create_log_producer_client(nullptr)
+        , pinst_log_producer_client_add_log(nullptr)
+        , pinst_log_producer_config_switch_debug_mode(nullptr)
+        , _client(nullptr)
+    {
+    
+    }
+    ~upload_helper() {
+        unload_logsdk();
+    }
+
+    bool initialize(const cmb::log_init_config& config);
+    bool is_initialized() const {
+        return _initialized;
+    }
+    void unitialize() { if(is_initialized()) unload_logsdk(); }
+private:
+    int load_logsdk();
+    int unload_logsdk();
+
+public:
+    pfn_log_producer_client_add_log pinst_log_producer_client_add_log;
+    log_producer_client* _client;
+
+private:
+    bool _initialized;
+    log4vendor_lib_t m_lib;
+
+    pfn_on_log_producer_send_done pinst_on_log_producer_send_done;
+
+    pfn_create_log_producer_config pinst_create_log_producer_config;
+    pfn_log_producer_config_set_packet_log_bytes pinst_log_producer_config_set_packet_log_bytes;
+
+    pfn_log_producer_config_set_packet_log_count pinst_log_producer_config_set_packet_log_count;
+    pfn_log_producer_config_set_max_buffer_limit pinst_log_producer_config_set_max_buffer_limit;
+    pfn_log_producer_config_set_send_thread_count pinst_log_producer_config_set_send_thread_count;
+    pfn_log_producer_config_set_persistent_max_log_count pinst_log_producer_config_set_persistent_max_log_count;
+    pfn_log_producer_config_set_skyeye_servname pinst_log_producer_config_set_skyeye_servname;
+    pfn_log_producer_config_set_skyeye_cmptId pinst_log_producer_config_set_skyeye_cmptId;
+    pfn_log_producer_config_set_skyeye_cmptname pinst_log_producer_config_set_skyeye_cmptname;
+    pfn_log_producer_config_set_skyeye_version pinst_log_producer_config_set_skyeye_version;
+    pfn_log_producer_config_set_persistent pinst_log_producer_config_set_persistent;
+    pfn_log_producer_config_set_skyeye_entityname pinst_log_producer_config_set_skyeye_entityname;
+    pfn_log_producer_config_set_skyeye_item pinst_log_producer_config_set_skyeye_item;
+    pfn_log_producer_config_set_persistent_file_path pinst_log_producer_config_set_persistent_file_path;
+    pfn_log_producer_config_set_united_appname pinst_log_producer_config_set_united_appname;
+    pfn_log_producer_config_set_united_version pinst_log_producer_config_set_united_version;
+
+    pfn_log_producer_config_set_united_needArchived pinst_log_producer_config_set_united_needArchived;
+    pfn_log_producer_config_set_united_deployUnitId pinst_log_producer_config_set_united_deployUnitId;
+    pfn_log_producer_config_set_united_serviceUnitId pinst_log_producer_config_set_united_serviceUnitId;
+
+    pfn_create_log_producer_client pinst_create_log_producer_client;
+    pfn_log_producer_config_switch_debug_mode pinst_log_producer_config_switch_debug_mode;
+
+};
+
+
+#endif //RVC_VENDOR_LOG4UPLOAD_H_

+ 51 - 0
Other/liblog4rvcother/mutex.cpp

@@ -0,0 +1,51 @@
+#include "mutex.h"
+
+namespace cmb {
+
+#if defined(_MSC_VER)
+
+    mutex::mutex()
+    {
+        ::InitializeCriticalSection(&csection_);
+    }
+
+    mutex::~mutex()
+    {
+        ::DeleteCriticalSection(&csection_);
+    }
+
+    void mutex::lock()
+    {
+        ::EnterCriticalSection(&csection_);
+    }
+
+    void mutex::unlock()
+    {
+        ::LeaveCriticalSection(&csection_);
+    }
+
+#elif defined(__GNUC__)
+
+    mutex::mutex()
+    {
+        pthread_mutex_init(&mutx_, NULL);
+    }
+
+    mutex::~mutex()
+    {
+        pthread_mutex_destroy(&mutx_);
+    }
+
+    void mutex::lock()
+    {
+        pthread_mutex_lock(&mutx_);
+    }
+
+    void mutex::unlock()
+    {
+        pthread_mutex_unlock(&mutx_);
+    }
+
+#endif
+
+}

+ 75 - 0
Other/liblog4rvcother/mutex.h

@@ -0,0 +1,75 @@
+#ifndef RVC_VENDOR_MUTEX_H_
+#define RVC_VENDOR_MUTEX_H_
+
+#pragma once
+
+#ifdef _WIN32
+#include <Windows.h>
+#else
+#include <pthread.h>
+#endif //_WIN32
+
+namespace cmb {
+
+	class noncopyable
+	{
+	protected:
+		noncopyable(){}
+		~noncopyable(){}
+	private:
+		noncopyable(const noncopyable&);
+		const noncopyable& operator=(const noncopyable&);
+
+	};
+
+	class mutex : private noncopyable
+	{
+		friend class condition;
+	public:
+		mutex();
+		~mutex();
+
+		void lock();
+		void unlock();
+
+	private:
+#if defined(_MSC_VER)
+		CRITICAL_SECTION csection_;
+#elif defined(__GNUC__)
+		pthread_mutex_t mutx_;
+#endif
+	};
+
+	class unique_lock : private noncopyable
+	{
+	public:
+		unique_lock(mutex& m) : mutex_(m)
+		{
+			mutex_.lock();
+			owns_ = true;
+		}
+		~unique_lock()
+		{
+			if (owns_)
+			{
+				mutex_.unlock();
+			}
+		}
+		void lock()
+		{
+			owns_ = true;
+			mutex_.lock();
+		}
+		void unlock()
+		{
+			owns_ = false;
+			mutex_.unlock();
+		}
+	private:
+		mutex& mutex_;
+		bool owns_;
+	};
+
+}
+
+#endif // RVC_VENDOR_MUTEX_H_

+ 8 - 0
Other/liblog4rvcother/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// liblog4rvcother.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 16 - 0
Other/liblog4rvcother/stdafx.h

@@ -0,0 +1,16 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
+// Windows 头文件:
+#include <windows.h>
+
+
+
+// TODO: 在此处引用程序需要的其他头文件

+ 8 - 0
Other/liblog4rvcother/targetver.h

@@ -0,0 +1,8 @@
+#pragma once
+
+// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
+
+// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
+// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
+
+#include <SDKDDKVer.h>