?? logger.h
字號:
#ifndef __GradSoft_Logger_h#define __GradSoft_Logger_h/* * part of GradSoft C++ ToolBox: Logger * (C) GradSoft, Kiev, Ukraine 2000, 2001 * http://www.gradsoft.com.ua * author: Ruslan Shevchenko <Ruslan@Shevchenko.Kiev.UA>, 2000 * $Id: Logger.h,v 1.20 2002/01/17 11:05:59 yad Exp $ */#include <GradSoft/LoggerPostConfig.h>#include <GradSoft/Threading.h>#include <cstddef>#include <string>#include <strstream>#include <fstream>#include <iostream>/** * **/namespace GradSoft { /** * Types of log events: * Debug, Info, Warning, Error, Fatal **/ enum LogEventType { /// Debug=0, /// Info=1, /// Warning=2, /// Error=3, /// Fatal=4 }; struct DebugLogEventStruct { static const LogEventType tag; }; struct InfoLogEventStruct { static const LogEventType tag; }; struct WarningLogEventStruct { static const LogEventType tag; }; struct ErrorLogEventStruct { static const LogEventType tag; }; struct FatalLogEventStruct { static const LogEventType tag; }; template<class EventType, bool enabled> class LogStream;/** * lock guard for logger streams. **/template<class EventType, bool enabled>class LogStreamLocker{ Mutex* mutex_p_;public: /** * lock logStream to current thread **/ LogStreamLocker(LogStream<EventType,enabled>& logStream) { if (enabled) { mutex_p_ = logStream.getMutexPtr(); mutex_p_->lock(); } } /** * unlock logStream **/ ~LogStreamLocker() { if (enabled) mutex_p_->unlock(); }};#ifdef HAVE_PARTIAL_SPECIALIZATIONtemplate<class EventType>class LogStreamLocker<EventType, false>{public: LogStreamLocker(LogStream<EventType,false>&) {} ~LogStreamLocker() {}};template<class EventType>class LogStreamLocker<EventType, true>{private: Mutex* mutex_p_;public: LogStreamLocker(LogStream<EventType,true>& logStream) { mutex_p_ = logStream.getMutexPtr(); mutex_p_->lock(); } ~LogStreamLocker() { mutex_p_->unlock(); }};#endif#ifndef _NDEBUG# ifndef LOG_DEBUG_ENABLE/** Are we want to log debug output ? [true/false] * default: true if _NDEBUG is not defined, otherwise false **/# define LOG_DEBUG_ENABLE false# endif # ifndef LOG_INFO_ENABLE/** Are we want to log info output ? [true/false] * default: true if _NDEBUG is not defined, otherwise false **/# define LOG_INFO_ENABLE true# endif#else# ifndef LOG_DEBUG_ENABLE# define LOG_DEBUG_ENABLE false# endif # ifndef LOG_INFO_ENABLE# define LOG_INFO_ENABLE false# endif#endif#ifndef LOG_WARNING_ENABLE/** Are we want to log warning output ? [true/false] * default: true **/# define LOG_WARNING_ENABLE true#endif#ifndef LOG_ERROR_ENABLE/** Are we want to log error output ? [true/false] * default: true **/# define LOG_ERROR_ENABLE true#endif#ifndef LOG_FATAL_ENABLE/** * Are we want to log fatal error output ? [true/false] * default: true **/# define LOG_FATAL_ENABLE true#endif /** * stream for debug output **/typedef LogStream<DebugLogEventStruct, LOG_DEBUG_ENABLE> DebugLogStream;/** * stream for information output **/typedef LogStream<InfoLogEventStruct, LOG_INFO_ENABLE> InfoLogStream;/** * stream for warning output **/typedef LogStream<WarningLogEventStruct, LOG_WARNING_ENABLE> WarningLogStream;/** * stream for errors output **/typedef LogStream<ErrorLogEventStruct, LOG_ERROR_ENABLE> ErrorLogStream;/** * stream for fatal errors output **/typedef LogStream<FatalLogEventStruct, LOG_FATAL_ENABLE> FatalLogStream;/// /** * Main class for events log **/ class Logger { public: /** * Struct, which indicate input/output exception **/ struct IOException { std::string message_; IOException(const char* message) :message_(message) {} /// const char* what() const { return message_.c_str(); } }; /// Logger(); /// Logger(const char* fname, bool dup_to_stderr=false) throw (IOException); /// ~Logger(); /// void setOutputFile(const char* fname) throw (IOException); /// void setCallback(LogEventType evTag, void (*callback)(const char* msg)); /** * set property: dup output to standart error stream for all streams **/ void setDuppedToStderr(bool x); /** * set output to syslog: if true we log to syslog, if false - no. * by default, output to syslog is enabled. **/ void setSyslogOutput(bool x) { syslogEnabled_ = x; } /// void put_event(LogEventType evTag, const char* value, bool dup_to_stderr = false); /// DebugLogStream& debugs() { return *debugStream_mp_; } /// const DebugLogStream& debugs() const { return *debugStream_mp_; } /// InfoLogStream& infos() { return *infoStream_mp_; } /// const InfoLogStream& infos() const { return *infoStream_mp_; } /// WarningLogStream& warnings() { return *warningStream_mp_; } /// const WarningLogStream& warnings() const { return *warningStream_mp_; } /// ErrorLogStream& errors() { return *errorStream_mp_; } /// const ErrorLogStream& errors() const { return *errorStream_mp_; } /// FatalLogStream& fatals() { return *fatalStream_mp_; } /// const FatalLogStream& fatals() const { return *fatalStream_mp_; } /// static const char* getStringEventType(LogEventType ev); /** * type for Debug LogStream lock guard. **/ typedef LogStreamLocker<DebugLogEventStruct,LOG_DEBUG_ENABLE> DebugLocker; /** * type for Info LogStream lock guard. **/ typedef LogStreamLocker<InfoLogEventStruct, LOG_INFO_ENABLE> InfoLocker; /** * type for Warnings LogStream lock guard. **/ typedef LogStreamLocker<WarningLogEventStruct,LOG_WARNING_ENABLE> WarningLocker; /** * type for Errors LogStream lock guard. **/ typedef LogStreamLocker<ErrorLogEventStruct,LOG_ERROR_ENABLE> ErrorLocker; /** * type for Fatals LogStream lock guard **/ typedef LogStreamLocker<FatalLogEventStruct,LOG_FATAL_ENABLE> FatalLocker; private: void (*callbacks_[5])(const char* msg); char* fname_; std::ofstream ofs_; bool syslogEnabled_; DebugLogStream* debugStream_mp_; InfoLogStream* infoStream_mp_; WarningLogStream* warningStream_mp_; ErrorLogStream* errorStream_mp_; FatalLogStream* fatalStream_mp_; Mutex mutex_; private: void init(bool dup_to_stderr=false); private: Logger(const Logger&); Logger& operator=(const Logger&); }; struct LogStreamBase; class LogStreamBuff: public std::streambuf { private: Logger& logger_; bool duppedToStderr_; LogEventType tag_; bool enabled_; std::ostrstream ostr_; bool touched_; public: LogStreamBuff(Logger& logger, LogEventType tag, bool enabled, bool duppedToStderr); ~LogStreamBuff() { sync(); } protected: friend LogStreamBase; std::streamsize xsputn(const char* str, std::streamsize size); int overflow(int c); int sync(); bool isDuppedToStderr() const { return duppedToStderr_; } void setDuppedToStderr(bool x) { duppedToStderr_ = x; } private: LogStreamBuff(); LogStreamBuff(const LogStreamBuff&); LogStreamBuff& operator=(const LogStreamBuff&); }; struct LogStreamBase { LogStreamBuff buff_; LogStreamBase(Logger& logger, LogEventType tag, bool enabled, bool duppedToStderr) :buff_(logger,tag,enabled,duppedToStderr) {} void setDuppedToStderr(bool x) { buff_.setDuppedToStderr(x); } bool isDuppedToStderr() const { return buff_.isDuppedToStderr(); } }; using std::ostream; // bug in MSVC templates implementation /** * Stream-like class for output to logger. * Example of usage: * \begin{verbatim} * logStream << "can't open file " << fname << endl; * \end{verbatim} * Stream have 2 compile-time attributes: *\begin{itemize} * \item EventType - type of events, which this stream can receive. * \item enabled - true, if we use output of this stream: *\end{itemize} * operations with LogStream<evt,true> are really logging to stream, * all operations with LogStream<evt,false> do nothing. **/ template<class EventType, bool enabled> class LogStream: private LogStreamBase, public ostream { private: Mutex mutex_; public: // public, as implementation effects: // bug in template friends in C++ compilers. LogStream(Logger& logger, bool duppedToStderr) :LogStreamBase(logger,EventType::tag,enabled, duppedToStderr), ostream(&buff_), mutex_() {} public: /// void setDuppedToStderr(bool x) { LogStreamBase::setDuppedToStderr(x); } /// bool isDuppedToStderr() const { return LogStreamBase::isDuppedToStderr(x); } // public, as implementation effects: // bug in template friends in C++ compilers. Mutex* getMutexPtr() { return &mutex_; } private: LogStream(); LogStream(const LogStream&); LogStream& operator=(const LogStream&); };#if defined(HAVE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)class DummyLogStreamBuff: public std::streambuf{public: DummyLogStreamBuff() {} int xsputn(char const *, int ) { return 0; }; int overflow(int c) { return c; } int sync() { return 0; }};struct DummyLogStreamBase{ DummyLogStreamBuff buff_;};template<class EventType>class LogStream<EventType, false>: private DummyLogStreamBase, public std::ostream{public: LogStream(Logger& logger, bool duppedToStderr) :std::ostream(&buff_) {} void setDuppedToStderr(bool x) {} bool isDuppedToStderr() const { return false; } Mutex* getMutexPtr() { return NULL; }};#endif inlineLogger::Logger(const char* fname, bool dup_to_stderr) throw (Logger::IOException){ // must be defined here, becous it's depend from compile-time settings. // note1: we have no code-bloat, becouse usially only one instance of logger // is situated in program. // note2: all method of logger with touch stream instances must be here. setOutputFile(fname); init(dup_to_stderr);}inlinevoid Logger::init(bool dup_to_stderr){ for(int i=0; i<5; ++i) { callbacks_[i]=NULL; } debugStream_mp_ = new DebugLogStream(*this, dup_to_stderr); infoStream_mp_ = new InfoLogStream(*this, dup_to_stderr); warningStream_mp_ = new WarningLogStream(*this, dup_to_stderr); errorStream_mp_ = new ErrorLogStream(*this, dup_to_stderr); fatalStream_mp_ = new FatalLogStream(*this, dup_to_stderr); syslogEnabled_ = true;}inline Logger::Logger(){ init();}inline Logger::~Logger(){ if (ofs_) ofs_.close(); delete debugStream_mp_; delete infoStream_mp_; delete warningStream_mp_; delete errorStream_mp_; delete fatalStream_mp_;}inlinevoid Logger::setDuppedToStderr(bool x){ MutexLocker ml(mutex_); debugStream_mp_->setDuppedToStderr(x); infoStream_mp_->setDuppedToStderr(x); warningStream_mp_->setDuppedToStderr(x); errorStream_mp_->setDuppedToStderr(x); fatalStream_mp_->setDuppedToStderr(x);}}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -