linux c 日志写入文件,linux系统中c++写日志文件功能分享

简化了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

#include

#include

#include

#ifdef _WIN32

#include

#include

#else

#include

#include

#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, 0, SEEK_END);

int len = ftell(file);

rewind(file);

content.clear();

char *buffer = new char[len];

fread(buffer, sizeof(char), len, file);

content.assign(buffer, len);

delete []buffer;

//int nRead;

//content.clear();

//char buffer[80];

//while(!feof(file)){

// nRead = fread(buffer,sizeof(char),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<: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] = '\0';

//如果不存在,创建

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

#include

#include

#include

#include

#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,0,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,0,MaxFilePathLen);

memset(_appFolder,0,MaxFilePathLen);

memset(_destFolder,0,MaxFilePathLen);

memset(_destPrefix,0,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,filename,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,filename,pos+1);

strncpy(_destPrefix+pos+1,destFolder+start,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,sizeof(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<

}

Logger::~Logger() {

logFile.close();

}

#define IMPLEMENT_LOG_FUNC1(cname,fname,lv) \

void cname::fname(string msg) {\

if(level <= lv){\

WriterMutexLock lock(&mutex);\

logFile<

logFile.flush();\

}\

}

#define PRINT_ARGS_TO_BUFFER(fmt,buf) \

{\

memset(buf,0,sizeof(buf));\

va_list argp;\

va_start(argp,fmt);\

vsprintf(buf,fmt,argp);\

va_end(argp);\

}

#define IMPLEMENT_LOG_FUNC2(cname,fname,lv) \

void cname::fname(const char* format,...) {\

if(level <= lv){\

WriterMutexLock lock(&mutex);\

PRINT_ARGS_TO_BUFFER(format,_gBuffer)\

logFile<

logFile.flush();\

}\

}

#define IMPLEMENT_LOG_FUNC(cname,fname,lv) \

IMPLEMENT_LOG_FUNC1(cname,fname,lv)\

IMPLEMENT_LOG_FUNC2(cname,fname,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<

logFile.flush();

}

}

void Logger::Log(LogLevel lv, const char* format,...) {

if(level <= lv){

WriterMutexLock lock(&mutex);

PRINT_ARGS_TO_BUFFER(format,_gBuffer)

logFile<

logFile.flush();

}

}

void Logger::Log(const char* file, int line, LogLevel lv, string msg) {

if(level <= lv){

WriterMutexLock lock(&mutex);

logFile<

logFile.flush();

}

}

Logger* Logger::GetInstancePtr() {

return &GetInstance();

}

void Logger::Log(const char* file, int line, LogLevel lv, const char* format,...) {

if(level <= lv){

WriterMutexLock lock(&mutex);

PRINT_ARGS_TO_BUFFER(format,_gBuffer)

logFile<

logFile.flush();

}

}

LogMessage::LogMessage(const char* file, int line, LogLevel lv) {

logger = Logger::GetInstancePtr();

mutex.Lock();

logger->Log(file,line,lv,"");

}

LogMessage::~LogMessage() {

logger->stream()<

logger->stream().flush();

mutex.Unlock();

}

} /* namespace FrameWork */

Logger.h

#ifndef LOGGER_H_

#define LOGGER_H_

#include "ILogger.h"

#include "Mutex.h"

#include

#include

const int MaxFilePathLen = 1024;

const char PathSplitChar = '/';

namespace FrameWork {

enum LogLevel{

///

/// 调试

///

DEBUG = -1,

///

/// 普通日志

///

INFO = 0,

///

/// 警告

///

WARN,

///

/// 错误

///

ERROR,

///

/// 崩溃

///

FATAL,

///

/// 超出错误级别

///

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,int line,LogLevel lv,string msg)=0;\

virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...)=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 * folder,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,const char* fmt,...);\

virtual void name(const char* file,int line,LogLevel lv,string msg);\

virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...);

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, int line,LogLevel lv);

ostream& stream(){return logger->stream();}

virtual ~LogMessage();

};

void InitLogging(const char* filename,LogLevel minlevel,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

#include "Logger.h"

using namespace std;

using namespace FrameWork;

int main(int argc,char* argv[]) {

InitLogging(argv[0],INFO,"./log/test");

cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

LOG(INFO)<

LOG(WARN)<

LOG(ERROR)<

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

#include

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_ */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值