1. 程式人生 > 實用技巧 >C++ Log日誌系統(雛形)

C++ Log日誌系統(雛形)

閒得無聊,瞎寫的一個東西。

測試了一下,執行緒安全,但程序不安全。

想要程序安全需要呼叫作業系統的API,懶得弄。

好多地方能夠優化甚至可能重寫,也沒寫,就記下了個思路在這裡。

主要熟練一下C++17的內容。

.h

#pragma once

#ifdef _WIN32
    #include "windows.h"
    #include <fileapi.h>
#else
    //
#endif // _WIN32

#include <fstream>
#include <iostream>
#include <functional>

enum
{ _isEnableSaveFile = 1, //_isErrorReportFileNotExist = -2, //_isFileNeedLock = 3, }; constexpr const char* szMidfix = "_"; constexpr const size_t _nFileMaxSize_KB = 102400; constexpr const size_t _nEachLogLengthMax = 1024; enum ELogType { LOG_DEBUG, LOG_INFO, LOG_ERROR, LOG_WARNING, __LOG_Max_
//... }; constexpr static const char* _enumLogType[] = { "DEBUG", "INFO", "ERROR", "WARNING", //... }; static_assert(__LOG_Max_ >= (sizeof(_enumLogType) / sizeof(char*)), "The Log Type Count Lesser Than _enumLogType size."); class Logs final { public://private: //TODO: public for test.
Logs(const char* szFile); public: ~Logs(); public: template<ELogType type, typename ...TArgs> void Log(const char* szFile, const char* szFunc, uint32_t nLine, const char* szMsgFormat, TArgs... Args...); private: void Init(const char* szFile); template<ELogType type, typename ...TArgs> size_t Write(const char* szFile, const char* szFunc, uint32_t nLine, const char* szMsgFormat, TArgs... Args...); private: std::fstream _file; std::string _szFilename; public: std::function<std::string(const std::string& szLastName)> _fcChangeNameRule; }; template<ELogType type, typename ...TArgs> inline void Logs::Log(const char* szFile, const char* szFunc, uint32_t nLine, const char* szMsgFormat, TArgs... Args...) { //const std::function<void()>& run = [&]() -> void //{ Write<type, TArgs...>(szFile, szFunc, nLine, szMsgFormat, Args...); //}; // //run(); //3000 times, 15ms. ////3000 times, 160ms. //std::future ret = std::async(std::launch::async, run); //if (!ret.valid()) //{ // //TODO: Do Something... // // //} } template<ELogType type, typename ...TArgs> inline size_t Logs::Write(const char* szFile, const char* szFunc, uint32_t nLine, const char* szMsgFormat, TArgs...Args ...) { static const char* szBase = "[%s] %s, Function: %s, Line: %d: \n\t%s\n"; char szRes[_nEachLogLengthMax]; char szTemp[_nEachLogLengthMax]; bool isHaveArgs = false; if constexpr (sizeof...(Args) > 0) { isHaveArgs = true; snprintf(szTemp, _nEachLogLengthMax, szMsgFormat, Args...); } size_t nWriteSize = snprintf(szRes, _nEachLogLengthMax, szBase, _enumLogType[static_cast<size_t>(type)], szFile, szFunc, nLine, isHaveArgs ? szTemp : szMsgFormat); puts(szRes); if (_isEnableSaveFile > 0) { _file << szRes; _file.seekg(0, std::ios_base::end); size_t nFileLen = static_cast<size_t>(_file.tellg()); if (nFileLen >= _nFileMaxSize_KB) { Init(_fcChangeNameRule(_szFilename).c_str()); } } return nWriteSize; } extern Logs g_log; //TODO: Rebuild... #define TestLogMarco(type, format, ...) do{g_log.Log<type>(__FILE__, __func__, __LINE__, format, ##__VA_ARGS__);}while(0); //#define RegistrLogger(type, name) //..

.cpp

#include "Logs.h"

Logs g_log("C:\\Users\\Administrator\\Desktop\\123ttt.log");

Logs::Logs(const char* szFile)
{
    _fcChangeNameRule = [](const std::string& szLast) ->std::string
    {
        return "";
    };

    Init(szFile);
}

Logs::~Logs()
{
    _file.close();
}

void Logs::Init(const char* szFile)
{
    if (szFile == "")
        return;

    if (_file.is_open())
    {
        _file.close();
    }

    _file.open(szFile, std::ios::out | std::ios::app);
    _szFilename = szFile;
}

main.cpp

#include <iostream>
#include <stdio.h>
#include "Logs.h"
#include <chrono>
#include <thread>

#pragma strict_gs_check(on)

//#define Log(t, msgs, ...) if ((t)) { printf(msgs, __VA_ARGS__); }
using namespace std::chrono;
int main() 
{
    //int a = puts("hhahah");
    //Log(1, "123 %s, %d.", "asd", 456);
    
    auto time_now = system_clock::now();
    auto duration_in_ms = duration_cast<milliseconds>(time_now.time_since_epoch());
    uint64_t nFactTime = duration_in_ms.count();

    for (size_t i = 0; i < 1500; i++)
    {
        TestLogMarco(ELogType::LOG_DEBUG, "22 %d", 222);
        TestLogMarco(ELogType::LOG_INFO, "33333");
    }
    
    auto time_now2 = system_clock::now();
    auto duration_in_ms2 = duration_cast<milliseconds>(time_now2.time_since_epoch());
    uint64_t nFactTime2 = duration_in_ms2.count();
    std::cout << nFactTime2 - nFactTime << std::endl;
    
    std::thread th1([]() 
        {
            auto time_now = system_clock::now();
            auto duration_in_ms = duration_cast<milliseconds>(time_now.time_since_epoch());
            uint64_t nFactTime = duration_in_ms.count();

            for (size_t i = 0; i < 150000; i++)
            {
                TestLogMarco(ELogType::LOG_DEBUG, "22 %d", 222);
                //TestLogMarco(ELogType::LOG_INFO, "33333");
            }

            auto time_now2 = system_clock::now();
            auto duration_in_ms2 = duration_cast<milliseconds>(time_now2.time_since_epoch());
            uint64_t nFactTime2 = duration_in_ms2.count();
            std::cout << "[2]: " << nFactTime2 - nFactTime << std::endl;
        });

    std::thread th2([]() 
        {
            auto time_now = system_clock::now();
            auto duration_in_ms = duration_cast<milliseconds>(time_now.time_since_epoch());
            uint64_t nFactTime = duration_in_ms.count();

            for (size_t i = 0; i < 150000; i++)
            {
                //TestLogMarco(ELogType::LOG_DEBUG, "22 %d", 222);
                TestLogMarco(ELogType::LOG_INFO, "33333");
            }

            auto time_now2 = system_clock::now();
            auto duration_in_ms2 = duration_cast<milliseconds>(time_now2.time_since_epoch());
            uint64_t nFactTime2 = duration_in_ms2.count();
            std::cout << "[3]: " << nFactTime2 - nFactTime << std::endl;
        });

    th1.join();
    th2.join();
    system("pause>nul");
    return 0;
}

我發現我越來越懶,咋辦。。。