C + + Write log file function sharing _c language in Linux system

Source: Internet
Author: User
Tags assert flush fread mkdir mutex strlen volatile

Simplifies the glog, only retains the function of writing log files, only to rewrite the Linux version, the win version is not rewritten, you can use
Log (INFO) << output logs
Log_if (info,condition) << output logs are also available
You can also call the Log Class Logger::getinstance () directly. Error and other ways to write a log
Call Initlogging (Argv[0],info, "./log/test") when initializing;
The first parameter is the path, the second parameter is the lowest log level, and the third parameter represents the prefix and folder of the log file

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, 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);
&NBSP;&NBSP;//&NBSP}
  //}
        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 &lt; Ilen;i + +) {


if (pszdir[i] = = ' \ ' | | pszdir[i] = = '/') {


Buf[i] = ' the ';


If it does not exist, create


IRet = ACCESS (buf,0);


if (iRet!= 0) {


IRet = MKDIR (BUF);


if (iRet!= 0) {


Delete[] BUF;


return false;


}


}


Support Linux, replace all \


Buf[i] = '/';


}


}


Delete[] BUF;


return true;


}


Private

enum {buffer_size = 3000};

};

}/* Namespace FrameWork * *
#endif/* Filehelper_h_ * *
[/code]

Logger.cpp

Copy Code code as follows:



#include "Logger.h"


#include &lt;cstring&gt;


#include &lt;time.h&gt;


#include &lt;cstdarg&gt;


#include &lt;cstdlib&gt;


#include &lt;assert.h&gt;


#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&gt;0 &amp;&amp; (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 &gt;0 &amp;&amp; Filename[pos]!= Pathsplitchar)


pos--;


strncpy (_appfolder,filename,pos+1);


Lend = strlen (Destfolder);


Posd = lend-1;


if (Destfolder[lend-1]!= Pathsplitchar) {


Has prefix


while (Posd &gt;0 &amp;&amp; destfolder[posd]!= Pathsplitchar)


posd--;


}


if (destfolder[0] = = '. ' &amp;&amp; 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<< "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,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<< "[" <<getcurtime (). C_STR () << "] [" #lv] "<<_gbuffer<<endl;\
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<< "[" <<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, int line, loglevel LV, const char* format,...) {
If (level <= LV) {
Writermutexlock Lock (&mutex);
Print_args_to_buffer (Format,_gbuffer)
logfile<< "[" <<getcurtime (). C_STR () << "[" <<_levelInfos[lv+1]<< "] [" <<file << "[" <<line<< "]" <<_gBuffer;
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 () <<endl;
Logger->stream (). Flush ();
Mutex. Unlock ();
}

}/* Namespace FrameWork * *

Logger.h

Copy Code code as follows:



#ifndef Logger_h_


#define Logger_h_

#include "ILogger.h"


#include "Mutex.h"


#include &lt;fstream&gt;


#include &lt;string&gt;


const int Maxfilepathlen = 1024;


const char Pathsplitchar = '/';


Namespace FrameWork {


Enum loglevel{


&lt;summary&gt;


Debugging


&lt;/summary&gt;


DEBUG =-1,


&lt;summary&gt;


Normal log


&lt;/summary&gt;


INFO = 0,


&lt;summary&gt;


Warning


&lt;/summary&gt;


WARN,


&lt;summary&gt;


Error


&lt;/summary&gt;


ERROR,


&lt;summary&gt;


Collapse


&lt;/summary&gt;


FATAL,


&lt;summary&gt;


Error level exceeded


&lt;/summary&gt;


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

Copy Code code as follows:

#include <iostream>
#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) << "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", M, "Zhongguoren");
return 0;
}

Mutex.h

Copy Code code as follows:



#ifndef Mutex_h_


#define Mutex_h_


#include &lt;pthread.h&gt;


#include &lt;stdlib.h&gt;


Namespace FrameWork {


typedef pthread_mutex_t MUTEXTYPE;

Class Mutex {
Public
Create A Mutex This is isn't held by anybody. This constructor is
Typically used for mutexes allocated on the heap or the stack.
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 this to systems that don ' t support Read-write locks, this may
 //is implemen Ted as synonyms to Lock () and Unlock () .  I can use
 //this for efficiency, but don ' t use them anyplace Where being able
 //to do shared reads are necessary to avoid deadlock.
 inline void ReaderLock ();  //block until free or shared then acquire a share
 inline void Reader Unlock (); Release a read share the This Mutex
 inline void WriterLock () {Lock ();}     //Acquire a exclusive lock
 inline void Writerunlock () {Unlock ();}//Release a lock From WriterLock ()

TODO (Hamaji): Doing nothing, implement correctly.
inline void Assertheld () {}
Private
Mutextype mutex_;
We want to do 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.
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_ &amp;&amp; pthread_mutex_init (&amp;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 (&amp;mutex_) = = 0:true; }


void Mutex::readerlock () {Lock ();}


void Mutex::readerunlock () {Unlock ();}


Class Mutexlock {


Public


Explicit Mutexlock (Mutex *mu): Mu_ (mu) {mu_-&gt;lock ();}


~mutexlock () {Mu_-&gt;unlock ();}


Private


Mutex * Const mu_;


Disallow "evil" constructors


Mutexlock (const mutexlock&amp;);


void operator= (const mutexlock&amp;);


};

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.