简化了glog,只保留了写日志文件的功能,只是改写了linux版本,win版本未改写,可以用 LOG(INFO)<< 输出日志 也可用LOG_IF(INFO,condition)<<输出日志 也可直接调用日志类Logger::GetInstance().Error 等方式写日志 初始化时调用 InitLogging(argv[0],INFO,"./log/test"); 第一个参数是路径,第二个参数是最低日志级别,第三个参数表示日志文件的前缀和文件夹
FileHelper.h #ifndef FILEHELPER_H_ #define FILEHELPER_H_ #include <string> #include <vector> #include <fstream> #include <stdio.h> #ifdef _WIN32 #include <direct.h> #include <io.h> #else #include <stdarg.h> #include <sys/stat.h> #endif
namespace FrameWork { #ifdef _WIN32 #define ACCESS _access #define MKDIR(a) _mkdir((a)) #else #define ACCESS access #define MKDIR(a) mkdir((a),0755) #endif
class FileHelper { public: static bool save(const std::string filename,std::string& content) { FILE *file = fopen(filename.c_str(),"wb");
if (file == NULL) return false; fwrite(content.c_str(),sizeof(char),content.size(),file); fclose(file); return true; }
// used to open binary file static bool open(const std::string filename,std::string& content) { FILE *file = fopen(filename.c_str(),"rb");
if (file == NULL) return false;
fseek(file,SEEK_END); int len = ftell(file); rewind(file); content.clear(); char *buffer = new char[len]; fread(buffer,len,file); content.assign(buffer,len); delete []buffer;
//int nRead; //content.clear(); //char buffer[80]; //while(!feof(file)){ // nRead = fread(buffer,sizeof(buffer),file); // if(nRead > 0){ // content.append(buffer); // } //} fclose(file); return true; }
// used to open text file static bool open(const std::string file_name,std::vector<std::string>& lines) { std::ifstream file(file_name.c_str(),std::ios::in); if (!file) { return false; }
lines.clear(); char buffer[BUFFER_SIZE];
while (file.getline(buffer,BUFFER_SIZE,'n')) { lines.push_back(buffer); }
return true; } static bool CreateDir(const char *pszDir) { size_t i = 0; size_t iRet; size_t iLen = strlen(pszDir); char* buf=new char[iLen+1]; strncpy(buf,pszDir,iLen+1); for (i = 0;i < iLen;i ++) { if (pszDir[i] == '' || pszDir[i] == '/') { buf[i] = ' '; //如果不存在,创建 iRet = ACCESS(buf,0); if (iRet != 0) { iRet = MKDIR(buf); if (iRet != 0) { delete[] buf; return false; } } //支持linux,将所有换成/ buf[i] = '/'; } } delete[] buf; return true; }
private:
enum { BUFFER_SIZE = 3000 };
};
} /* namespace FrameWork */ #endif /* FILEHELPER_H_ */ [/code]
Logger.cpp
复制代码 代码如下: #include "Logger.h" #include<cstring> #include<time.h> #include<cstdarg> #include<cstdlib> #include<assert.h> #include "FileHelper.h" #include "Mutex.h" namespace FrameWork { Mutex LogMessage::mutex; static char _defaltFolder[]="/var/tmp/"; static char _appName[MaxFilePathLen]; static char _appFolder[MaxFilePathLen]; static char _destFolder[MaxFilePathLen]; static char _destPrefix[MaxFilePathLen]; static LogLevel _destLevel; static char _levelInfos[][16]={ "Debug","Info","Warn","Error","Fatal" }; const int BUFFER_SIZE = 8196; static char _gBuffer[BUFFER_SIZE]; void combine_folder(char** destpath,char* basefolder,char* relativefolder) { int lenb = strlen(basefolder); int lenr = strlen(relativefolder); char* pret = (char*)malloc((lenb+lenr+1)*sizeof(char)); int pos=lenb-1; memset(pret,lenb+lenr+1); while(pos>0 && ( basefolder[pos]!='/')) pos--; strncpy(*destpath,basefolder,pos+1); if(relativefolder[0] == '' || relativefolder[0] == '/'){ strncpy(*destpath+pos+1,relativefolder+1,lenr-1); }else{ strncpy(*destpath+pos+1,relativefolder,lenr); } }
static void InitPaths(const char* filename,const char* destFolder) { memset(_appName,MaxFilePathLen); memset(_appFolder,MaxFilePathLen); memset(_destFolder,MaxFilePathLen); memset(_destPrefix,MaxFilePathLen);
strcpy(_appName,filename); int len = strlen(filename),lend; int pos = len-1,posd,start; while(pos >0 && filename[pos] != PathSplitChar) pos--; strncpy(_appFolder,filename,pos+1); lend = strlen(destFolder); posd = lend-1; if(destFolder[lend-1] != PathSplitChar) { //has prefix while(posd >0 && destFolder[posd] != PathSplitChar) posd--; } if(destFolder[0] == '.' && destFolder[1] == PathSplitChar){ strncpy(_destFolder,pos+1); start = 2; } else{ pos = 8; strcpy(_destFolder,_defaltFolder); if(destFolder[0] != PathSplitChar){ start = 0; }else{ start = 1; } } strncpy(_destFolder+pos+1,destFolder+start,posd-start+1); strncpy(_destPrefix,pos+1); strncpy(_destPrefix+pos+1,lend-start); }
void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder) { InitPaths(filename,destFolder); _destLevel = minlevel; }
static string GetLocalDate(void) { time_t t = time(0); tm *ld; char tmp[64] = ""; ld=localtime(&t); strftime(tmp,sizeof(tmp),"%Y-%m-%d",ld); return string(tmp); } static string GetCurTime(void) { time_t t = time(0); tm *ld; char tmp[64] = ""; ld=localtime(&t); strftime(tmp,"%Y-%m-%d %H:%M:%S",ld); return string(tmp); }
Logger::Logger(LogLevel level,char * folder,char * prefix) :level(level) { std::string path; path.append(prefix); path.append(GetLocalDate()); path.append(".log"); FileHelper::CreateDir(folder); logPrefix.append(prefix); logPath = path; logFile.open(path.c_str(),ios::app|ios::out); logFile<<"Log file created at:"<<GetCurTime()<<endl; }
Logger::~Logger() { logFile.close(); }
#define IMPLEMENT_LOG_FUNC1(cname,fname,lv) void cname::fname(string msg) { if(level <= lv){ WriterMutexLock lock(&mutex); logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<msg.c_str()<<endl; logFile.flush(); } }
#define PRINT_ARGS_TO_BUFFER(fmt,buf) { memset(buf,sizeof(buf)); va_list argp; va_start(argp,fmt); vsprintf(buf,fmt,argp); va_end(argp); }
#define IMPLEMENT_LOG_FUNC2(cname,lv) void cname::fname(const char* format,...) { if(level <= lv){ WriterMutexLock lock(&mutex); PRINT_ARGS_TO_BUFFER(format,_gBuffer) logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<_gBuffer<<endl; logFile.flush(); } }
#define IMPLEMENT_LOG_FUNC(cname,lv) IMPLEMENT_LOG_FUNC1(cname,lv) IMPLEMENT_LOG_FUNC2(cname,lv)
IMPLEMENT_LOG_FUNC(Logger,Debug,DEBUG) IMPLEMENT_LOG_FUNC(Logger,Info,INFO) IMPLEMENT_LOG_FUNC(Logger,Warn,WARN) IMPLEMENT_LOG_FUNC(Logger,Error,ERROR) IMPLEMENT_LOG_FUNC(Logger,Fatal,FATAL)
Logger& Logger::GetInstance() { static Logger _logger(_destLevel,_destFolder,_destPrefix); return _logger; }
void Logger::Log(LogLevel lv,string msg) { if(level <= lv){ WriterMutexLock lock(&mutex); logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<msg.c_str()<<endl; logFile.flush(); } }
void Logger::Log(LogLevel lv,const char* format,...) { if(level <= lv){ WriterMutexLock lock(&mutex); PRINT_ARGS_TO_BUFFER(format,_gBuffer) logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<_gBuffer<<endl; logFile.flush(); } }
void Logger::Log(const char* file,int line,LogLevel lv,string msg) { if(level <= lv){ WriterMutexLock lock(&mutex); logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<msg.c_str(); logFile.flush(); } }
Logger* Logger::GetInstancePtr() { return &GetInstance(); }
void Logger::Log(const char* file,_gBuffer) logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<_gBuffer; logFile.flush(); } }
LogMessage::LogMessage(const char* file,LogLevel lv) { logger = Logger::GetInstancePtr(); mutex.Lock(); logger->Log(file,line,lv,""); }
LogMessage::~LogMessage() { logger->stream()<<endl; logger->stream().flush(); mutex.Unlock(); }
} /* namespace FrameWork */
Logger.h
复制代码 代码如下: #ifndef LOGGER_H_ #define LOGGER_H_
#include "ILogger.h" #include "Mutex.h" #include<fstream> #include<string> const int MaxFilePathLen = 1024; const char PathSplitChar = '/'; namespace FrameWork { enum LogLevel{ /// <summary> /// 调试 /// </summary> DEBUG = -1, /// <summary> /// 普通日志 /// </summary> INFO = 0, /// <summary> /// 警告 /// </summary> WARN, /// <summary> /// 错误 /// </summary> ERROR, /// <summary> /// 崩溃 /// </summary> FATAL, /// <summary> /// 超出错误级别 /// </summary> OFF };
class ILogger { public: // virtual ~ILogger(){} #define ABSTRACT_LOG_FUNC(name) virtual void name(string msg)=0; virtual void name(const char* fmt,...)=0;
ABSTRACT_LOG_FUNC(Debug) ABSTRACT_LOG_FUNC(Info) ABSTRACT_LOG_FUNC(Warn) ABSTRACT_LOG_FUNC(Error) ABSTRACT_LOG_FUNC(Fatal)
#undef ABSTRACT_LOG_FUNC #define ABSTRACT_LOG_FUNC_X(name) virtual void name(LogLevel lv,string msg)=0; virtual void name(LogLevel lv,const char* fmt,...)=0; virtual void name(const char* file,string msg)=0; virtual void name(const char* file,...)=0; ABSTRACT_LOG_FUNC_X(Log)
#undef LOG_FUNC_X };
class Logger: public ILogger { std::string logPath; std::string logPrefix; std::fstream logFile; LogLevel level; Mutex mutex;
Logger(LogLevel level,char * prefix);
public: static Logger& GetInstance(); static Logger* GetInstancePtr(); virtual ~Logger(); inline fstream & stream(){return logFile;}
#define DECLARE_LOG_FUNC(name) virtual void name(string msg); virtual void name(const char* fmt,...);
#define DECLARE_LOG_FUNC_X(name) virtual void name(LogLevel lv,string msg); virtual void name(LogLevel lv,...); virtual void name(const char* file,string msg); virtual void name(const char* file,...);
DECLARE_LOG_FUNC(Debug) DECLARE_LOG_FUNC(Info) DECLARE_LOG_FUNC(Warn) DECLARE_LOG_FUNC(Error) DECLARE_LOG_FUNC(Fatal)
DECLARE_LOG_FUNC_X(Log)
#undef DECLARE_LOG_FUNC_X #undef DECLARE_LOG_FUNC
};
class LogMessage { Logger* logger; static Mutex mutex; public: LogMessage(const char* file,LogLevel lv); ostream& stream(){return logger->stream();} virtual ~LogMessage(); };
void InitLogging(const char* filename,const char* destFolder); void CloseLogging();
#define LOG(level) LogMessage(__FILE__,__LINE__,level).stream() #define LOG_IF(severity,condition) !(condition) ? (void) 0 : LOG(severity) #define LOG_ASSERT(condition) LOG_IF(FATAL,!(condition)) << "Assert failed: " #condition #define CHECK(condition) LOG_IF(FATAL,!(condition)) << "Check failed: " #condition " "
} /* namespace FrameWork */ #endif /* LOGGER_H_ */
main.cpp
复制代码 代码如下: #include <iostream> #include "Logger.h" using namespace std; using namespace FrameWork; int main(int argc,char* argv[]) { InitLogging(argv[0],"./log/test"); cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! LOG(INFO)<<"info test"; LOG(WARN)<<"WARN TEST %d"<<20; LOG(ERROR)<<"Error test %d %s"<<20<<"nihao";
Logger::GetInstance().Error("error test common"); Logger::GetInstance().Fatal("fatal test common %d ",100); Logger::GetInstance().Info("info test normal %d %s ",50,"zhongguoren"); return 0; }
Mutex.h
复制代码 代码如下: #ifndef MUTEX_H_ #define MUTEX_H_ #include <pthread.h> #include <stdlib.h> namespace FrameWork { typedef pthread_mutex_t MutexType;
class Mutex { public: // Create a Mutex that is not held by anybody. This constructor is // typically used for Mutexes allocated on the heap or the stack. // See below for a recommendation for constructing global Mutex // objects. inline Mutex();
// Destructor inline ~Mutex();
inline void Lock(); // Block if needed until free then acquire exclusively inline void Unlock(); // Release a lock acquired via Lock() inline bool TryLock(); // If free,Lock() and return true,else return false // Note that on systems that don't support read-write locks,these may // be implemented as synonyms to Lock() and Unlock(). So you can use // these for efficiency,but don't use them anyplace where being able // to do shared reads is necessary to avoid deadlock. inline void ReaderLock(); // Block until free or shared then acquire a share inline void ReaderUnlock(); // Release a read share of this Mutex inline void WriterLock() { Lock(); } // Acquire an exclusive lock inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
// TODO(hamaji): Do nothing,implement correctly. inline void AssertHeld() {} private: MutexType mutex_; // We want to make sure that the compiler sets is_safe_ to true only // when we tell it to,and never makes assumptions is_safe_ is // always true. volatile is the most reliable way to do that. volatile bool is_safe_;
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock. Mutex(Mutex* /*ignored*/) {} // Disallow "evil" constructors Mutex(const Mutex&); void operator=(const Mutex&); }; #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ if (is_safe_ && fncall(&mutex_) != 0) abort(); } while (0)
Mutex::Mutex() { SetIsSafe(); if (is_safe_ && pthread_mutex_init(&mutex_,NULL) != 0) abort(); } Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } bool Mutex::TryLock() { return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true; } void Mutex::ReaderLock() { Lock(); } void Mutex::ReaderUnlock() { Unlock(); } class MutexLock { public: explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } ~MutexLock() { mu_->Unlock(); } private: Mutex * const mu_; // Disallow "evil" constructors MutexLock(const MutexLock&); void operator=(const MutexLock&); };
// ReaderMutexLock and WriterMutexLock do the same,for rwlocks class ReaderMutexLock { public: explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } ~ReaderMutexLock() { mu_->ReaderUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors ReaderMutexLock(const ReaderMutexLock&); void operator=(const ReaderMutexLock&); };
class WriterMutexLock { public: explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } ~WriterMutexLock() { mu_->WriterUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors WriterMutexLock(const WriterMutexLock&); void operator=(const WriterMutexLock&); }; } /* namespace FrameWork */ #endif /* MUTEX_H_ */
您可能感兴趣的文章:- Linux C++ 使用condition实现阻塞队列的方法
- linux C++ 获取文件绝对路径的实例代码
- Linux中使用VS Code编译调试C++项目详解
- Linux 平台上比较好的C/C++ IDE 清单
- 总结UNIX/LINUX下C++程序计时的方法
- Linux下用C++实现俄罗斯方块
- C++实现Linux下弹出U盘的方法
- 在Linux下编译C或C++程序的教程
- Linux上搭建C/C++IDE开发环境
- 详解 linux c++的编译器g++的基本使用
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|