00001 #ifndef __LOG_H__
00002 #define __LOG_H__
00003
00004 #include <sstream>
00005 #include <string>
00006 #include <stdio.h>
00007 #include <iostream>
00008
00009
00010 #define ERROR "ERROR"
00011 #define WARNING "WARNING"
00012 #define INFO "INFO"
00013 #define DEBUG "DEBUG"
00014 #define DEBUG1 "DEBUG1"
00015
00016
00017 inline std::string NowTime();
00018
00019 enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG1, logDEBUG};
00020
00021 template <typename T>
00022 class Log
00023 {
00024 public:
00025 Log();
00026 virtual ~Log();
00027 std::ostringstream& Get(TLogLevel level = logINFO);
00028 public:
00029 static TLogLevel& ReportingLevel();
00030 static std::string ToString(TLogLevel level);
00031 static TLogLevel FromString(const std::string& level);
00032 protected:
00033 std::ostringstream os;
00034 private:
00035 Log(const Log&);
00036 Log& operator =(const Log&);
00037 };
00038
00039 template <typename T>
00040 Log<T>::Log()
00041 {
00042 }
00043
00044 template <typename T>
00045 std::ostringstream& Log<T>::Get(TLogLevel level)
00046 {
00047
00048 os << " " << ToString(level) << ": ";
00049 os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
00050 return os;
00051 }
00052
00053 template <typename T>
00054 Log<T>::~Log()
00055 {
00056
00057 T::Output(os.str());
00058 }
00059
00060 template <typename T>
00061 TLogLevel& Log<T>::ReportingLevel()
00062 {
00063 static TLogLevel reportingLevel = logDEBUG;
00064 return reportingLevel;
00065 }
00066
00067 template <typename T>
00068 std::string Log<T>::ToString(TLogLevel level)
00069 {
00070 static const char* const buffer[] = {ERROR, WARNING, INFO, DEBUG1, DEBUG};
00071 return buffer[level];
00072 }
00073
00074 template <typename T>
00075 TLogLevel Log<T>::FromString(const std::string& level)
00076 {
00077 if (level == "DEBUG1")
00078 return logDEBUG1;
00079 if (level == "DEBUG")
00080 return logDEBUG;
00081 if (level == "INFO")
00082 return logINFO;
00083 if (level == "WARNING")
00084 return logWARNING;
00085 if (level == "ERROR")
00086 return logERROR;
00087 Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default.";
00088 return logINFO;
00089 }
00090
00091 class Output2FILE
00092 {
00093 public:
00094 static FILE*& Stream();
00095 static void Output(const std::string& msg);
00096 };
00097
00098 inline FILE*& Output2FILE::Stream()
00099 {
00100
00101 static FILE* pStream = stdout;
00102 return pStream;
00103 }
00104
00105 inline void Output2FILE::Output(const std::string& msg)
00106 {
00107 FILE* pStream = Stream();
00108 if (!pStream)
00109 return;
00110 fprintf(pStream, "%s", msg.c_str());
00111 fflush(pStream);
00112 }
00113
00114 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
00115 # if defined (BUILDING_FILELOG_DLL)
00116 # define FILELOG_DECLSPEC __declspec (dllexport)
00117 # elif defined (USING_FILELOG_DLL)
00118 # define FILELOG_DECLSPEC __declspec (dllimport)
00119 # else
00120 # define FILELOG_DECLSPEC
00121 # endif // BUILDING_DBSIMPLE_DLL
00122 #else
00123 # define FILELOG_DECLSPEC
00124 #endif // _WIN32
00125
00126 class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {};
00127
00128
00129 #ifndef FILELOG_MAX_LEVEL
00130 #define FILELOG_MAX_LEVEL logDEBUG
00131 #endif
00132
00133 #define FILE_LOG(level) \
00134 if (level > FILELOG_MAX_LEVEL) ;\
00135 else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
00136 else FILELog().Get(level)
00137
00138 #include <sys/time.h>
00139
00140 inline std::string NowTime()
00141 {
00142 char buffer[11];
00143 time_t t;
00144 time(&t);
00145 tm r = {0};
00146 strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
00147 struct timeval tv;
00148 gettimeofday(&tv, 0);
00149 char result[100] = {0};
00150 std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000);
00151 return result;
00152 }
00153
00154
00155 #endif //__LOG_H__