GrabBag/VrUtils/Src/VrLog.cpp

317 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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>
#include <shlobj.h>
#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宏
///******************************************************************************************************************/
#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;
#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(&timestamp); \
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
#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)
#endif // __ANROID__
///******************************************************************************************************************/
// 动态获取日志路径(包含应用名称)
static std::string GetLogPath()
{
std::string appName = "YJApp"; // 默认应用名称
// 尝试从进程路径获取应用名称
#ifdef _WIN32
// 获取用户文档目录
// 如果无法获取用户目录,则使用原来的方式
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);
}
}
}
char userPath[MAX_PATH];
if (SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, userPath) == S_OK) {
std::string userDir(userPath);
return userDir + "\\" + appName + "\\Log";
}
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;
}
/// 开启/关闭时间戳
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;
}
/// 输出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)
{
}