天天看點

來自mooon的最簡單的日志類CSimpleLogger

/**

 * <b>單個頭檔案,可即時獨立使用</b><b>,隻要定義了宏NOT_WITH_MOOON,即不依賴于mooon</b>

 * 簡單的寫日志類,非線程安全,提供按大小滾動功能

 * 不追求功能,也不追求性能,隻求簡單,若要功能強、性能高,可以使用CLogger

 *

 * 使用方法:

 * 1) 構造一個<b>CSimpleLogger</b>對象

 *    <b>CSimpleLogger </b><b>logger</b>(".", "test.log", 1024*1024, 10);

 * 2) 調用print方法寫日志

 *    logger.<b>print</b>("%s\n", "test");

 */

#ifndef MOOON_SYS_SIMPLE_LOGGER_H

#define MOOON_SYS_SIMPLE_LOGGER_H

// 隻要定義了NOT_WITH_MOOON宏,

// 則本檔案和mooon無任何關系,友善內建到自己的代碼中

<b>#define NOT_WITH_MOOON</b>

#if !defined(NOT_WITH_MOOON)

#include

#endif // NOT_WITH_MOOON

SYS_NAMESPACE_BEGIN

/***

  * 萬能型類型轉換函數

  */

template

inline std::string any2string(AnyType any_value)

{

    std::stringstream result_stream;

    result_stream

    return result_stream.str();

}

  * 取目前時間,和date_util.h有重複,但為保持simple_logger.h的獨立性,在所難免

inline void get_current_datetime(char* datetime_buffer, size_t datetime_buffer_size)

    struct tm result;

    time_t now = time(NULL);

    localtime_r(&amp;now, &amp;result);

    snprintf(datetime_buffer, datetime_buffer_size

        ,"%04d-%02d-%02d %02d:%02d:%02d"

        ,result.tm_year+1900, result.tm_mon+1, result.tm_mday

        ,result.tm_hour, result.tm_min, result.tm_sec);

class <b>CSimpleLogger</b>

public:

    /***

      * 構造一個CSimpleLogger,并建立或打開日志檔案

      * @log_dir 日志存放的目錄,不需要以斜杠結尾,目錄必須已經存在

      * @filename 日志的檔案名,不包含目錄部分,

      *           由log_dir和filename共同組成日志檔案路徑

      * @log_size 每個日志檔案的大小,機關為位元組數,如果小于1024,則會被強制為1024

      * @log_numer 日志滾動的個數

      * @record_size 單條日志的大小,超過會被截斷,機關為位元組數,如果小于1024,則會被強制為1024

      */

    <b>CSimpleLogger</b>(const std::string&amp; log_dir

                 ,const std::string&amp; filename

                 ,unsigned int log_size = 1024*1024*100

                 ,unsigned char log_numer = 10

                 ,unsigned short record_size = 8192);

    ~CSimpleLogger();

    /** 日志檔案是否建立或打開成功 */

    bool is_ok() const;

    /** 輸出日志,象printf一樣使用,不自動加換行符 */

    void print(const char* format, ...);

    /** 重新整理日志,因為使用FILE是帶緩存的 */

    void flush();

private:

    void reset();    /** 複位狀态值 */

    void roll_log(); /** 滾動日志 */

    FILE* _fp;                    /** 目前正在寫的日志檔案描述符 */

    char* _log_buffer;            /** 存放日志的Buffer */

    int _bytes_writed;            /** 已經寫入的位元組數 */

    std::string _log_dir;         /** 日志存放目錄 */

    std::string _filename;        /** 日志檔案名,不包含目錄部分 */

    unsigned int _log_size;       /** 單個日志檔案的大小 */

    unsigned char _log_numer;     /** 日志滾動的個數 */

    unsigned short _record_size;  /** 單條日志的大小,機關為位元組數 */

};

inline CSimpleLogger::CSimpleLogger(

                     const std::string&amp; log_dir 

                    ,const std::string&amp; filename

                    ,unsigned int log_size

                    ,unsigned char log_numer

                    ,unsigned short record_size)

 :_fp(NULL)

 ,_log_buffer(NULL)

 ,_bytes_writed(0)

 ,_log_dir(log_dir)

 ,_filename(filename)

 ,_log_size(log_size)

 ,_log_numer(log_numer)

 ,_record_size(record_size)

    std::string log_path = log_dir + std::string("/") + filename;

    _fp = fopen(log_path.c_str(), "a");

    if (_fp != NULL)

    {

        if (-1 == fseek(_fp, 0, SEEK_END))

        {

            // 失敗,将不會寫日志

            fclose(_fp);

            _fp = NULL;

        }

        else

            // 取得已有大小

            _bytes_writed = ftell(_fp);

            // 不能太小氣了          

            if (_log_size

            {

                _log_size = 1024;

            }

            // 同樣不能太小氣

            if (_record_size

                _record_size = 1024;

            _log_buffer = new char[_record_size];

    }

inline CSimpleLogger::~CSimpleLogger()

        fclose(_fp);

    delete []_log_buffer;

inline bool CSimpleLogger::is_ok() const

    return _fp != NULL;

inline void CSimpleLogger::print(const char* format, ...)

        va_list ap;

        va_start(ap, format);

        char datetime_buffer[sizeof("2012-12-21 00:00:00")]; // 剛好世界末日

        get_current_datetime(datetime_buffer, sizeof(datetime_buffer));

        vsnprintf(_log_buffer, _record_size, format, ap);

        int bytes_writed = fprintf(_fp, "[%s]%s", datetime_buffer, _log_buffer);

        if (bytes_writed &gt; 0)

            _bytes_writed += bytes_writed;

        if (_bytes_writed &gt; static_cast(_log_size))

            roll_log();

        va_end(ap);

inline void CSimpleLogger::roll_log()

    std::string new_path; // 滾動後的檔案路徑,包含目錄和檔案名

    std::string old_path; // 滾動前的檔案路徑,包含目錄和檔案名

    reset(); // 輪回,一切重新開始

    // 曆史滾動

    for (int i=_log_numer-1; i&gt;0; --i)

        new_path = _log_dir + std::string("/") + _filename + std::string(".") + any2string(i);

        old_path = _log_dir + std::string("/") + _filename + std::string(".") + any2string(i-1);

        if (0 == access(old_path.c_str(), F_OK))

            rename(old_path.c_str(), new_path.c_str());

    if (_log_numer &gt; 0)

        // 目前滾動

        new_path = _log_dir + std::string("/") + _filename + std::string(".1");

        old_path = _log_dir + std::string("/") + _filename;

    // 重新建立

    _fp = fopen(old_path.c_str(), "w+");

inline void CSimpleLogger::reset()

    _bytes_writed = 0;

        _fp = NULL;

inline void CSimpleLogger::flush()

        fflush(_fp);

  * 測試代碼

#include "simple_logger.h"

int main()

    CSimpleLogger logger(".", "test.log", 10240);

    for (int i=0; i

        logger.print("%d ==&gt; abcdefghijklmnopqrestuvwxyz.\n", i);

    return 0;

*/

SYS_NAMESPACE_END

#endif // MOOON_SYS_SIMPLE_LOGGER_H

閱讀(1676) | 評論(1) | 轉發(1) |

給主人留下些什麼吧!~~

來自mooon的最簡單的日志類CSimpleLogger

<b>dyllove98</b>:

來自mooon的最簡單的日志類CSimpleLogger

.....

來自mooon的最簡單的日志類CSimpleLogger

評論熱議

請登入後評論。