- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# Logger.h

Go to the documentation of this file.

    00001
    00015 #pragma once
    00016
    00017 #include "LogInfo.h"
    00018 #include "ILogPrinter.h"
    00019 #include "LogLevel.h"
    00020 #include "LogFilter.h"
    00021 #include "ILogManager.h"
    00022 #include "RegistryKey.h"
    00023 #include "SimpleTextLogPrinter.h"
    00024 #include "DebugOutputLogManager.h"
    00025 #include "XMLLogPrinter.h"
    00026 #include "FileLogManager.h"
    00027
    00028 #include <vector>
    00029 #include <set>
    00030 #include <map>
    00031 #include <boost/any.hpp>
    00032
    00033 #include <algorithm>
    00034 #include <boost/foreach.hpp>
    00035 #include <boost/algorithm/string/erase.hpp>
    00036 #include "boost/date_time/posix_time/posix_time.hpp"
    00037 #include <exception>
    00038
    00039 #define LOGGING_KEYNAME_DEFAULT_PROCESS _T("DefaultProcess")
    00040 #define LOGGING_KEYNAME_SOFTWARE _T("Software")
    00041 #define LOGGING_KEYNAME_NVIDIA_CORPORATION _T("NVIDIA Corporation")
    00042 #define LOGGING_KEYNAME_LOGGING _T("Logging")
    00043 #define LOGGING_KEYNAME_PROCESSES _T("Processes")
    00044 #define LOGGING_KEYNAME_DEFINITIONS _T("Definitions")
    00045 #define LOGGING_KEYNAME_LOGCHANNELS _T("LogChannels")
    00046 #define LOGGING_KEYNAME_LOGPRINTERS _T("LogPrinters")
    00047 #define LOGGING_KEYNAME_LOGMANAGERS _T("LogManagers")
    00048 #define LOGGING_KEYNAME_LOGFILTERS _T("LogFilters")
    00049 #define LOGGING_KEYNAME_LOGPRINTER _T("LogPrinter")
    00050 #define LOGGING_KEYNAME_LOGFILTER _T("LogFilter")
    00051 #define LOGGING_KEYNAME_CLASSNAME _T("ClassName")
    00052
    00053 #define LOGGING_SYSTEM_LOG(message)                                                                     \
    00054 {                                                                                                       \
    00055     Log(LogInfo(LogLevel_System, std::tstring(_T("system")), _T(__FUNCTION__), _T(__FILE__), __LINE__), \
    00056     MakeChainLoggable(MakeEmptyChain() + boost::posix_time::second_clock::local_time() + _T(": ") + message));                                                     \
    00057 }
    00058
    00059 namespace Nvidia {
    00060 namespace Logging {
    00061
    00062 namespace Test {
    00063     class LoggerTest;
    00064     class LoggerConstructorTest;
    00065 }
    00066
    00078 class Logger
    00079 {
    00080     friend class Nvidia::Logging::Test::LoggerTest;
    00081     friend class Nvidia::Logging::Test::LoggerConstructorTest;
    00082
    00083 private:
    00098     std::vector<std::pair<LogFilter*, ILogPrinter*> > FiltersAndPrinters;
    00099
    00106     std::map<std::tstring, ILogManager*> Managers;
    00107
    00108 public:
    00122     Logger();
    00123
    00125     ~Logger();
    00126
    00134     void Log(const LogInfo& logInfo, const CompositeLoggable& message);
    00135
    00144     LogLevel GetMaximumLogLevel(const std::tstring& scopeLoggerName);
    00145
    00152     static Logger& GetLogger();
    00153
    00154 private:
    00168     bool TryConfigureFromRegistry(HKEY baseKeyHandle, const std::tstring& processName);
    00169
    00178     void ConfigureDefault();
    00179
    00199     void ConfigureLogChannel(const std::tstring& logFilterName, const std::tstring& logPrinterName,
    00200         const std::set<std::tstring>& logManagers, const RegistryKey& definitionsKey);
    00201
    00212     ILogPrinter* CreateLogPrinter(const RegistryKey& key) const;
    00213
    00224     ILogManager* CreateLogManager(const RegistryKey& key) const;
    00225
    00234     ILogManager* GetOrCreateLogManager(const std::tstring& name, const RegistryKey& key);
    00235
    00242     std::tstring GetProcessName();
    00243 };
    00244
    00245 // Configuration reading order:
    00246 // 1. HKCU/.../PROCESS.EXE
    00247 // 2. HKLM/.../PROCESS.EXE
    00248 // 3. HKCU/.../DEFAULT
    00249 // 4. HKLM/.../DEFAULT
    00250 // 5. Hardcoded default
    00251 inline Logger::Logger()
    00252 {
    00253     std::tstring processName = GetProcessName();
    00254
    00255     if ( TryConfigureFromRegistry(HKEY_CURRENT_USER, processName) )
    00256     {
    00257         LOGGING_SYSTEM_LOG(_T("Logging init OK. Using configuration from HKCU for ") + processName);
    00258     }
    00259     else if ( TryConfigureFromRegistry(HKEY_LOCAL_MACHINE, processName) )
    00260     {
    00261         LOGGING_SYSTEM_LOG(_T("Logging init OK. Using configuration from HKLM for ") + processName);
    00262     }
    00263     else if ( TryConfigureFromRegistry(HKEY_CURRENT_USER, LOGGING_KEYNAME_DEFAULT_PROCESS) )
    00264     {
    00265         LOGGING_SYSTEM_LOG(_T("Logging init OK. Using configuration from HKCU for ") + LOGGING_KEYNAME_DEFAULT_PROCESS);
    00266     }
    00267     else if ( TryConfigureFromRegistry(HKEY_LOCAL_MACHINE, LOGGING_KEYNAME_DEFAULT_PROCESS) )
    00268     {
    00269         LOGGING_SYSTEM_LOG(_T("Logging init OK. Using configuration from HKLM for ") + LOGGING_KEYNAME_DEFAULT_PROCESS);
    00270     }
    00271     else
    00272     {
    00273         ConfigureDefault();
    00274         LOGGING_SYSTEM_LOG(_T("Logging init OK. No configuration found in registry, using default configuration"));
    00275     }
    00276 }
    00277
    00278 inline std::tstring Logger::GetProcessName()
    00279 {
    00280     try {
    00281         return Utils::GetProcessName();
    00282     } catch ( std::exception& ) {
    00283         return LOGGING_KEYNAME_DEFAULT_PROCESS;
    00284     }
    00285 }
    00286
    00287 inline void Logger::ConfigureDefault()
    00288 {
    00289     LogFilter*  logFilter  = new LogFilter(LogLevel_Warning);
    00290     ILogPrinter* logPrinter = new SimpleTextLogPrinter();
    00291     ILogManager* logManager = new DebugOutputLogManager();
    00292     logPrinter->AddLogManager(logManager);
    00293
    00294     FiltersAndPrinters.push_back(std::make_pair(logFilter, logPrinter));
    00295     Managers[_T("default")] = logManager;
    00296 }
    00297
    00298 inline bool Logger::TryConfigureFromRegistry(HKEY baseKeyHandle, const std::tstring& processName)
    00299 {
    00300     try {
    00301         const RegistryKey& loggingKey = RegistryKey(baseKeyHandle, LOGGING_KEYNAME_SOFTWARE).GetSubKey(LOGGING_KEYNAME_NVIDIA_CORPORATION).GetSubKey(LOGGING_KEYNAME_LOGGING);
    00302
    00303         const RegistryKey& processKey = loggingKey.GetSubKey(LOGGING_KEYNAME_PROCESSES).GetSubKey(processName);
    00304         const RegistryKey& processLogChannelsKey = processKey.GetSubKey(LOGGING_KEYNAME_LOGCHANNELS);
    00305
    00306         const RegistryKey& definitionsKey = loggingKey.GetSubKey(LOGGING_KEYNAME_DEFINITIONS);
    00307         const RegistryKey& logChannelsKey = definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGCHANNELS);
    00308         definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGPRINTERS);
    00309         definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGMANAGERS);
    00310         definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGFILTERS);
    00311
    00312         //if above didn't throw then process config structure is right.
    00313         //Errors (i.e. missing LogXXX definition) are now dealt with locally.
    00314         BOOST_FOREACH(std::tstring logChannelName, processLogChannelsKey.GetValueNames())
    00315         {
    00316             try {
    00317                 const RegistryKey& thisChannelKey = logChannelsKey.GetSubKey(logChannelName);
    00318                 const std::tstring& logFilterName = thisChannelKey.GetStringValue(LOGGING_KEYNAME_LOGFILTER);
    00319                 const std::tstring& logPrinterName = thisChannelKey.GetStringValue(LOGGING_KEYNAME_LOGPRINTER);
    00320                 const std::set<std::tstring>& logManagers = thisChannelKey.GetSubKey(LOGGING_KEYNAME_LOGMANAGERS).GetValueNames();
    00321
    00322                 ConfigureLogChannel(logFilterName, logPrinterName, logManagers, definitionsKey);
    00323             } catch ( RegistryException& ) {
    00324             }
    00325         }
    00326         return true;
    00327
    00328     } catch ( RegistryException& ) {
    00329         return false;
    00330     }
    00331 }
    00332
    00333 inline void Logger::ConfigureLogChannel(const std::tstring& logFilterName, const std::tstring& logPrinterName,
    00334                                  const std::set<std::tstring>& logManagers, const RegistryKey& definitionsKey)
    00335 {
    00336     try {
    00337         LogFilter* logFilter = new LogFilter(definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGFILTERS).GetSubKey(logFilterName));
    00338         try {
    00339             ILogPrinter* logPrinter = CreateLogPrinter(definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGPRINTERS).GetSubKey(logPrinterName));
    00340             BOOST_FOREACH(std::tstring logManagerName, logManagers)
    00341             {
    00342                 try {
    00343                     logPrinter->AddLogManager(GetOrCreateLogManager(logManagerName, definitionsKey.GetSubKey(LOGGING_KEYNAME_LOGMANAGERS).GetSubKey(logManagerName)));
    00344                 } catch ( std::exception& ) {
    00345                     //This happens when new LogManager is not compatible with this LogPrinter.
    00346                     //
    00347                     //We don't care about destruction of the unused LogManager here.
    00348                     //If it was created, then the pointer was also saved in Managers container,
    00349                     //and so this LogManager will be destructed in ~Logger().
    00350                 }
    00351             }
    00352
    00353             FiltersAndPrinters.push_back(std::make_pair(logFilter, logPrinter));
    00354
    00355         } catch ( std::exception& ) {
    00356             delete logFilter;
    00357         }
    00358     } catch ( std::exception& ) {
    00359     }
    00360 }
    00361
    00362 // This function should be modified when new LogPrinters are added.
    00363 inline ILogPrinter* Logger::CreateLogPrinter(const RegistryKey& key) const
    00364 {
    00365     const std::tstring& className = key.GetStringValue(LOGGING_KEYNAME_CLASSNAME);
    00366     if ( className == _T("SimpleTextLogPrinter") )
    00367     {
    00368         return new SimpleTextLogPrinter(key);
    00369     }
    00370     else if ( className == _T("XMLLogPrinter") )
    00371     {
    00372         return new XMLLogPrinter(key);
    00373     }
    00374     else
    00375     {
    00376         throw std::runtime_error("No LogPrinter defined with such name.");
    00377     }
    00378 }
    00379
    00380 // This function should be modified when new LogManagers are added.
    00381 inline ILogManager* Logger::CreateLogManager(const RegistryKey& key) const
    00382 {
    00383     const std::tstring& className = key.GetStringValue(LOGGING_KEYNAME_CLASSNAME);
    00384     if ( className == _T("DebugOutputLogManager") )
    00385     {
    00386         return new DebugOutputLogManager(key);
    00387
    00388     }
    00389     else if ( className == _T("FileLogManager") )
    00390     {
    00391         return new FileLogManager(key);
    00392     }
    00393     else
    00394     {
    00395         throw std::runtime_error("No LogManager defined with such name.");
    00396     }
    00397 }
    00398
    00399 inline ILogManager* Logger::GetOrCreateLogManager(const std::tstring& name, const RegistryKey& key)
    00400 {
    00401     if ( Managers.count(name) )
    00402         return Managers[name];
    00403     ILogManager* logManager = CreateLogManager(key);
    00404     Managers[name] = logManager;
    00405     return logManager;
    00406 }
    00407
    00408 inline Logger::~Logger()
    00409 {
    00410     std::pair<LogFilter*, ILogPrinter*> pair;
    00411     BOOST_FOREACH(pair, FiltersAndPrinters)
    00412     {
    00413         delete pair.first;
    00414         delete pair.second;
    00415     }
    00416
    00417     std::pair<std::tstring, ILogManager*> pair2;
    00418
    00419     BOOST_FOREACH(pair2, Managers)
    00420     {
    00421         delete pair2.second;
    00422     }
    00423 }
    00424
    00425 inline void Logger::Log(const LogInfo& logInfo, const CompositeLoggable& message)
    00426 {
    00427     std::pair<LogFilter*, ILogPrinter*> pair;
    00428     BOOST_FOREACH(pair, FiltersAndPrinters)
    00429     {
    00430         if ( !(pair.first)->IsFiltered(logInfo) )
    00431             (pair.second)->PrintMessage(logInfo, message);
    00432     }
    00433 }
    00434
    00435 inline LogLevel Logger::GetMaximumLogLevel(const std::tstring& scopeLoggerName)
    00436 {
    00437     LogFilter* filter;
    00438     LogLevel maximumLogLevel = LogLevel_System;
    00439
    00440     std::pair<LogFilter*, ILogPrinter*> pair;
    00441
    00442     BOOST_FOREACH(pair, FiltersAndPrinters)
    00443     {
    00444         filter = pair.first;
    00445         maximumLogLevel = Utils::Maximum(maximumLogLevel, filter->GetMaximumLogLevel(scopeLoggerName));
    00446     }
    00447
    00448     return maximumLogLevel;
    00449 }
    00450
    00451 inline Logger& Logger::GetLogger()
    00452 {
    00453     static Logger logger;
    00454     return logger;
    00455 }
    00456
    00457 }
    00458 }