2008-01-17 12:02:22 +00:00
/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*
2010-01-11 03:07:32 +00:00
* InspIRCd : ( C ) 2002 - 2010 InspIRCd Development Team
2009-03-15 12:42:35 +00:00
* See : http : //wiki.inspircd.org/Credits
2008-01-17 12:02:22 +00:00
*
* This program is free but copyrighted software ; see
* the file COPYING for details .
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2012-04-14 18:03:25 -07:00
# ifndef LOGMANAGER_H
# define LOGMANAGER_H
2008-02-09 11:35:27 +00:00
2008-02-10 20:07:30 +00:00
/** This class implements a nonblocking writer.
* Most people writing an ircd give little thought to their disk
* i / o . On a congested system , disk writes can block for long
* periods of time ( e . g . if the system is busy and / or swapping
* a lot ) . If we just use a blocking fprintf ( ) call , this could
* block for undesirable amounts of time ( half of a second through
* to whole seconds ) . We DO NOT want this , so we make our logfile
* nonblocking and hook it into the SocketEngine .
* NB : If the operating system does not support nonblocking file
* I / O ( linux seems to , as does freebsd ) this will default to
* blocking behaviour .
*/
2009-10-20 04:40:18 +00:00
class CoreExport FileWriter
2008-02-10 20:07:30 +00:00
{
protected :
/** The log file (fd is inside this somewhere,
* we get it out with fileno ( ) )
*/
FILE * log ;
2008-02-17 14:37:34 +00:00
2008-02-10 20:07:30 +00:00
/** Number of write operations that have occured
*/
int writeops ;
2008-02-17 14:37:34 +00:00
2008-02-10 20:07:30 +00:00
public :
/** The constructor takes an already opened logfile.
*/
2009-09-26 14:13:13 +00:00
FileWriter ( FILE * logfile ) ;
2008-02-17 14:37:34 +00:00
2008-02-10 20:07:30 +00:00
/** Write one or more preformatted log lines.
* If the data cannot be written immediately ,
* this class will insert itself into the
* SocketEngine , and register a write event ,
* and when the write event occurs it will
* attempt again to write the data .
*/
void WriteLogLine ( const std : : string & line ) ;
2008-02-17 14:37:34 +00:00
2008-02-10 20:07:30 +00:00
/** Close the log file and cancel any events.
*/
virtual ~ FileWriter ( ) ;
} ;
2008-02-17 14:37:34 +00:00
/*
* New world logging !
* The brief summary :
* Logging used to be a simple affair , a FILE * handled by a nonblocking logging class inheriting from EventHandler , that was inserted
* into the socket engine , and wrote lines . If nofork was on , it was printf ( ) ' d .
*
* We decided to horribly overcomplicate matters , and create vastly customisable logging . LogManager and LogStream form the visible basis
* of the new interface . Basically , a LogStream can be inherited to do different things with logging output . We inherit from it once in core
* to create a FileLogStream , that writes to a file , for example . Different LogStreams can hook different types of log messages , and different
* levels of output too , for extreme customisation . Multiple LogStreams can hook the same message / levels of output , meaning that e . g . output
* can go to a channel as well as a file .
*
* HOW THIS WORKS
2008-02-17 19:09:03 +00:00
* LogManager handles all instances of LogStreams , classes derived from LogStream are instantiated and passed to it .
2008-02-17 14:37:34 +00:00
*/
/** LogStream base class. Modules (and other stuff) inherit from this to decide what logging they are interested in, and what to do with it.
*/
2008-02-09 11:35:27 +00:00
class CoreExport LogStream : public classbase
{
2008-02-09 12:41:17 +00:00
protected :
2008-02-10 14:20:58 +00:00
int loglvl ;
2008-02-09 11:35:27 +00:00
public :
2009-09-26 14:13:13 +00:00
LogStream ( int loglevel ) : loglvl ( loglevel )
2008-02-09 11:35:27 +00:00
{
}
2008-02-17 19:09:03 +00:00
/* A LogStream's destructor should do whatever it needs to close any resources it was using (or indicate that it is no longer using a resource
* in the event that the resource is shared , see for example FileLogStream ) .
*/
2008-02-10 20:07:30 +00:00
virtual ~ LogStream ( ) { }
2008-02-17 19:09:03 +00:00
/** Changes the loglevel for this LogStream on-the-fly.
* This is needed for - nofork . But other LogStreams could use it to change loglevels .
2008-02-17 14:37:34 +00:00
*/
void ChangeLevel ( int lvl ) { this - > loglvl = lvl ; }
2008-02-15 13:30:46 +00:00
2008-02-17 14:37:34 +00:00
/** Called when there is stuff to log for this particular logstream. The derived class may take no action with it, or do what it
* wants with the output , basically . loglevel and type are primarily for informational purposes ( the level and type of the event triggered )
* and msg is , of course , the actual message to log .
*/
2008-02-14 00:43:48 +00:00
virtual void OnLog ( int loglevel , const std : : string & type , const std : : string & msg ) = 0 ;
2008-02-09 11:35:27 +00:00
} ;
2008-02-10 20:07:30 +00:00
typedef std : : map < FileWriter * , int > FileLogMap ;
2009-10-18 16:18:44 +00:00
class CoreExport LogManager
2008-02-09 11:35:27 +00:00
{
private :
2008-02-17 19:09:03 +00:00
/** Lock variable, set to true when a log is in progress, which prevents further loggging from happening and creating a loop.
*/
bool Logging ;
/** Map of active log types and what LogStreams will receive them.
*/
2008-02-09 11:35:27 +00:00
std : : map < std : : string , std : : vector < LogStream * > > LogStreams ;
2008-02-17 19:09:03 +00:00
/** Refcount map of all LogStreams managed by LogManager.
* If a logstream is not listed here , it won ' t be automatically closed by LogManager , even if it ' s loaded in one of the other lists .
*/
std : : map < LogStream * , int > AllLogStreams ;
/** LogStreams with type * (which means everything), and a list a logtypes they are excluded from (eg for "* -USERINPUT -USEROUTPUT").
*/
std : : map < LogStream * , std : : vector < std : : string > > GlobalLogStreams ;
/** Refcounted map of all FileWriters in use by FileLogStreams, for file stream sharing.
*/
FileLogMap FileLogs ;
2008-02-09 11:35:27 +00:00
public :
2008-02-17 19:09:03 +00:00
2009-10-19 04:09:30 +00:00
LogManager ( ) ;
~ LogManager ( ) ;
2009-09-02 00:46:44 +00:00
2008-02-17 19:09:03 +00:00
/** Adds a FileWriter instance to LogManager, or increments the reference count of an existing instance.
* Used for file - stream sharing for FileLogStreams .
*/
2008-02-10 20:07:30 +00:00
void AddLoggerRef ( FileWriter * fw )
{
FileLogMap : : iterator i = FileLogs . find ( fw ) ;
if ( i = = FileLogs . end ( ) )
{
FileLogs . insert ( std : : make_pair ( fw , 1 ) ) ;
}
else
{
+ + i - > second ;
}
}
2008-02-17 19:09:03 +00:00
/** Indicates that a FileWriter reference has been removed. Reference count is decreased, and if zeroed, the FileWriter is closed.
*/
2008-02-10 20:07:30 +00:00
void DelLoggerRef ( FileWriter * fw )
{
FileLogMap : : iterator i = FileLogs . find ( fw ) ;
if ( i = = FileLogs . end ( ) ) return ; /* Maybe should log this? */
if ( - - i - > second < 1 )
{
delete i - > first ;
FileLogs . erase ( i ) ;
}
}
2008-02-17 19:09:03 +00:00
/** Opens all logfiles defined in the configuration file using <log method="file">.
*/
2008-02-10 20:07:30 +00:00
void OpenFileLogs ( ) ;
2008-02-17 19:09:03 +00:00
/** Removes all LogStreams, meaning they have to be readded for logging to continue.
* Only LogStreams that were listed in AllLogStreams are actually closed .
2008-02-17 14:37:34 +00:00
*/
2008-02-09 20:15:09 +00:00
void CloseLogs ( ) ;
2008-02-17 19:09:03 +00:00
/** Adds a single LogStream to multiple logtypes.
* This automatically handles things like " * -USERINPUT -USEROUTPUT " to mean all but USERINPUT and USEROUTPUT types .
* It is not a good idea to mix values of autoclose for the same LogStream .
* @ param type The type string ( from configuration , or whatever ) to parse .
* @ param l The LogStream to add .
* @ param autoclose True to have the LogStream automatically closed when all references to it are removed from LogManager . False to leave it open .
*/
void AddLogTypes ( const std : : string & type , LogStream * l , bool autoclose ) ;
2008-02-17 14:37:34 +00:00
/** Registers a new logstream into the logging core, so it can be called for future events
2008-02-17 19:09:03 +00:00
* It is not a good idea to mix values of autoclose for the same LogStream .
* @ param type The type to add this LogStream to .
* @ param l The LogStream to add .
* @ param autoclose True to have the LogStream automatically closed when all references to it are removed from LogManager . False to leave it open .
* @ return True if the LogStream was added successfully , False otherwise .
2008-02-17 14:37:34 +00:00
*/
2008-02-15 13:30:46 +00:00
bool AddLogType ( const std : : string & type , LogStream * l , bool autoclose ) ;
2008-02-17 19:09:03 +00:00
2008-02-17 14:37:34 +00:00
/** Removes a logstream from the core. After removal, it will not recieve further events.
2008-02-17 19:09:03 +00:00
* If the LogStream was ever added with autoclose , it will be closed after this call ( this means the pointer won ' t be valid anymore ) .
2008-02-17 14:37:34 +00:00
*/
2008-02-14 00:43:48 +00:00
void DelLogStream ( LogStream * l ) ;
2008-02-17 19:09:03 +00:00
/** Removes a LogStream from a single type. If the LogStream has been registered for "*" it will still receive the type unless you remove it from "*" specifically.
* If the LogStream was added with autoclose set to true , then when the last occurrence of the stream is removed it will automatically be closed ( freed ) .
*/
2008-02-09 11:35:27 +00:00
bool DelLogType ( const std : : string & type , LogStream * l ) ;
2008-02-17 19:09:03 +00:00
/** Logs an event, sending it to all LogStreams registered for the type.
* @ param type Log message type ( ex : " USERINPUT " , " MODULE " , . . . )
* @ param loglevel Log message level ( DEBUG , VERBOSE , DEFAULT , SPARSE , NONE )
* @ param msg The message to be logged ( literal ) .
2008-02-17 14:37:34 +00:00
*/
2008-02-09 11:35:27 +00:00
void Log ( const std : : string & type , int loglevel , const std : : string & msg ) ;
2008-02-17 19:09:03 +00:00
/** Logs an event, sending it to all LogStreams registered for the type.
* @ param type Log message type ( ex : " USERINPUT " , " MODULE " , . . . )
* @ param loglevel Log message level ( DEBUG , VERBOSE , DEFAULT , SPARSE , NONE )
* @ param msg The format of the message to be logged . See your C manual on printf ( ) for details .
2008-02-17 14:37:34 +00:00
*/
2008-03-30 02:48:54 +00:00
void Log ( const std : : string & type , int loglevel , const char * fmt , . . . ) CUSTOM_PRINTF ( 4 , 5 ) ;
2008-02-09 11:35:27 +00:00
} ;
# endif