Log.h
cpp
#ifndef _LOG_H_
#define _LOG_H_
#include "log_global.h"
#include <QObject>
#include "singleton.h"
class LogPrivate;
class LOG_EXPORT Log :public Singleton<Log>
{
DEFINE_CONSTRUCT(Log)
public:
void initLogPath(const QString& logPath);
void warn(const char * msg,const char *filename = __FILE__,int line = __LINE__,const char *function = "warn");
void info(const char * msg,const char *filename = __FILE__,int line = __LINE__,const char *function = "info");
void debug(const char * msg,const char *filename = __FILE__,int line = __LINE__,const char *function = "debug");
void error(const char * msg,const char *filename = __FILE__,int line = __LINE__,const char *function = "error");
private:
LogPrivate* d_ptr;
};
#define LOG_DEBUG(msg) Log::instance()->debug(msg,__FILE__,__LINE__,__FUNCTION__);
#define LOG_INFO(msg) Log::instance()->info(msg,__FILE__,__LINE__,__FUNCTION__);
#define LOG_ERROR(msg) Log::instance()->error(msg,__FILE__,__LINE__,__FUNCTION__);
#define LOG_WARN(msg) Log::instance()->warn(msg,__FILE__,__LINE__,__FUNCTION__);
#endif // LOG_H
signgleton.h
cpp
#ifndef singleton_INC
#define singleton_INC
#include <QMutexLocker>
#include <QMutex>
#include <QAtomicPointer>
template <typename T>
class Singleton
{
public:
static T *instance()
{
if ( s_instance.testAndSetOrdered(0,0) ) { //若单例还未创建则进入分支,testAndSetOrdered可实现获取单例指针原子操作。
QMutexLocker locker(s_mutex);
if (s_instance.testAndSetOrdered(0,0)) {//再次检测,当有一个以上线程同时进入分支时可以确保唯一实例。
s_instance.store(new T);
}
}
return s_instance.load();
}
static void destroy()
{
T *tins = s_instance.fetchAndStoreOrdered(0);// Atomic fetch-and-store
if (tins) {
delete tins;
}
}
static bool isInstanceExist()
{
return !(s_instance.testAndSetOrdered(0,0));
}
protected:
Singleton(){}
~Singleton(){}
private:
Singleton(const Singleton &);
Singleton &operator =(const Singleton &);
private:
static QMutex *s_mutex;
static QAtomicPointer<T> s_instance;
};
template <typename T>
QMutex *Singleton<T>::s_mutex=new QMutex;
template <typename T>
QAtomicPointer<T> Singleton<T>::s_instance;
#define DEFINE_CONSTRUCT(CLASS_NAME) \
protected:\
explicit CLASS_NAME();\
~CLASS_NAME();\
friend class Singleton<CLASS_NAME>;
#endif /* ----- #ifndef singleton_INC ----- */
log.cpp
cpp
#include "log.h"
#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp\RollingFileAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/PatternLayout.hh"
#include "log4cpp/Priority.hh"
#include <QDebug>
#include <QGuiApplication>
#include <QFileInfo>
class LogPrivate{
public:
LogPrivate():m_Root(log4cpp::Category::getInstance("rootName")),m_logPath(""){
}
~LogPrivate(){
log4cpp::Category::shutdown();
}
void setLogPath(const std::string& filePath=""){
if(!m_logPath.empty())
return;
m_logPath=filePath;
init();
}
std::string logPath()const{
return m_logPath;
}
void init(){
if(m_logPath.empty()){
m_logPath= QGuiApplication::applicationDirPath().toStdString()+"/"+QGuiApplication::applicationName().toStdString()+".log";
}
m_pLayout=new log4cpp::PatternLayout();
m_pLayout->setConversionPattern("[%d{%Y-%m-%d %H:%M:%S.%l}] [tid:%t] %m%n");
m_pOsAppender=new log4cpp::OstreamAppender("IOStream",&std::cout);
m_pOsAppender->setLayout(m_pLayout);
// m_pLayout_File=new log4cpp::PatternLayout();
// m_pLayout_File->setConversionPattern("[%d{%Y-%m-%d %H:%M:%S.%l}] [tid:%t] %m%n");
// m_pFileAppender= new log4cpp::FileAppender("fileAppender",m_logPath);
// m_pFileAppender->setLayout(m_pLayout_File);
m_pLayout_RollFile=new log4cpp::PatternLayout();
m_pLayout_RollFile->setConversionPattern("[%d{%Y-%m-%d %H:%M:%S.%l}] [tid:%t] %m%n");
m_pFileRollAppender= new log4cpp::RollingFileAppender("fileAppender",m_logPath,1024*1024*10,1);
m_pFileRollAppender->setLayout(m_pLayout_RollFile);
m_Root.addAppender(m_pOsAppender);
// m_Root.addAppender(m_pFileAppender);
m_Root.addAppender(m_pFileRollAppender);
m_Root.setPriority(log4cpp::Priority::DEBUG);
}
void warn(const char * msg)
{
if(m_logPath.empty()){
init();
}
m_Root.warn(msg);
}
void info(const char * msg)
{
if(m_logPath.empty()){
init();
}
m_Root.info(msg);
}
void debug(const char* msg)
{
if(m_logPath.empty()){
init();
}
m_Root.debug(msg);
}
void error(const char * msg)
{
if(m_logPath.empty()){
init();
}
m_Root.error(msg);
}
private:
log4cpp::PatternLayout* m_pLayout = nullptr;
log4cpp::PatternLayout* m_pLayout_File = nullptr;
log4cpp::PatternLayout* m_pLayout_RollFile = nullptr;
log4cpp::OstreamAppender * m_pOsAppender = nullptr;
log4cpp::FileAppender* m_pFileAppender = nullptr;
log4cpp::RollingFileAppender * m_pFileRollAppender = nullptr;
log4cpp::Category& m_Root;
std::string m_logPath;
};
void Log::error(const char *msg, const char *filename, int line, const char *function)
{
QFileInfo fileInfo(filename);
char info[4096] = {0};
sprintf(info,"[file:%s] [line:%d] [func:%s] [msg-error]:%s",fileInfo.fileName().toStdString().c_str(),line,function,msg);
d_ptr->error(info);
}
void Log::debug(const char *msg, const char *filename, int line, const char *function)
{
QFileInfo fileInfo(filename);
char info[4096] = {0};
sprintf(info,"[file:%s] [line:%d] [func:%s] [msg-debug]:%s",fileInfo.fileName().toStdString().c_str(),line,function,msg);
d_ptr->debug(info);
}
void Log::info(const char *msg, const char *filename, int line, const char *function)
{
QFileInfo fileInfo(filename);
char info[4096] = {0};
sprintf(info,"[file:%s] [line:%d] [func:%s] [msg-info ]:%s",fileInfo.fileName().toStdString().c_str(),line,function,msg);
d_ptr->info(info);
}
void Log::warn(const char *msg, const char *filename, int line, const char *function)
{
QFileInfo fileInfo(filename);
char info[4096] = {0};
sprintf(info,"[file:%s] [line:%d] [func:%s] [msg-warn ]:%s",fileInfo.fileName().toStdString().c_str(),line,function,msg);
d_ptr->warn(info);
}
Log::~Log()
{
if(d_ptr!=nullptr){
delete d_ptr;
d_ptr=nullptr;
}
}
//Log &Log::instance()
//{
// static Log Instance;
// return Instance;
//}
void Log::initLogPath(const QString &logPath)
{
if(logPath.isEmpty())
return;
d_ptr->setLogPath(logPath.toStdString());
}
Log::Log():d_ptr(new LogPrivate())
{
}
日志格式为
支持回滚