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
00246
00247
00248
00249
00250
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
00313
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
00346
00347
00348
00349
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
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
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 }