1. 程式人生 > 其它 >C++ 日誌模組列印

C++ 日誌模組列印

技術標籤:C++基礎/高階loggingc++c++11

日誌模組標頭檔案

#pragma once

#define LOG_PRINT(printLev, format, ...) LogPrinter::LogPrint(printLev, __FILE__, __LINE__, format, __VA_ARGS__);

#define LOG_PRINT_INFO(format, ...) LogPrinter::LogPrint(PRINT_LEV_INFO, __FILE__, __LINE__, format, __VA_ARGS__);
#define LOG_PRINT_EVENT(format, ...) LogPrinter::LogPrint(PRINT_LEV_EVENT, __FILE__, __LINE__, format, __VA_ARGS__);
#define LOG_PRINT_ERROR(format, ...) LogPrinter::LogPrint(PRINT_LEV_ERROR, __FILE__, __LINE__, format, __VA_ARGS__); #define LOG_PRINT_DEBUG(format, ...) LogPrinter::LogPrint(PRINT_LEV_DEBUG, __FILE__, __LINE__, format, __VA_ARGS__); enum PRINT_LEV { PRINT_LEV_DEBUG, PRINT_LEV_INFO, PRINT_LEV_EVENT,
PRINT_LEV_ERROR, PRINT_LEV_UNKNOWN, PRINT_LEV_NUM }; class LogPrinter { private: explicit LogPrinter(); ~LogPrinter(); public: static void LogPrint(PRINT_LEV printLev, const char* filename, int lineNo, const char* format, ...); private: class LogPrinterDef; static
LogPrinterDef* _PrinterDef; };

日誌模組原始檔

#include <stdio.h>
#include <string>
#include <stdarg.h>
#include <time.h>

#include "LogPrinter.h"

using namespace std;

#define RUN_LOG_FILENAME "RunLog.log"
#define LOG_FILE_MAX_SIZE (60 * 1024 * 1024)   // 單檔案大小限制:60MB

class LogPrinter::LogPrinterDef
{
private:
    static const string m_printLevel[PRINT_LEV_NUM];

public:
    void prevInfoPrint(PRINT_LEV printLev, const char* fileName, int lineNo) {
        char buf[128];

        time_t now = time(0);
        tm ltm;
        localtime_s(&ltm, &now);

        sprintf_s(buf, "[%d/%02d/%02d %2d:%02d:%02d] [%s:%d] [%s]: ",
            ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday,
            ltm.tm_hour, ltm.tm_min, ltm.tm_sec,
            fileName, lineNo, m_printLevel[printLev].data());

        printf("%s", buf);

        FILE* fp;
        ::fopen_s(&fp, RUN_LOG_FILENAME, "a+");
        if (!fp) {
            return;
        }

        fwrite(buf, sizeof(char), strlen(buf), fp);
        fclose(fp);
    }

    int GetFileSize() {
        struct stat statbuf;
        stat(RUN_LOG_FILENAME, &statbuf);
        return statbuf.st_size;
    }

    void logFileSizeCtl() {
        if (GetFileSize() < LOG_FILE_MAX_SIZE)
            return;

        const char* newname = "RunLogBack.log";

        FILE* fp;
        fopen_s(&fp, newname, "r");
        if (fp != NULL) {
            fclose(fp);
            remove(newname);
        }
        rename(RUN_LOG_FILENAME, newname);
    }
};

LogPrinter::LogPrinterDef* LogPrinter::_PrinterDef = new LogPrinterDef;

const string LogPrinter::LogPrinterDef::m_printLevel[PRINT_LEV_NUM] = {
    "Debug",
    "Info",
    "Event",
    "Error",
    "Unknown",
};


LogPrinter::LogPrinter() {}

LogPrinter::~LogPrinter() { delete _PrinterDef; _PrinterDef = nullptr; }

/* 記錄日誌
* @param printLev  [日誌資訊等級]
* @param filename  [日誌資訊檔名]
* @param lineNo    [日誌資訊所在行]
* @param format    [日誌資訊列表格式]
*/
void __cdecl LogPrinter::LogPrint(PRINT_LEV printLev, const char* filename, int lineNo, const char* format, ...)    // __cdecl 是關鍵的返回值型別
{
    if (printLev < 0 || printLev >= PRINT_LEV_NUM)
        printLev = PRINT_LEV_UNKNOWN;

    _PrinterDef->logFileSizeCtl();

    string s_filiname;
    const char* temp = strrchr(filename, '\\');
    if (temp)
        s_filiname = temp + 1;
    else
        s_filiname = filename;
    _PrinterDef->prevInfoPrint(printLev, s_filiname.data(), lineNo);

    va_list args;
    va_start(args, format);
    vprintf(format, args);
    printf("\n");

    FILE* fp;
    ::fopen_s(&fp, RUN_LOG_FILENAME, "a+");
    if (!fp) {
        return;
    }
    vfprintf(fp, format, args);
    fwrite("\n", 1, 1, fp);
    fclose(fp);

    return;
}

呼叫方法:

int main()
{
	LOG_PRINT_INFO("要列印的字串: %s, %s","Hello", "world");
	return 0;
}

執行截圖:
在這裡插入圖片描述