/* * vim: ts=4 sw=4 et tw=0 wm=0 * * libcola - A library providing force-directed network layout using the * stress-majorization method subject to separation constraints. * * Copyright (C) 2006-2008 Monash University * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * See the file LICENSE.LGPL distributed with the library. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ /* Logging code from DJJ article: http://www.ddj.com/cpp/201804215. Title: Logging In C++ Author: Petru Marginean Keywords: OCT07 C++ Description: Unpublished source code accompanying the article by Petru Marginean, in which he presents a C++ logging framework that is typesafe, thread-safe, and portable. */ #ifndef __COLA_LOG_H__ #define __COLA_LOG_H__ #include #include #include #include namespace cola { inline std::string NowTime(); enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4}; template 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 Log::Log() { } template std::ostringstream& Log::Get(TLogLevel level) { os << "- " << NowTime(); os << " " << ToString(level) << ": "; os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); return os; } template Log::~Log() { os << std::endl; T::Output(os.str()); } template TLogLevel& Log::ReportingLevel() { static TLogLevel reportingLevel = cola::logDEBUG4; return reportingLevel; } template std::string Log::ToString(TLogLevel level) { static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"}; return buffer[level]; } template TLogLevel Log::FromString(const std::string& level) { if (level == "DEBUG4") return logDEBUG4; if (level == "DEBUG3") return logDEBUG3; if (level == "DEBUG2") return logDEBUG2; if (level == "DEBUG1") return logDEBUG1; if (level == "DEBUG") return logDEBUG; if (level == "INFO") return logINFO; if (level == "WARNING") return logWARNING; if (level == "ERROR") return logERROR; Log().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 {}; //typedef Log FILELog; #ifndef FILELOG_MAX_LEVEL #define FILELOG_MAX_LEVEL cola::logDEBUG4 #endif #define FILE_LOG(level) \ if (level > FILELOG_MAX_LEVEL) ;\ else if (level > cola::FILELog::ReportingLevel() || !cola::Output2FILE::Stream()) ; \ else cola::FILELog().Get(level) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) #include inline std::string NowTime() { const int MAX_LEN = 200; char buffer[MAX_LEN]; if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, "HH':'mm':'ss", buffer, MAX_LEN) == 0) return "Error in NowTime()"; static DWORD first = GetTickCount(); std::stringstream result; result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)(GetTickCount() - first) % 1000); return result.str(); } #else #include inline std::string NowTime() { char buffer[11]; time_t t; time(&t); tm r; strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r)); struct timeval tv; gettimeofday(&tv, 0); std::stringstream result; result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)tv.tv_usec / 1000); return result.str(); } #endif //WIN32 } // namespace cola #endif //__COLA_LOG_H__