/* * ZoneMinder Logger Interface, $Date$, $Revision$ * Copyright (C) 2001-2008 Philip Coombes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef ZM_LOGGER_H #define ZM_LOGGER_H #include "zm_config.h" #include #include #include #include #ifdef HAVE_SYS_SYSCALL_H #include #endif // HAVE_SYS_SYSCALL_H #include #include "zm_thread.h" class Logger { public: enum { NOOPT=-6, NOLOG, PANIC, FATAL, ERROR, WARNING, INFO, DEBUG1, DEBUG2, DEBUG3, DEBUG4, DEBUG5, DEBUG6, DEBUG7, DEBUG8, DEBUG9 }; typedef int Level; typedef std::map StringMap; typedef std::map IntMap; class Options { public: int mTerminalLevel; int mDatabaseLevel; int mFileLevel; int mSyslogLevel; std::string mLogPath; std::string mLogFile; public: Options( Level terminalLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) : mTerminalLevel( terminalLevel ), mDatabaseLevel( databaseLevel ), mFileLevel( fileLevel ), mSyslogLevel( syslogLevel ), mLogPath( logPath ), mLogFile( logFile ) { } }; private: static bool smInitialised; static Logger *smInstance; RecursiveMutex log_mutex; static StringMap smCodes; static IntMap smSyslogPriorities; private: bool mInitialised; std::string mId; std::string mIdRoot; std::string mIdArgs; Level mLevel; // Level that is currently in operation Level mTerminalLevel; // Maximum level output via terminal Level mDatabaseLevel; // Maximum level output via database Level mFileLevel; // Maximum level output via file Level mSyslogLevel; // Maximum level output via syslog Level mEffectiveLevel; // Level optimised to take account of maxima bool mDbConnected; std::string mLogPath; std::string mLogFile; FILE *mLogFileFP; bool mHasTerminal; bool mFlush; private: static void usrHandler(int sig); public: friend void logInit(const char *name, const Options &options); friend void logTerm(); static Logger *fetch() { if ( !smInstance ) { smInstance = new Logger(); Options options; smInstance->initialise( "undef", options ); } return smInstance; } private: Logger(); ~Logger(); public: void initialise(const std::string &id, const Options &options); void terminate(); private: int limit(int level) { if ( level > DEBUG9 ) return DEBUG9; if ( level < NOLOG ) return NOLOG; return level; } bool boolEnv(const std::string &name, bool defaultValue=false); int intEnv(const std::string &name, bool defaultValue=0); std::string strEnv(const std::string &name, const std::string &defaultValue=""); char *getTargettedEnv(const std::string &name); void loadEnv(); public: const std::string &id() const { return mId; } const std::string &id(const std::string &id); Level level() const { return mLevel; } Level level(Level=NOOPT); bool debugOn() { return mEffectiveLevel >= DEBUG1; } Level terminalLevel(Level=NOOPT); Level databaseLevel(Level=NOOPT); Level fileLevel(Level=NOOPT); Level syslogLevel(Level=NOOPT); private: void logFile(const std::string &logFile); void openFile(); void closeFile(); void openSyslog(); void closeSyslog(); void closeDatabase(); public: void logPrint(bool hex, const char * const filepath, const int line, const int level, const char *fstring, ...); }; void logInit(const char *name, const Logger::Options &options=Logger::Options()); void logTerm(); inline const std::string &logId() { return Logger::fetch()->id(); } inline Logger::Level logLevel() { return Logger::fetch()->level(); } inline Logger::Level logDebugging() { return Logger::fetch()->debugOn(); } #define logPrintf(logLevel,params...) {\ if ( logLevel <= Logger::fetch()->level() )\ Logger::fetch()->logPrint( false, __FILE__, __LINE__, logLevel, ##params );\ } #define logHexdump(logLevel,data,len) {\ if ( logLevel <= Logger::fetch()->level() )\ Logger::fetch()->logPrint( true, __FILE__, __LINE__, logLevel, "%p (%d)", data, len );\ } /* Debug compiled out */ #ifndef DBG_OFF #define Debug(level,params...) logPrintf(level,##params) #define Hexdump(level,data,len) logHexdump(level,data,len) #else #define Debug(level,params...) #define Hexdump(level,data,len) #endif /* Standard debug calls */ #define Info(params...) logPrintf(Logger::INFO,##params) #define Warning(params...) logPrintf(Logger::WARNING,##params) #define Error(params...) logPrintf(Logger::ERROR,##params) #define Fatal(params...) logPrintf(Logger::FATAL,##params) #define Panic(params...) logPrintf(Logger::PANIC,##params) #define Mark() Info("Mark/%s/%d",__FILE__,__LINE__) #define Log() Info("Log") #ifdef __GNUC__ #define Enter(level) logPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) #define Exit(level) logPrintf(level,("Exiting %s",__PRETTY_FUNCTION__)) #else #define Enter(level) #define Exit(level) #endif #endif // ZM_LOGGER_H