logger.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #include <algorithm>
00024 #include <iomanip>
00025 #include <fstream>
00026 
00027 // 3rd party library includes
00028 #include <SDL.h>
00029 
00030 // FIFE includes
00031 // These includes are split up in two parts, separated by one empty line
00032 // First block: files included from the FIFE root src directory
00033 // Second block: files included from the same folder
00034 #include "modules.h"
00035 #include "logger.h"
00036 #include "util/base/exception.h"
00037 
00038 // define the module info relationships structure here, begin
00039 struct ModuleInfo {
00040     logmodule_t module;
00041     logmodule_t parent;
00042     std::string name;
00043 };
00044 MODULE_INFO_RELATIONSHIPS
00045 // end
00046 
00047 namespace FIFE {
00048     LogManager* LogManager::m_instance = NULL;
00049 
00050     Logger::Logger(logmodule_t module):
00051         m_module(module) {
00052     }
00053 
00054     Logger::~Logger() {
00055     }
00056 
00057     void Logger::log(LogManager::LogLevel level, const std::string& msg) {
00058         LogManager::instance()->log(level, m_module, msg);
00059     }
00060 
00061     void Logger::log(LogManager::LogLevel level, const LMsg& msg) {
00062         LogManager::instance()->log(level, m_module, msg.str);
00063     }
00064 
00065     LogManager* LogManager::instance() {
00066         if (!m_instance) {
00067             m_instance = new LogManager();
00068         }
00069         return m_instance;
00070     }
00071 
00072     LogManager::~LogManager() {
00073         delete m_instance;
00074     }
00075 
00076 
00077     void LogManager::log(LogLevel level, logmodule_t module, const std::string& msg) {
00078         if (level < m_level) {
00079             return;
00080         }
00081         if (!isVisible(module)) {
00082             return;
00083         }
00084         std::string lvlstr = "";
00085         switch (level) {
00086             case LEVEL_DEBUG: lvlstr = "DEBUG";
00087             break;
00088 
00089             case LEVEL_LOG: lvlstr = "LOG";
00090             break;
00091 
00092             case LEVEL_WARN: lvlstr = "WARN";
00093             break;
00094 
00095             case LEVEL_ERROR: lvlstr = "ERROR";
00096             break;
00097 
00098             case LEVEL_PANIC: lvlstr = "PANIC";
00099             break;
00100 
00101             default: lvlstr = "ERROR";
00102             break;
00103         }
00104         if (m_logtoprompt) {
00105             std::cout << moduleInfos[module].name << ":" << lvlstr << ":" << msg << std::endl;
00106         }
00107         if (m_logtofile) {
00108             *m_logfile << moduleInfos[module].name << ":" << lvlstr << ":" << msg << std::endl;
00109         }
00110         if (level == LEVEL_PANIC) {
00111             abort();
00112         }
00113     }
00114 
00115     void LogManager::setLevelFilter(LogLevel level) {
00116         m_level = level;
00117     }
00118 
00119     LogManager::LogLevel LogManager::getLevelFilter() {
00120         return m_level;
00121     }
00122 
00123     void LogManager::addVisibleModule(logmodule_t module) {
00124         validateModule(module);
00125         int32_t ind = static_cast<int32_t>(module);
00126         m_modules[ind] = true;
00127         if (moduleInfos[ind].parent != LM_CORE) {
00128             addVisibleModule(moduleInfos[ind].parent);
00129         }
00130     }
00131 
00132     void LogManager::removeVisibleModule(logmodule_t module) {
00133         validateModule(module);
00134         m_modules[module] = false;
00135     }
00136 
00137     void LogManager::clearVisibleModules() {
00138         for (int32_t i = 0; i < LM_MODULE_MAX; i++) {
00139             m_modules[i] = false;
00140         }
00141     }
00142 
00143     void LogManager::setLogToPrompt(bool log_to_promt) {
00144         m_logtoprompt = log_to_promt;
00145     }
00146 
00147     bool LogManager::isLoggingToPrompt() {
00148         return m_logtoprompt;
00149     }
00150 
00151     void LogManager::setLogToFile(bool logtofile) {
00152         if(logtofile){
00153             m_logfile = new std::ofstream("fife.log");
00154         }
00155         else {
00156             if (m_logfile){
00157                 delete m_logfile;
00158             }
00159         }
00160         m_logtofile = logtofile;
00161     }
00162 
00163     bool LogManager::isLoggingToFile() {
00164         return m_logtofile;
00165     }
00166 
00167     bool LogManager::isVisible(logmodule_t module) {
00168         if (!m_modules[module]) {
00169             return false;
00170         }
00171         if (moduleInfos[module].parent != LM_CORE) {
00172             return isVisible(moduleInfos[module].parent);
00173         }
00174         return true;
00175     }
00176 
00177     LogManager::LogManager():
00178         m_level(LEVEL_DEBUG),
00179         module_check_stack(),
00180         m_logtofile(false),
00181         m_logtoprompt(false) {
00182         validateModuleDescription(LM_CORE);
00183         m_logfile = 0;
00184         clearVisibleModules();
00185     }
00186 
00187     void LogManager::validateModule(logmodule_t m) {
00188         if ((m <= LM_CORE) || (m >= LM_MODULE_MAX)) {
00189             std::cout << "Invalid module received in LogManager: " << m << ", aborting\n";
00190             abort();
00191         }
00192     }
00193 
00194     void LogManager::validateModuleDescription(logmodule_t module) {
00195         if (module == LM_CORE) {
00196             for (int32_t m = static_cast<int32_t>(LM_CORE)+1; m < static_cast<int32_t>(LM_MODULE_MAX); m++) {
00197                 if (moduleInfos[m].module != static_cast<logmodule_t>(m)) {
00198                     std::ostringstream stream;
00199                     stream << m;
00200                     std::string msg = "Log module definition ids do not match in index ";
00201                     msg += stream.str();
00202                     std::cout << msg << std::endl;
00203                     throw InvalidFormat(msg);
00204                 }
00205                 module_check_stack.clear();
00206                 validateModuleDescription(static_cast<logmodule_t>(m));
00207             }
00208         } else {
00209             module_check_stack.push_back(module);
00210             if (count(module_check_stack.begin(), module_check_stack.end(), module) > 1) {
00211                 throw InvalidFormat("Log module definition hierarchy contains cycles");
00212             }
00213         }
00214     }
00215 
00216     std::string LogManager::getModuleName(logmodule_t module) {
00217         return moduleInfos[module].name;
00218     }
00219 }