The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

logger.h

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #ifndef __LOGMANAGER_H
00015 #define __LOGMANAGER_H
00016 
00029 class CoreExport FileWriter : public EventHandler
00030 {
00031  protected:
00034         InspIRCd* ServerInstance;
00035 
00039         FILE* log;
00040 
00043         int writeops;
00044 
00045  public:
00048         FileWriter(InspIRCd* Instance, FILE* logfile);
00049 
00056         virtual void HandleEvent(EventType et, int errornum = 0);
00057 
00065         void WriteLogLine(const std::string &line);
00066 
00069         virtual void Close();
00070 
00074         virtual ~FileWriter();
00075 };
00076 
00077 
00078 
00079 /*
00080  * New world logging!
00081  * The brief summary:
00082  *  Logging used to be a simple affair, a FILE * handled by a nonblocking logging class inheriting from EventHandler, that was inserted
00083  *  into the socket engine, and wrote lines. If nofork was on, it was printf()'d.
00084  *
00085  *  We decided to horribly overcomplicate matters, and create vastly customisable logging. LogManager and LogStream form the visible basis
00086  *  of the new interface. Basically, a LogStream can be inherited to do different things with logging output. We inherit from it once in core
00087  *  to create a FileLogStream, that writes to a file, for example. Different LogStreams can hook different types of log messages, and different
00088  *  levels of output too, for extreme customisation. Multiple LogStreams can hook the same message/levels of output, meaning that e.g. output
00089  *  can go to a channel as well as a file.
00090  *
00091  *  HOW THIS WORKS
00092  *   LogManager handles all instances of LogStreams, classes derived from LogStream are instantiated and passed to it.
00093  */
00094 
00097 class CoreExport LogStream : public classbase
00098 {
00099  protected:
00100         InspIRCd *ServerInstance;
00101         int loglvl;
00102  public:
00103         LogStream(InspIRCd *Instance, int loglevel) : ServerInstance(Instance), loglvl(loglevel)
00104         {
00105         }
00106 
00107         /* 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
00108          * in the event that the resource is shared, see for example FileLogStream).
00109          */
00110         virtual ~LogStream() { }
00111 
00115         void ChangeLevel(int lvl) { this->loglvl = lvl; }
00116 
00121         virtual void OnLog(int loglevel, const std::string &type, const std::string &msg) = 0;
00122 };
00123 
00124 typedef std::map<FileWriter*, int> FileLogMap;
00125 
00126 class CoreExport LogManager : public classbase
00127 {
00128  private:
00131         bool Logging;
00132 
00135         LogStream* noforkstream;
00136 
00137         InspIRCd *ServerInstance;
00138 
00141         std::map<std::string, std::vector<LogStream *> > LogStreams;
00142 
00146         std::map<LogStream *, int> AllLogStreams;
00147 
00150         std::map<LogStream *, std::vector<std::string> > GlobalLogStreams;
00151 
00154         FileLogMap FileLogs;
00155 
00156  public:
00157 
00158         LogManager(InspIRCd *Instance)
00159         {
00160                 noforkstream = NULL;
00161                 ServerInstance = Instance;
00162                 Logging = false;
00163         }
00164 
00169         void SetupNoFork();
00170 
00174         void AddLoggerRef(FileWriter* fw)
00175         {
00176                 FileLogMap::iterator i = FileLogs.find(fw);
00177                 if (i == FileLogs.end())
00178                 {
00179                         FileLogs.insert(std::make_pair(fw, 1));
00180                 }
00181                 else
00182                 {
00183                         ++i->second;
00184                 }
00185         }
00186 
00189         void DelLoggerRef(FileWriter* fw)
00190         {
00191                 FileLogMap::iterator i = FileLogs.find(fw);
00192                 if (i == FileLogs.end()) return; /* Maybe should log this? */
00193                 if (--i->second < 1)
00194                 {
00195                         delete i->first;
00196                         FileLogs.erase(i);
00197                 }
00198         }
00199 
00202         void OpenFileLogs();
00203 
00207         void CloseLogs();
00208 
00216         void AddLogTypes(const std::string &type, LogStream *l, bool autoclose);
00217 
00225         bool AddLogType(const std::string &type, LogStream *l, bool autoclose);
00226 
00230         void DelLogStream(LogStream* l);
00231 
00235         bool DelLogType(const std::string &type, LogStream *l);
00236 
00242         void Log(const std::string &type, int loglevel, const std::string &msg);
00243 
00249         void Log(const std::string &type, int loglevel, const char *fmt, ...) CUSTOM_PRINTF(4, 5);
00250 };
00251 
00252 #endif