2025-07-23 01:35:14 +08:00
|
|
|
|
#include "VrLog.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <log4cpp/Category.hh>
|
|
|
|
|
|
#include <log4cpp/Appender.hh>
|
|
|
|
|
|
#include <log4cpp/FileAppender.hh>
|
|
|
|
|
|
#include <log4cpp/Priority.hh>
|
|
|
|
|
|
#include <log4cpp/PatternLayout.hh>
|
|
|
|
|
|
#include <log4cpp/RollingFileAppender.hh>
|
|
|
|
|
|
#include <log4cpp/PropertyConfigurator.hh>
|
|
|
|
|
|
|
|
|
|
|
|
#include "VrFileUtils.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
#include <direct.h>
|
2025-08-31 21:08:28 +08:00
|
|
|
|
#include <shlobj.h>
|
2025-07-23 01:35:14 +08:00
|
|
|
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
|
|
|
|
|
#include <WinSock2.h>
|
|
|
|
|
|
#pragma comment(lib,"Ws2_32.lib")
|
|
|
|
|
|
#else
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////定义Log宏
|
|
|
|
|
|
///******************************************************************************************************************/
|
|
|
|
|
|
|
2025-09-29 00:56:53 +08:00
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
#define PATH_SEP "\\"
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define PATH_SEP "/"
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define LOG_CONFIG_FILE "config.ini"
|
|
|
|
|
|
#define LOG_PRINT_FILE "AppLog.log"
|
|
|
|
|
|
|
|
|
|
|
|
static log4cpp::PatternLayout* m_pLayout = nullptr;
|
|
|
|
|
|
static log4cpp::RollingFileAppender* m_prollfileAppender = nullptr;
|
|
|
|
|
|
static bool g_isLogInitialized = false;
|
|
|
|
|
|
static bool g_isTimeEnabled = true;
|
|
|
|
|
|
|
2025-07-23 01:35:14 +08:00
|
|
|
|
|
|
|
|
|
|
#ifdef STM32_UCOSIII
|
|
|
|
|
|
#define LOG_TIME do{ \
|
|
|
|
|
|
OS_ERR err;\
|
|
|
|
|
|
OS_TICK time = OSTimeGet(&err); \
|
|
|
|
|
|
printf("[%10u]",time); \
|
|
|
|
|
|
}while(0)
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define LOG_TIME do { \
|
|
|
|
|
|
std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); \
|
|
|
|
|
|
std::time_t timestamp = std::chrono::system_clock::to_time_t(now); \
|
|
|
|
|
|
std::tm local_time = *std::localtime(×tamp); \
|
|
|
|
|
|
long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); \
|
|
|
|
|
|
printf("%d-%02d-%02d %02d:%02d:%02d.%03lld", local_time.tm_year + 1900 , local_time.tm_mon + 1, local_time.tm_mday, local_time.tm_hour, local_time.tm_min, local_time.tm_sec, milliseconds % 1000); \
|
|
|
|
|
|
} while(0)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
|
#include <android/log.h>
|
|
|
|
|
|
#define MY_LOG_VERBOSE(fmt, ...) __android_log_print(ANDROID_LOG_VERBOSE, "APPV", ##__VA_ARGS__)
|
|
|
|
|
|
#define MY_LOG_DEBUG(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "APPD", ##__VA_ARGS__)
|
|
|
|
|
|
#define MY_LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "APPI", ##__VA_ARGS__)
|
|
|
|
|
|
#define MY_LOG_WARNING(fmt, ...) __android_log_print(ANDROID_LOG_WARN, "APPW", ##__VA_ARGS__)
|
|
|
|
|
|
#define MY_LOG_ERRO(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "APPE", ##__VA_ARGS__)
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
2025-11-09 21:01:51 +08:00
|
|
|
|
#define MY_LOG_VERBOSE(filePath, nLine, fmt, ...) do { if(g_isTimeEnabled) LOG_TIME; printf(" V[%25s:%4u] " fmt"", filePath, nLine ,##__VA_ARGS__); fflush(stdout); } while(0)
|
|
|
|
|
|
#define MY_LOG_DEBUG(filePath, nLine, fmt, ...) do { if(g_isTimeEnabled) LOG_TIME; printf(" D[%25s:%4u] " fmt"", filePath, nLine ,##__VA_ARGS__); fflush(stdout); } while(0)
|
|
|
|
|
|
#define MY_LOG_INFO(filePath, nLine, fmt, ...) do { if(g_isTimeEnabled) LOG_TIME; printf(" I[%25s:%4u] " fmt"", filePath, nLine ,##__VA_ARGS__); fflush(stdout); } while(0)
|
|
|
|
|
|
#define MY_LOG_WARNING(filePath, nLine, fmt, ...) do { if(g_isTimeEnabled) LOG_TIME; printf(" W[%25s:%4u] " fmt"", filePath, nLine ,##__VA_ARGS__); fflush(stdout); } while(0)
|
|
|
|
|
|
#define MY_LOG_ERRO(filePath, nLine, fmt, ...) do { if(g_isTimeEnabled) LOG_TIME; printf(" E[%25s:%4u] " fmt"", filePath, nLine ,##__VA_ARGS__); fflush(stdout); } while(0)
|
2025-07-23 01:35:14 +08:00
|
|
|
|
#endif // __ANROID__
|
|
|
|
|
|
///******************************************************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
// 动态获取日志路径(包含应用名称)
|
|
|
|
|
|
static std::string GetLogPath()
|
|
|
|
|
|
{
|
2025-08-31 21:08:28 +08:00
|
|
|
|
std::string appName = "YJApp"; // 默认应用名称
|
|
|
|
|
|
|
2025-07-23 01:35:14 +08:00
|
|
|
|
// 尝试从进程路径获取应用名称
|
|
|
|
|
|
#ifdef _WIN32
|
2025-08-31 21:08:28 +08:00
|
|
|
|
// 获取用户文档目录
|
|
|
|
|
|
|
|
|
|
|
|
// 如果无法获取用户目录,则使用原来的方式
|
2025-07-23 01:35:14 +08:00
|
|
|
|
char exePath[MAX_PATH];
|
|
|
|
|
|
if (GetModuleFileNameA(NULL, exePath, MAX_PATH) != 0) {
|
|
|
|
|
|
std::string fullPath(exePath);
|
|
|
|
|
|
size_t pos = fullPath.find_last_of("\\");
|
|
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
|
|
std::string fileName = fullPath.substr(pos + 1);
|
|
|
|
|
|
size_t dotPos = fileName.find_last_of(".");
|
|
|
|
|
|
if (dotPos != std::string::npos) {
|
|
|
|
|
|
appName = fileName.substr(0, dotPos);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-31 21:08:28 +08:00
|
|
|
|
|
|
|
|
|
|
char userPath[MAX_PATH];
|
|
|
|
|
|
if (SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, userPath) == S_OK) {
|
|
|
|
|
|
std::string userDir(userPath);
|
|
|
|
|
|
return userDir + "\\" + appName + "\\Log";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-23 01:35:14 +08:00
|
|
|
|
return ".\\" + appName + "\\Log";
|
|
|
|
|
|
#else
|
|
|
|
|
|
// Linux/Android平台
|
|
|
|
|
|
char exePath[1024];
|
|
|
|
|
|
ssize_t len = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
|
|
|
|
|
|
if (len != -1) {
|
|
|
|
|
|
exePath[len] = '\0';
|
|
|
|
|
|
std::string fullPath(exePath);
|
|
|
|
|
|
size_t pos = fullPath.find_last_of("/");
|
|
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
|
|
appName = fullPath.substr(pos + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
|
return "/sdcard/" + appName + "/Log";
|
|
|
|
|
|
#else
|
|
|
|
|
|
return appName + "/Log";
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 自动初始化和清理类,确保程序启动时初始化日志,退出时清理日志资源
|
|
|
|
|
|
class VrLogAutoCleaner {
|
|
|
|
|
|
public:
|
|
|
|
|
|
VrLogAutoCleaner() {
|
|
|
|
|
|
VrLogUtils::InitLog();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~VrLogAutoCleaner() {
|
|
|
|
|
|
VrLogUtils::UninitLog();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 静态实例,程序启动时自动初始化日志,程序退出时自动清理日志
|
|
|
|
|
|
static VrLogAutoCleaner g_logAutoCleaner;
|
|
|
|
|
|
|
|
|
|
|
|
/// 初始化log
|
|
|
|
|
|
void VrLogUtils::InitLog()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 防止重复初始化
|
|
|
|
|
|
if (g_isLogInitialized) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if file exist then load file config
|
|
|
|
|
|
std::string logPath = GetLogPath();
|
|
|
|
|
|
std::string logConfig = logPath + PATH_SEP + LOG_CONFIG_FILE;
|
|
|
|
|
|
if (CVrFileUtils::IsFileExist(logConfig.c_str()))
|
|
|
|
|
|
{
|
|
|
|
|
|
// load profile
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
log4cpp::PropertyConfigurator::configure(logConfig);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (log4cpp::ConfigureFailure& f)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cout << "Load Log Profile Error" << f.what() << std::endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!CVrFileUtils::IsDirExist(logPath.c_str()))
|
|
|
|
|
|
{
|
|
|
|
|
|
CVrFileUtils::CreatNewDir(logPath.c_str());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// create file appender
|
|
|
|
|
|
if (nullptr == m_pLayout)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pLayout = new log4cpp::PatternLayout;
|
|
|
|
|
|
// 设置布局格式,可以控制是否自动换行
|
|
|
|
|
|
// %d{%Y-%m-%d %H:%M:%S.%l} [%p] %c - %m%n
|
|
|
|
|
|
// 其中 %n 表示换行符,如果想要控制换行可以去掉或修改这个
|
|
|
|
|
|
m_pLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l} [%p] %m");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nullptr == m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_prollfileAppender = new log4cpp::RollingFileAppender("AppLogAppender", logPath + PATH_SEP + LOG_PRINT_FILE,
|
|
|
|
|
|
1024 * 1024, // 单个文件大小1M
|
|
|
|
|
|
10); // 10个文件
|
|
|
|
|
|
|
|
|
|
|
|
m_prollfileAppender->setLayout(m_pLayout);
|
|
|
|
|
|
|
|
|
|
|
|
// add appender to category
|
|
|
|
|
|
log4cpp::Category& root = log4cpp::Category::getRoot();
|
|
|
|
|
|
root.addAppender(m_prollfileAppender);
|
|
|
|
|
|
|
|
|
|
|
|
// set priority
|
|
|
|
|
|
root.setPriority(log4cpp::Priority::DEBUG);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g_isLogInitialized = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 关闭log
|
|
|
|
|
|
void VrLogUtils::UninitLog()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!g_isLogInitialized) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pLayout)
|
|
|
|
|
|
{
|
|
|
|
|
|
delete m_pLayout;
|
|
|
|
|
|
m_pLayout = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
delete m_prollfileAppender;
|
|
|
|
|
|
m_prollfileAppender = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
log4cpp::Category::shutdown();//关闭Category;
|
|
|
|
|
|
|
|
|
|
|
|
g_isLogInitialized = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 00:56:53 +08:00
|
|
|
|
|
|
|
|
|
|
/// 开启/关闭时间戳
|
|
|
|
|
|
void VrLogUtils::EnableTime(bool bEnable)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nullptr != m_pLayout)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pLayout->setConversionPattern(bEnable ? "%d{%Y-%m-%d %H:%M:%S.%l} [%p] %m" : "%p %m");
|
|
|
|
|
|
}
|
|
|
|
|
|
g_isTimeEnabled = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-23 01:35:14 +08:00
|
|
|
|
/// 输出log
|
|
|
|
|
|
void VrLogUtils::EchoLog(VrLogLevel eLogLevel, const char* sFilePath, const int nLine, const char* sLogGroup, const char* sFormat, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 由于VrLogAutoCleaner会在程序启动时自动初始化,这里只做保险检查
|
|
|
|
|
|
if (!g_isLogInitialized) {
|
|
|
|
|
|
InitLog();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// load log info
|
|
|
|
|
|
va_list args;
|
|
|
|
|
|
va_start(args, sFormat);
|
|
|
|
|
|
char szLogInfo[1024] = { 0 };
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
vsprintf_s(szLogInfo, sFormat, args);
|
|
|
|
|
|
#else
|
|
|
|
|
|
vsprintf(szLogInfo, sFormat, args);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
log4cpp::Category& root = log4cpp::Category::getRoot();
|
|
|
|
|
|
|
|
|
|
|
|
switch (eLogLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
case KELOGLEVEL_None:
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KELOGLEVEL_Verbose:
|
|
|
|
|
|
MY_LOG_VERBOSE(sFilePath, nLine, "%s", szLogInfo);
|
|
|
|
|
|
if (nullptr != m_pLayout && nullptr != m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG4CPP_DEBUG(root, szLogInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KELOGLEVEL_Debug:
|
|
|
|
|
|
MY_LOG_DEBUG(sFilePath, nLine, "%s", szLogInfo);
|
|
|
|
|
|
if (nullptr != m_pLayout && nullptr != m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG4CPP_DEBUG(root, szLogInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KELOGLEVEL_Info:
|
|
|
|
|
|
MY_LOG_INFO(sFilePath, nLine, "%s", szLogInfo);
|
|
|
|
|
|
if (nullptr != m_pLayout && nullptr != m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG4CPP_INFO(root, szLogInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KELOGLEVEL_Warning:
|
|
|
|
|
|
MY_LOG_WARNING(sFilePath, nLine, "%s", szLogInfo);
|
|
|
|
|
|
if (nullptr != m_pLayout && nullptr != m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG4CPP_WARN(root, szLogInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case KELOGLEVEL_Error:
|
|
|
|
|
|
MY_LOG_ERRO(sFilePath, nLine, "%s", szLogInfo);
|
|
|
|
|
|
if (nullptr != m_pLayout && nullptr != m_prollfileAppender)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG4CPP_ERROR(root, szLogInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 修改log level default info
|
|
|
|
|
|
void VrLogUtils::AlterLogLevel(VrLogLevel eLogLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 修改log输出形式 默认都输出
|
|
|
|
|
|
void VrLogUtils::AlterLogType(VrLogType eLogType)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|