C++ Log日誌系統(雛形)
阿新 • • 發佈:2020-10-29
閒得無聊,瞎寫的一個東西。
測試了一下,執行緒安全,但程序不安全。
想要程序安全需要呼叫作業系統的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; }
我發現我越來越懶,咋辦。。。