00001
00002 #ifndef __LOG_H__
00003 #define __LOG_H__
00004
00005 #include <sstream>
00006 #include <string>
00007 #include <stdio.h>
00008 #include <iostream>
00009
00010
00011 #define LOG_ERROR "ERROR"
00012 #define WARNING "WARNING"
00013 #define INFO "INFO"
00014 #define DEBUG "DEBUG"
00015 #define DEBUG1 "DEBUG1"
00016
00017
00018 inline std::string NowTime();
00019
00020 enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1};
00021
00022 template <typename T>
00023 class Log {
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 > logDEBUG1 ? level - logDEBUG1 : 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 = logINFO;
00064 return reportingLevel;
00065 }
00066
00067 template <typename T>
00068 std::string Log<T>::ToString(TLogLevel level)
00069 {
00070 static const char* const buffer[] = {LOG_ERROR, WARNING, INFO, DEBUG, DEBUG1};
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 public:
00093 static FILE*& Stream();
00094 static void Output(const std::string& msg);
00095 };
00096
00097 inline FILE*& Output2FILE::Stream()
00098 {
00099
00100 static FILE* pStream = stdout;
00101 return pStream;
00102 }
00103
00104 inline void Output2FILE::Output(const std::string& msg)
00105 {
00106 FILE* pStream = Stream();
00107 if (!pStream)
00108 return;
00109 fprintf(pStream, "%s", msg.c_str());
00110 fflush(pStream);
00111 }
00112
00113 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
00114 # if defined (BUILDING_FILELOG_DLL)
00115 # define FILELOG_DECLSPEC __declspec (dllexport)
00116 # elif defined (USING_FILELOG_DLL)
00117 # define FILELOG_DECLSPEC __declspec (dllimport)
00118 # else
00119 # define FILELOG_DECLSPEC
00120 # endif // BUILDING_DBSIMPLE_DLL
00121 #else
00122 # define FILELOG_DECLSPEC
00123 #endif // _WIN32
00124
00125 class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {};
00126
00127
00128 #ifndef FILELOG_MAX_LEVEL
00129 #define FILELOG_MAX_LEVEL logDEBUG1
00130 #endif
00131
00132 #define FILE_LOG(level) \
00133 if (level > FILELOG_MAX_LEVEL) ;\
00134 else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
00135 else FILELog().Get(level)
00136
00137 #include <sys/time.h>
00138
00139 inline std::string NowTime()
00140 {
00141 char buffer[11];
00142 time_t t;
00143 time(&t);
00144 tm r = {0};
00145 strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
00146 struct timeval tv;
00147 gettimeofday(&tv, 0);
00148 char result[100] = {0};
00149 sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000);
00150 return result;
00151 }
00152
00153
00154 #endif //__LOG_H__