C++で簡単なロガーを考えてみた
コードを見ればわかるはず
#include <stdarg.h> #include <string> #include <sstream> #include <fstream> class LogLevel { public: enum type { Info= 1, Debug, Warn, Error, }; static std::string ToString(LogLevel::type logLevel) { switch (logLevel) { case LogLevel::Info: return "INFO "; case LogLevel::Debug: return "DEBUG"; case LogLevel::Warn: return "WARN "; case LogLevel::Error: return "ERROR"; default: return "UNKNOWN"; } } }; class Logger { private: LogLevel::type m_tatgetLogLevel; std::string m_logFilePath; public: static Logger* GetInstance() { static Logger instance; return &instance; } // 出力したいログレベルを設定します void SetLogLevel(const LogLevel::type& logLevel) { this->m_tatgetLogLevel = logLevel; } // 出力したいログファイルを設定します void SetLogFilePath(const char* logFilePath) { this->m_logFilePath = logFilePath; } void Write(const LogLevel::type& logLevel, const char* fileName, const char* funcName, const int lineNum, const char* format, ...) { char message[512] = { 0 }; va_list args; va_start(args, format); #ifdef _WIN32 vsprintf_s(message, format, args); #else vsprintf(message, format, args); #endif this->write(logLevel, fileName, funcName, lineNum, message); va_end(args); } void Info(const char* const fileName, const char* const funcName, const int lineNum, const char* message) const { this->write(LogLevel::Info, fileName, funcName, lineNum, message); } void Debug(const char* const fileName, const char* const funcName, const int lineNum, const char* message) const { this->write(LogLevel::Debug, fileName, funcName, lineNum, message); } void Warn(const char* const fileName, const char* const funcName, const int lineNum, const char* message) const { this->write(LogLevel::Warn, fileName, funcName, lineNum, message); } void Error(const char* const fileName, const char* const funcName, const int lineNum, const char* message) const { this->write(LogLevel::Error, fileName, funcName, lineNum, message); } private: // Logger() : m_tatgetLogLevel(LogLevel::Info) { // ログファイル名を決めましょう this->m_logFilePath = "C:\\testlog.log"; } void write(const LogLevel::type& logLevel, const char* fileName, const char* funcName, const int lineNum, const char* message) const { if (!this->isEnabled(logLevel)) return; // ログを出力する処理 std::ofstream ofs; ofs.open(this->m_logFilePath, std::ios::app); ofs << this->getDateTimeNow() << " " << "[" << LogLevel::ToString(logLevel) << "]" << "[" << fileName << "]" << "[" << funcName << "]" << "[" << lineNum << "]" << message << std::endl; ofs.close(); } bool isEnabled(const LogLevel::type& logLevel) const { return this->m_tatgetLogLevel <= logLevel; } std::string getDateTimeNow() const { std::ostringstream oss; // 時刻を整形する処理 return oss.str(); } }; #define LOG_LEVEL_SET(x) Logger::GetInstance()->SetLogLevel(x); #define LOG_FILE_PATH_SET(x) Logger::GetInstance()->SetLogFilePath(x); #ifdef _WIN32 #define LOG_INFO(format, ...) Logger::GetInstance()->Write(LogLevel::Info, __FILE__, __FUNCTION__, __LINE__, format, __VA_ARGS__); #define LOG_DEBUG(format, ...) Logger::GetInstance()->Write(LogLevel::Debug, __FILE__, __FUNCTION__, __LINE__, format, __VA_ARGS__); #define LOG_WARN(format, ...) Logger::GetInstance()->Write(LogLevel::Warn, __FILE__, __FUNCTION__, __LINE__, format, __VA_ARGS__); #define LOG_ERROR(format, ...) Logger::GetInstance()->Write(LogLevel::Error, __FILE__, __FUNCTION__, __LINE__, format, __VA_ARGS__); #else #define LOG_INFO(format, ...) Logger::GetInstance()->Write(LogLevel::Info, __FILE__, __func__, __LINE__, format, __VA_ARGS__); #define LOG_DEBUG(format, ...) Logger::GetInstance()->Write(LogLevel::Debug, __FILE__, __func__, __LINE__, format, __VA_ARGS__); #define LOG_WARN(format, ...) Logger::GetInstance()->Write(LogLevel::Warn, __FILE__, __func__, __LINE__, format, __VA_ARGS__); #define LOG_ERROR(format, ...) Logger::GetInstance()->Write(LogLevel::Error, __FILE__, __func__, __LINE__, format, __VA_ARGS__); #endif int main(int argc, char* argv[]) { LOG_INFO("info %d, %d--", 1, 2); LOG_DEBUG("debug--"); LOG_WARN("warn %s--", "あいうえお"); LOG_ERROR("error %s %d--", "abcde", 1000); // yyyy/mm/dd hh:mm:ss.000 [INFO ][XXXX\cpploggersample.cpp][main][157]info 1, 2-- // yyyy/mm/dd hh:mm:ss.000 [DEBUG][XXXX\cpploggersample.cpp][main][158]debug-- // yyyy/mm/dd hh:mm:ss.000 [WARN ][XXXX\cpploggersample.cpp][main][159]warn あいうえお-- // yyyy/mm/dd hh:mm:ss.000 [ERROR][XXXX\cpploggersample.cpp][main][160]error abcde 1000-- return 0; }