C++的一個記日誌的程式碼
同事提供的一個記日誌的程式碼,支援四種日誌級別,使用極其簡單,直接include即可。
#ifndef __LOG_H__
#define __LOG_H__
#include <sstream>
#include <string>
#include <stdio.h>
inline std::string NowTime();
enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG};
template <typename T>
class Log
{
public:
Log();
virtual ~Log();
std::ostringstream& Get(TLogLevel level = logINFO);
public:
static TLogLevel& ReportingLevel();
static std::string ToString(TLogLevel level);
static TLogLevel FromString(const std::string& level);
protected:
std::ostringstream os;
private:
Log(const Log&);
Log& operator =(const Log&);
};
template <typename T>
Log<T>::Log()
{
}
template <typename T>
std::ostringstream& Log<T>::Get(TLogLevel level)
{
os << "- " << NowTime();
os << " " << ToString(level) << ": ";
os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
return os;
}
template <typename T>
Log<T>::~Log()
{
os << std::endl;
T::Output(os.str());
}
template <typename T>
TLogLevel& Log<T>::ReportingLevel()
{
static TLogLevel reportingLevel = logDEBUG;
return reportingLevel;
}
template <typename T>
std::string Log<T>::ToString(TLogLevel level)
{
static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG"};
return buffer[level];
}
template <typename T>
TLogLevel Log<T>::FromString(const std::string& level)
{
if (level == "DEBUG")
return logDEBUG;
if (level == "INFO")
return logINFO;
if (level == "WARNING")
return logWARNING;
if (level == "ERROR")
return logERROR;
Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default.";
return logINFO;
}
class Output2FILE
{
public:
static FILE*& Stream();
static void Output(const std::string& msg);
};
inline FILE*& Output2FILE::Stream()
{
static FILE* pStream = stderr;
return pStream;
}
inline void Output2FILE::Output(const std::string& msg)
{
FILE* pStream = Stream();
if (!pStream)
return;
fprintf(pStream, "%s", msg.c_str());
fflush(pStream);
}
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# if defined (BUILDING_FILELOG_DLL)
# define FILELOG_DECLSPEC __declspec (dllexport)
# elif defined (USING_FILELOG_DLL)
# define FILELOG_DECLSPEC __declspec (dllimport)
# else
# define FILELOG_DECLSPEC
# endif // BUILDING_DBSIMPLE_DLL
#else
# define FILELOG_DECLSPEC
#endif // _WIN32
class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {};
//typedef Log<Output2FILE> FILELog;
#ifndef FILELOG_MAX_LEVEL
#define FILELOG_MAX_LEVEL logDEBUG
#endif
#define FILE_LOG(level) \
if (level > FILELOG_MAX_LEVEL) ;\
else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
else FILELog().Get(level)
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#include <windows.h>
inline std::string NowTime()
{
const int MAX_LEN = 200;
char buffer[MAX_LEN];
char dateBuffer[MAX_LEN];
if (GetDateFormatA(LOCALE_USER_DEFAULT, 0, 0,
"yyyy'-'MM'-'dd", dateBuffer,MAX_LEN) == 0)
return "Error in NowTime() GetDateFormatA";
if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
"HH':'mm':'ss", buffer, MAX_LEN) == 0)
return "Error in NowTime()";
std::string logtime = std::string(dateBuffer);
logtime += " ";
logtime += std::string(buffer);
char result[200] = {0};
static DWORD first = GetTickCount();
//std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000);
std::sprintf(result, "%s.%03ld", logtime.c_str(), (long)(GetTickCount() - first) % 1000);
return result;
}
#else
#include <sys/time.h>
inline std::string NowTime()
{
char buffer[11];
time_t t;
time(&t);
tm r = {0};
strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
struct timeval tv;
gettimeofday(&tv, 0);
char result[100] = {0};
std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000);
return result;
}
#endif //WIN32
#endif //__LOG_H__
使用時,例子是這樣:
FILE *g_logFile = NULL;
g_logFile = fopen(logFile.c_str(), "a");
if (g_logFile)
Output2FILE::Stream() = g_logFile;
//FILELog().ReportingLevel() = logINFO;
if (g_logFile)
fclose(g_logFile);
日誌預設級別是logINFO
相關文章
- [Java/日誌] 日誌框架列印應用程式日誌程式碼的執行情況Java框架
- 如何實現一個高效的本地日誌收集程式
- 一個完整的go 日誌元件Go元件
- 上一個日誌的錯誤
- 一個簡單的 C# 非同步日誌記錄器C#非同步
- 分享一個收集 Nginx 日誌的 ExporterNginxExport
- 一個刪除重做日誌檔案的參考指令碼指令碼
- 程式中的日誌
- 【知識點】C++的日誌框架C++框架
- php日誌,記錄日誌PHP
- 寫給開發者:記錄日誌的10個建議
- 【教程】一個比較良心的C++程式碼混淆器C++
- [awstats]一個基於perl的日誌分析工具
- 檢視pod下面某一個容器的日誌
- 一個 JSer 的 Dart 學習日誌(四):非同步程式設計JSDart非同步程式設計
- 從一個埋點日誌上報指令碼說起指令碼
- 一個 JSer 的 Dart 學習日誌(六):寫一個向量JSDart
- Praat 學習日誌2--第一個指令碼程式,輸出“hello world!”指令碼
- Python多程式記錄日誌Python
- 我的管理日誌【一】
- 一個 JSer 的 Dart 學習日誌(一):函式JSDart函式
- 觸發LGWR程式寫日誌的4個條件
- 記錄一則clear重做日誌檔案的案例
- 一個不懂營銷的程式設計師的一週營銷日記程式設計師
- C/C++—— 一個特別奇怪的C++程式C++
- C++的一個簡單的控制程式碼類别範本C++
- oracle日誌分析從列表中移去一個日誌檔案Oracle
- kafka-log日誌程式碼解析Kafka
- 如何在程式碼中打日誌
- 壓縮SQL SERVER日誌程式碼SQLServer
- 一個 JSer 的 Dart 學習日誌(三):類JSDart
- 一個用python寫的自動監控alert日誌告警資訊的小程式Python
- 使用 .NET Core 的日誌記錄
- 一個C++程式設計師的Delphi學習筆記 (轉)C++程式設計師筆記
- PHP慢指令碼日誌和Mysql的慢查詢日誌PHP指令碼MySql
- demo演示如何寫一個無配置格式統一的日誌
- 架構師日記-如何寫的一手好程式碼架構
- 日誌模組(一標頭檔案就實現了日誌記錄)