#pragma once #include <sstream> class Logger { public: enum LogLevel { TRACE, DEBUG, INFO, WARN, ERROR, FATAL, LOGLEVEL_COUNT }; Logger(const char *file, int line); Logger(const char *file, int line, LogLevel level); Logger(const char *file, int line, bool isAbort); ~Logger(); static void setHandle(FILE* fd); static void setLevel(LogLevel level); static LogLevel level(); std::ostream& stream(); private: void initMsgHead(const char *file, int line, LogLevel level = TRACE); private: LogLevel level_; FILE* fd_; std::ostringstream stream_; static LogLevel s_level_; static FILE* s_fd_; }; #define LOG_TRACE if (Logger::level() <= Logger::TRACE) \ Logger(__FILE__, __LINE__, Logger::TRACE).stream() #define LOG_DEBUG if (Logger::level() <= Logger::DEBUG) \ Logger(__FILE__, __LINE__, Logger::DEBUG).stream() #define LOG_INFO if (Logger::level() <= Logger::INFO) \ Logger(__FILE__, __LINE__, Logger::INFO).stream() #define LOG_WARN if (Logger::level() <= Logger::WARN) \ Logger(__FILE__, __LINE__, Logger::WARN).stream() #define LOG_ERROR Logger(__FILE__, __LINE__, Logger::ERROR).stream() #define LOG_FATAL Logger(__FILE__, __LINE__, Logger::FATAL).stream()
#include "stdafx.h" #include "Logger.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sstream> #include <assert.h> Logger::LogLevel Logger::s_level_ = Logger::TRACE; FILE* Logger::s_fd_ = NULL; Logger::Logger(const char *file, int line) { initMsgHead(file, line); } Logger::Logger(const char *file, int line, LogLevel level) { initMsgHead(file, line, level); } Logger::Logger(const char *file, int line, bool isAbort) { LogLevel level = (isAbort?FATAL:ERROR); initMsgHead(file, line, level); } Logger::~Logger() { if (s_fd_) { stream_ << std::endl; std::string buf(stream_.str()); fwrite(buf.data(), sizeof(char), buf.size(), s_fd_); if (level_ == FATAL) { abort(); } } } void Logger::setHandle(FILE* fd) { s_fd_ = fd; } void Logger::setLevel(LogLevel level) { s_level_ = level; } Logger::LogLevel Logger::level() { return s_level_; } std::ostream& Logger::stream() { return stream_; } void Logger::initMsgHead(const char *file, int line, LogLevel level) { const char *logLevel[LOGLEVEL_COUNT] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; char msgHead[256] = {0}; time_t curtime = time(NULL); struct tm curtm; localtime_s(&curtm, &curtime); const char *pstr = strrchr(file, '\\'); const char *name = ((pstr!=NULL) ? pstr+1 : file); level_ = level; sprintf_s(msgHead, sizeof(msgHead), "%04d-%02d-%02d %02d:%02d:%02d[%s:%04d][%s] - ", curtm.tm_year+1900, curtm.tm_mon+1, curtm.tm_mday, curtm.tm_hour, curtm.tm_min, curtm.tm_sec, name, line, logLevel[level_]); stream_ << msgHead; }
#include "Logger.h" int _tmain(int argc, _TCHAR* argv[]) { FILE *fd = NULL; if (0 != fopen_s(&fd, "log.txt", "a+")) { printf("open error\n"); } Logger::setHandle(fd); Logger::setLevel(Logger::WARN); for (int i=0; i<2000; i++) { LOG_TRACE << "this is trace"; LOG_WARN << "this is warning"; LOG_ERROR << "this is error" << ", number:" << i+1; LOG_WARN << "this is last"; } LOG_ERROR << "endline" << std::endl; fclose(fd); system("pause"); return 0; }