zoneminder/src/zm_logger.h

247 lines
6.3 KiB
C++

/*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ZM_LOGGER_H
#define ZM_LOGGER_H
#include "zm_config.h"
#include <stdint.h>
#include <unistd.h>
#include <string>
#include <map>
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif // HAVE_SYS_SYSCALL_H
#include <mysql/mysql.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<Level,std::string> StringMap;
typedef std::map<Level,int> IntMap;
class Options
{
public:
int mTermLevel;
int mDatabaseLevel;
int mFileLevel;
int mSyslogLevel;
std::string mLogPath;
std::string mLogFile;
public:
Options( Level termLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) :
mTermLevel( termLevel ),
mDatabaseLevel( databaseLevel ),
mFileLevel( fileLevel ),
mSyslogLevel( syslogLevel ),
mLogPath( logPath ),
mLogFile( logFile )
{
}
};
private:
static bool smInitialised;
static Logger *smInstance;
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 mTermLevel; // 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;
MYSQL mDbConnection;
std::string mLogPath;
std::string mLogFile;
FILE *mLogFileFP;
bool mHasTerm;
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 termLevel( 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 void logCapLevel( Logger::Level level )
{
Logger::fetch()->level( 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