zoukankan      html  css  js  c++  java
  • linux c/c++日志输出

    介绍一个在linux下c++开发的一个日志输出的小功能模块,在下面的几个文件当中,代码的设计思路值得我们好好的借鉴

      1 /*
      2  * ILogger.h
      3  *
      4  *  Created on: 2016��1��7��
      5  *      Author: Administrator
      6  */
      7 
      8 #ifndef FRAME_LOG_LOGGER_H_
      9 #define FRAME_LOG_LOGGER_H_
     10 #include <iostream>
     11 #include "Mutex.h"
     12 #include<fstream>
     13 #include<string>
     14 
     15 using namespace std;
     16 
     17 const int MaxFilePathLen = 1024;
     18 const char PathSplitChar = '/';
     19 namespace FrameWork {
     20 enum LogLevel{
     21     /// <summary>
     22     /// 调试
     23     /// </summary>
     24     DEBUG = -1,
     25     /// <summary>
     26     /// 普通日志
     27     /// </summary>
     28     INFO = 0,
     29     /// <summary>
     30     /// 警告
     31     /// </summary>
     32     WARN,
     33     /// <summary>
     34     /// 错误
     35     /// </summary>
     36     ERROR,
     37     /// <summary>
     38     /// 崩溃
     39     /// </summary>
     40     FATAL,
     41     /// <summary>
     42     /// 超出错误级别
     43     /// </summary>
     44     OFF
     45 };
     46 
     47 
     48 class ILogger {
     49 public:
     50     //
     51     virtual ~ILogger() {
     52     }
     53 
     54 //利用宏定义,来简化代码输出,值得推荐
     55 #define ABSTRACT_LOG_FUNC(name) 
     56     virtual void name(string msg)=0; 
     57     virtual void name(const char* fmt,...)=0;
     58 
     59     ABSTRACT_LOG_FUNC(Debug)
     60     ABSTRACT_LOG_FUNC(Info)
     61     ABSTRACT_LOG_FUNC(Warn)
     62     ABSTRACT_LOG_FUNC(Error)
     63     ABSTRACT_LOG_FUNC(Fatal)
     64 
     65 #undef ABSTRACT_LOG_FUNC
     66 #define ABSTRACT_LOG_FUNC_X(name) 
     67     virtual void name(LogLevel lv,string msg)=0; 
     68     virtual void name(LogLevel lv,const char* fmt,...)=0;
     69     virtual void name(const char* file,int line,LogLevel lv,string msg)=0;
     70     virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...)=0;
     71     ABSTRACT_LOG_FUNC_X(Log)
     72 
     73 #undef LOG_FUNC_X
     74 };
     75 
     76 class Logger: public ILogger {
     77     std::string logPath;
     78     std::string logPrefix;
     79     std::fstream logFile;
     80     LogLevel level;
     81     Mutex mutex;
     82 
     83     Logger(LogLevel level, char * folder, char * prefix);
     84 
     85 public:
     86     static Logger& GetInstance();
     87     static Logger* GetInstancePtr();
     88     virtual ~Logger();
     89     inline fstream & stream() {
     90         return logFile;
     91     }
     92 
     93 #define DECLARE_LOG_FUNC(name) 
     94     virtual void name(string msg); 
     95     virtual void name(const char* fmt,...);
     96 
     97 #define DECLARE_LOG_FUNC_X(name) 
     98     virtual void name(LogLevel lv,string msg); 
     99     virtual void name(LogLevel lv,const char* fmt,...);
    100     virtual void name(const char* file,int line,LogLevel lv,string msg);
    101     virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...);
    102 
    103     DECLARE_LOG_FUNC(Debug)
    104     DECLARE_LOG_FUNC(Info)
    105     DECLARE_LOG_FUNC(Warn)
    106     DECLARE_LOG_FUNC(Error)
    107     DECLARE_LOG_FUNC(Fatal)
    108 
    109     DECLARE_LOG_FUNC_X(Log)
    110 
    111 #undef DECLARE_LOG_FUNC_X
    112 #undef DECLARE_LOG_FUNC
    113 
    114 };
    115 
    116 class LogMessage {
    117     Logger* logger;
    118     static Mutex mutex;
    119 public:
    120     LogMessage(const char* file, int line, LogLevel lv);
    121     LogMessage(LogLevel lv);
    122     ostream& stream() {
    123         return logger->stream();
    124     }
    125     virtual ~LogMessage();
    126 };
    127 
    128 void InitLogging(const char* filename, LogLevel minlevel,
    129         const char* destFolder);
    130 void CloseLogging();
    131 
    132 #define LOG(level) LogMessage(__FILE__, __LINE__,level).stream()
    133 
    134 #define LOGFILE(level) LogMessage(level).stream()
    135 
    136 #define LOG_IF(severity, condition) 
    137     !(condition) ? (void) 0 : LOG(severity)
    138 #define LOG_ASSERT(condition)  
    139     LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
    140 #define CHECK(condition)  
    141     LOG_IF(FATAL, !(condition)) 
    142     << "Check failed: " #condition " "
    143 
    144 } /* namespace FrameWork */
    145 
    146 #endif /* FRAME_LOG_LOGGER_H_ */
    View Code

    Logger的实现,在文件内定义了输助函数的使用

      1 /*
      2  * Logger.cpp
      3  *
      4  *      Author: liu xw
      5  */
      6 
      7 #include "Logger.h"
      8 #include<cstring>
      9 #include<time.h>
     10 #include<cstdarg>
     11 #include<cstdlib>
     12 #include<assert.h>
     13 #include "FileHelper.h"
     14 #include "Mutex.h"
     15 namespace FrameWork {
     16 Mutex LogMessage::mutex;
     17 static char _defaltFolder[]="/var/tmp/";
     18 static char _appName[MaxFilePathLen];
     19 static char _appFolder[MaxFilePathLen];
     20 static char _destFolder[MaxFilePathLen];
     21 static char _destPrefix[MaxFilePathLen];
     22 static LogLevel _destLevel;
     23 static char _levelInfos[][16]={
     24     "Debug","Info","Warn","Error","Fatal"
     25 };
     26 const int BUFFER_SIZE = 8196;
     27 static char _gBuffer[BUFFER_SIZE];
     28 void combine_folder(char** destpath, char* basefolder,char* relativefolder)
     29 {
     30     int lenb = strlen(basefolder);
     31     int lenr = strlen(relativefolder);
     32     char* pret = (char*)malloc((lenb+lenr+1)*sizeof(char));
     33     int pos=lenb-1;
     34     memset(pret,0,lenb+lenr+1);
     35     while(pos>0 && ( basefolder[pos]!='/'))
     36         pos--;
     37     strncpy(*destpath,basefolder,pos+1);
     38     if(relativefolder[0] == '\' || relativefolder[0] == '/'){
     39         strncpy(*destpath+pos+1,relativefolder+1,lenr-1);
     40     }else{
     41         strncpy(*destpath+pos+1,relativefolder,lenr);
     42     }
     43 }
     44 
     45 static void InitPaths(const char* filename,const char* destFolder)
     46 {
     47     memset(_appName,0,MaxFilePathLen);
     48     memset(_appFolder,0,MaxFilePathLen);
     49     memset(_destFolder,0,MaxFilePathLen);
     50     memset(_destPrefix,0,MaxFilePathLen);
     51 
     52     strcpy(_appName,filename);
     53     int len = strlen(filename),lend;
     54     int pos = len-1,posd,start;
     55     while(pos >0 && filename[pos] != PathSplitChar)
     56         pos--;
     57     strncpy(_appFolder,filename,pos+1);
     58     lend = strlen(destFolder);
     59     posd = lend-1;
     60     if(destFolder[lend-1] != PathSplitChar) {
     61         //has prefix
     62         while(posd >0 && destFolder[posd] != PathSplitChar)
     63             posd--;
     64     }
     65     if(destFolder[0] == '.' && destFolder[1] == PathSplitChar){
     66         strncpy(_destFolder,filename,pos+1);
     67         start = 2;
     68     }   else{
     69         pos = 8;
     70         strcpy(_destFolder,_defaltFolder);
     71         if(destFolder[0] != PathSplitChar){
     72             start = 0;
     73         }else{
     74             start = 1;
     75         }
     76     }
     77     strncpy(_destFolder+pos+1,destFolder+start,posd-start+1);
     78     strncpy(_destPrefix,filename,pos+1);
     79     strncpy(_destPrefix+pos+1,destFolder+start,lend-start);
     80 }
     81 
     82 void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder)
     83 {
     84     InitPaths(filename,destFolder);
     85     _destLevel = minlevel;
     86 }
     87 
     88 
     89 
     90 static string GetLocalDate(void)
     91 {
     92     time_t t = time(0);
     93     tm *ld;
     94     char tmp[64] = "";
     95     ld=localtime(&t);
     96     strftime(tmp,sizeof(tmp),"%Y-%m-%d",ld);
     97     return string(tmp);
     98 }
     99 static string GetCurTime(void)
    100 {
    101     time_t t = time(0);
    102     tm *ld;
    103     char tmp[64] = "";
    104     ld=localtime(&t);
    105     strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",ld);
    106     return string(tmp);
    107 }
    108 
    109 Logger::Logger(LogLevel level,char * folder,char * prefix)
    110     :level(level)
    111 {
    112     std::string path;
    113     path.append(prefix);
    114     path.append(GetLocalDate());
    115     path.append(".log");
    116     FileHelper::CreateDir(folder);
    117     logPrefix.append(prefix);
    118     logPath = path;
    119     logFile.open(path.c_str(),ios::app|ios::out);
    120     logFile<<"Log file created at:"<<GetCurTime()<<endl;
    121 }
    122 
    123 Logger::~Logger() {
    124     logFile.close();
    125 }
    126 
    127 #define IMPLEMENT_LOG_FUNC1(cname,fname,lv) 
    128 void cname::fname(string msg) {
    129     if(level <= lv){
    130         WriterMutexLock lock(&mutex);
    131         logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<msg.c_str()<<endl;
    132         logFile.flush();
    133     }
    134 }
    135 
    136 #define PRINT_ARGS_TO_BUFFER(fmt,buf) 
    137     {
    138         memset(buf,0,sizeof(buf));
    139         va_list argp;
    140         va_start(argp,fmt);
    141         vsprintf(buf,fmt,argp);
    142         va_end(argp);
    143     }
    144 
    145 #define IMPLEMENT_LOG_FUNC2(cname,fname,lv) 
    146 void cname::fname(const char* format,...) {
    147     if(level <= lv){
    148         WriterMutexLock lock(&mutex);
    149         PRINT_ARGS_TO_BUFFER(format,_gBuffer)
    150         logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<_gBuffer<<endl;
    151         logFile.flush();
    152     }
    153 }
    154 
    155 
    156 #define IMPLEMENT_LOG_FUNC(cname,fname,lv) 
    157 IMPLEMENT_LOG_FUNC1(cname,fname,lv)
    158 IMPLEMENT_LOG_FUNC2(cname,fname,lv)
    159 
    160 IMPLEMENT_LOG_FUNC(Logger,Debug,DEBUG)
    161 IMPLEMENT_LOG_FUNC(Logger,Info,INFO)
    162 IMPLEMENT_LOG_FUNC(Logger,Warn,WARN)
    163 IMPLEMENT_LOG_FUNC(Logger,Error,ERROR)
    164 IMPLEMENT_LOG_FUNC(Logger,Fatal,FATAL)
    165 
    166 Logger& Logger::GetInstance() {
    167     static Logger _logger(_destLevel,_destFolder,_destPrefix);
    168     return _logger;
    169 }
    170 
    171 void Logger::Log(LogLevel lv, string msg) {
    172     if(level <= lv){
    173         WriterMutexLock lock(&mutex);
    174         logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<msg.c_str()<<endl;
    175         logFile.flush();
    176     }
    177 }
    178 
    179 void Logger::Log(LogLevel lv, const char* format,...) {
    180     if(level <= lv){
    181         WriterMutexLock lock(&mutex);
    182         PRINT_ARGS_TO_BUFFER(format,_gBuffer)
    183         logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<_gBuffer<<endl;
    184         logFile.flush();
    185     }
    186 }
    187 
    188 void Logger::Log(const char* file, int line, LogLevel lv, string msg) {
    189     if(level <= lv){
    190         WriterMutexLock lock(&mutex);
    191         logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<msg.c_str();
    192         logFile.flush();
    193     }
    194 }
    195 
    196 Logger* Logger::GetInstancePtr() {
    197     return &GetInstance();
    198 }
    199 
    200 void Logger::Log(const char* file, int line, LogLevel lv, const char* format,...) {
    201     if(level <= lv){
    202         WriterMutexLock lock(&mutex);
    203         PRINT_ARGS_TO_BUFFER(format,_gBuffer)
    204         logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<_gBuffer;
    205         logFile.flush();
    206     }
    207 }
    208 
    209 LogMessage::LogMessage(const char* file, int line, LogLevel lv) {
    210     logger = Logger::GetInstancePtr();
    211     mutex.Lock();
    212     logger->Log(file,line,lv,"");
    213 }
    214 
    215 LogMessage::LogMessage(LogLevel lv) {
    216     logger = Logger::GetInstancePtr();
    217     mutex.Lock();
    218     logger->Log(lv,"");
    219 }
    220 
    221 LogMessage::~LogMessage() {
    222     logger->stream()<<endl;
    223     logger->stream().flush();
    224     mutex.Unlock();
    225 }
    226 
    227 } /* namespace FrameWork */
    View Code

    读写文件类:FileHelper

      1 /*
      2  * FileHelper.h
      3  *
      4  *  Created on: 2013年9月10日
      5  *      Author: Administrator
      6  */
      7 
      8 #ifndef FILEHELPER_H_
      9 #define FILEHELPER_H_
     10 #include <string>
     11 #include <vector>
     12 #include <fstream>
     13 #include <stdio.h>
     14 #ifdef _WIN32
     15 #include <direct.h>
     16 #include <io.h>
     17 #else
     18 #include <stdarg.h>
     19 #include <sys/stat.h>
     20 #endif
     21 
     22 namespace FrameWork {
     23 #ifdef _WIN32
     24 #define ACCESS _access
     25 #define MKDIR(a) _mkdir((a))
     26 #else
     27 #define ACCESS access
     28 #define MKDIR(a) mkdir((a),0755)
     29 #endif
     30 
     31 class FileHelper {
     32 public:
     33     static bool save(const std::string filename, std::string& content) {
     34         FILE *file = fopen(filename.c_str(), "wb");
     35 
     36         if (file == NULL)
     37             return false;
     38         fwrite(content.c_str(), sizeof(char), content.size(), file);
     39         fclose(file);
     40         return true;
     41     }
     42 
     43     // used to open binary file
     44     static bool open(const std::string filename, std::string& content) {
     45         FILE *file = fopen(filename.c_str(), "rb");
     46 
     47         if (file == NULL)
     48             return false;
     49 
     50         fseek(file, 0, SEEK_END);
     51         int len = ftell(file);
     52         rewind(file);
     53         content.clear();
     54         char *buffer = new char[len];
     55         fread(buffer, sizeof(char), len, file);
     56         content.assign(buffer, len);
     57         delete[] buffer;
     58 
     59         //int nRead;
     60         //content.clear();
     61         //char buffer[80];
     62         //while(!feof(file)){
     63         //  nRead = fread(buffer,sizeof(char),sizeof(buffer),file);
     64         //  if(nRead > 0){
     65         //      content.append(buffer);
     66         //  }
     67         //}
     68         fclose(file);
     69         return true;
     70     }
     71 
     72     // used to open text file
     73     static bool open(const std::string file_name,
     74             std::vector<std::string>& lines) {
     75         std::ifstream file(file_name.c_str(), std::ios::in);
     76         if (!file) {
     77             return false;
     78         }
     79 
     80         lines.clear();
     81         char buffer[BUFFER_SIZE];
     82 
     83         while (file.getline(buffer, BUFFER_SIZE, '
    ')) {
     84             lines.push_back(buffer);
     85         }
     86 
     87         return true;
     88     }
     89     static bool CreateDir(const char *pszDir) {
     90         size_t i = 0;
     91         size_t iRet;
     92         size_t iLen = strlen(pszDir);
     93         char* buf = new char[iLen + 1];
     94         strncpy(buf, pszDir, iLen + 1);
     95         for (i = 0; i < iLen; i++) {
     96             if (pszDir[i] == '\' || pszDir[i] == '/') {
     97                 buf[i] = '';
     98                 //如果不存在,创建
     99                 iRet = ACCESS(buf, 0);
    100                 if (iRet != 0) {
    101                     iRet = MKDIR(buf);
    102                     if (iRet != 0) {
    103                         delete[] buf;
    104                         return false;
    105                     }
    106                 }
    107                 //支持linux,将所有换成/
    108                 buf[i] = '/';
    109             }
    110         }
    111         delete[] buf;
    112         return true;
    113     }
    114 
    115 private:
    116 
    117     enum {
    118         BUFFER_SIZE = 3000
    119     };
    120 
    121 };
    122 
    123 } /* namespace FrameWork */
    124 #endif /* FILEHELPER_H_ */
    View Code

    为线程安全的使用增加互斥量

      1 /*
      2  * Mutex.h
      3  *
      4  *  Created on: 2016年1月7日
      5  *      Author: Administrator
      6  */
      7 
      8 #ifndef FRAME_LOG_MUTEX_H_
      9 #define FRAME_LOG_MUTEX_H_
     10 
     11 #include <pthread.h>
     12 #include <stdlib.h>
     13 namespace FrameWork {
     14 typedef pthread_mutex_t MutexType;
     15 
     16 class Mutex {
     17 public:
     18     // Create a Mutex that is not held by anybody.  This constructor is
     19     // typically used for Mutexes allocated on the heap or the stack.
     20     // See below for a recommendation for constructing global Mutex
     21     // objects.
     22     inline Mutex();
     23 
     24     // Destructor
     25     inline ~Mutex();
     26 
     27     inline void Lock();    // Block if needed until free then acquire exclusively
     28     inline void Unlock();  // Release a lock acquired via Lock()
     29     inline bool TryLock(); // If free, Lock() and return true, else return false
     30     // Note that on systems that don't support read-write locks, these may
     31     // be implemented as synonyms to Lock() and Unlock().  So you can use
     32     // these for efficiency, but don't use them anyplace where being able
     33     // to do shared reads is necessary to avoid deadlock.
     34     inline void ReaderLock();   // Block until free or shared then acquire a share
     35     inline void ReaderUnlock(); // Release a read share of this Mutex
     36     inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
     37     inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
     38 
     39     // TODO(hamaji): Do nothing, implement correctly.
     40     inline void AssertHeld() {}
     41 private:
     42     MutexType mutex_;
     43     // We want to make sure that the compiler sets is_safe_ to true only
     44     // when we tell it to, and never makes assumptions is_safe_ is
     45     // always true.  volatile is the most reliable way to do that.
     46     volatile bool is_safe_;
     47 
     48     inline void SetIsSafe() { is_safe_ = true; }
     49 
     50     // Catch the error of writing Mutex when intending MutexLock.
     51     Mutex(Mutex* /*ignored*/) {}
     52     // Disallow "evil" constructors
     53     Mutex(const Mutex&);
     54     void operator=(const Mutex&);
     55 };
     56 #define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  
     57     if (is_safe_ && fncall(&mutex_) != 0) abort();                           
     58     } while (0)
     59 
     60     Mutex::Mutex()             {
     61         SetIsSafe();
     62         if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
     63     }
     64     Mutex::~Mutex()            { SAFE_PTHREAD(pthread_mutex_destroy); }
     65     void Mutex::Lock()         { SAFE_PTHREAD(pthread_mutex_lock); }
     66     void Mutex::Unlock()       { SAFE_PTHREAD(pthread_mutex_unlock); }
     67     bool Mutex::TryLock()      { return is_safe_ ?
     68         pthread_mutex_trylock(&mutex_) == 0 : true; }
     69     void Mutex::ReaderLock()   { Lock(); }
     70     void Mutex::ReaderUnlock() { Unlock(); }
     71     class MutexLock {
     72     public:
     73         explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
     74         ~MutexLock() { mu_->Unlock(); }
     75     private:
     76         Mutex * const mu_;
     77         // Disallow "evil" constructors
     78         MutexLock(const MutexLock&);
     79         void operator=(const MutexLock&);
     80     };
     81 
     82     // ReaderMutexLock and WriterMutexLock do the same, for rwlocks
     83     class ReaderMutexLock {
     84     public:
     85         explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
     86         ~ReaderMutexLock() { mu_->ReaderUnlock(); }
     87     private:
     88         Mutex * const mu_;
     89         // Disallow "evil" constructors
     90         ReaderMutexLock(const ReaderMutexLock&);
     91         void operator=(const ReaderMutexLock&);
     92     };
     93 
     94     class WriterMutexLock {
     95     public:
     96         explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
     97         ~WriterMutexLock() { mu_->WriterUnlock(); }
     98     private:
     99         Mutex * const mu_;
    100         // Disallow "evil" constructors
    101         WriterMutexLock(const WriterMutexLock&);
    102         void operator=(const WriterMutexLock&);
    103     };
    104 } /* namespace FrameWork */
    105 
    106 #endif /* FRAME_LOG_MUTEX_H_ */
    View Code

    主函数:

     1 /*
     2  * TestLogMain.cpp
     3  *
     4  *  Created on: 2016
     5  *      Author: Administrator
     6  */
     7 
     8 #include <iostream>
     9 #include "Logger.h"
    10 using namespace std;
    11 using namespace FrameWork;
    12 int Main(int argc, char* argv[]) {
    13     InitLogging(argv[0], INFO, "./log/test");
    14     cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    15     LOG(INFO) << "info test";
    16     LOG(WARN) << "WARN TEST %d" << 20;
    17     LOG(ERROR) << "Error test %d %s" << 20 << "nihao";
    18 
    19     Logger::GetInstance().Error("error test common");
    20     Logger::GetInstance().Fatal("fatal test common %d ", 100);
    21     Logger::GetInstance().Info("info test normal %d %s ", 50, "zhongguoren");
    22     return 0;
    23 }
    View Code


    该代码并来源于他人分享,但没有记住地址,十分抱歉。但是里面的代码风格与设计思路是应该好好学习的。

    感谢大神们的分享!

  • 相关阅读:
    tp5.前端模板注释
    站在历史天空下的幻想——高考感怀七十二韵
    公交查询
    模糊查询
    ibox 的使用
    tabs 导航 及内容切换
    c#ADO.NET 执行带参数及有返回数据
    Sql Server中变的定义以及赋值的应用
    EF的3种开发模式
    php7.1.30 下微信公众号问题
  • 原文地址:https://www.cnblogs.com/liuxw7/p/5343471.html
Copyright © 2011-2022 走看看