1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
/*
* $Revision: 3157 $
*
* last checkin:
* $Author: chimani $
* $Date: 2012-12-12 16:49:59 +0100 (Wed, 12 Dec 2012) $
***************************************************************/
/** \file
* \brief Contains logging functionality
*
* \author Markus Chimani
*
* \par License:
* This file is part of the Open Graph Drawing Framework (OGDF).
*
* \par
* Copyright (C)<br>
* See README.txt in the root directory of the OGDF installation for details.
*
* \par
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 or 3 as published by the Free Software Foundation;
* see the file LICENSE.txt included in the packaging of this file
* for details.
*
* \par
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* \par
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* \see http://www.gnu.org/copyleft/gpl.html
***************************************************************/
#ifndef OGDF_LOGGER_H
#define OGDF_LOGGER_H
//#include <ogdf/basic/basic.h>
#include <ogdf/internal/basic/config.h>
namespace ogdf {
//! Centralized global and local logging facility working on streams like cout.
/**
* The Logger class is a centralized logging environment with 2x2 different use-cases working together.
* All generated output is sent into the \a world-stream, i.e., \a cout, if not set otherwise.
*
* \b Logging \b vs. \b Statistic:
* The Logger differentiates between \a logging and \a statistic mode.
* When in logging mode, only the output written via the lout()/slout() commands is
* written to the world stream (according to loglevels). When in statistic mode,
* only the output of the sout()/ssout() commands is written.
* (Sidenote: there is also a \a forced output fout()/sfout() which is written independent on the current mode).
*
* The idea of these two modi is that one can augment the code with output which is
* interesting in the normal computation mode via lout, but the same algorithm can also be run given tabular
* statistic-lines when e.g. batch-testing the algorithm on a set of benchmark instances.
*
* \b Global \b vs. \b Local:
* You can choose to use the Logging facilities globally via the static outputs (slout(), ssout(), sfout()).
* Thereby the global log-level and statistic-mode settings are applied.
* Alternatively you can create your own Logging object with its own parameters only for your algorithm,
* and use the object methods lout(), sout(), and fout(). This allows you to turn output on for your own
* (new) algorithm, but keep the rest of the library silent.
*
* \b Global \b Settings:
* The slout command takes an (optional) parameter given the importance of the output (aka. loglevel).
* The output is written only if the globalLogLevel is not higher. The method globalStatisticMode
* turn the statistic-mode on and off (thereby disabling or enabling the logging mode).
*
* Furthermore, we have a globalMinimumLogLevel. This is used to globally forbid any output
* with too low importance written by any Logger-objects.
*
* \b Local \b Settings:
* A Logger-object has its own set of settings, i.e., its own localLogLevel and an own localLogMode,
* which can be any of the following:
* - \a LM_LOG: the object is in logging mode, using its own localLogLevel
* - \a LM_STATISTIC: the object is in statistic mode
* - \a LM_GLOBAL: the object is in the same mode as the static Logger-class (i.e., global settings)
* - \a LM_GLOBALLOG: the object is in logging mode, but uses the globalLogLevel
*
* \b Typical \b Usage:<br>
* The simplest but restricted and verbose usage is to write <br>
* <code><br>
* Logger::slout() << "1+2=" << (1+2) << endl;
* </code>
*
* The conceptually easiest and cleanest approach is to augment your algorithm class with a Logger.
* Multiple inheritance allows this pretty straightforwardly:<br>
* <code><br>
* class MyAlgorithm : public MyBaseClass, protected Logger {<br>
* int myMethod();<br>
* }<br>
* <br>
* MyAlgorithm::myMethod() {<br>
* lout() << "1+2=" << (1+2) << endl;<br>
* }<br>
* </code>
*
*
* \b Internal \b Library \b Logging:
* Internal Libaries (as, e.g., Abacus) can use their own, global, set of logging functions.
* Its LogLevels are parallel and independent of the global LogLevel, but its logging is automatically
* turned off whenever the (global/static) Logger is in statistics-mode.
*/
class OGDF_EXPORT Logger {
public:
//! supported log-levels from lowest to highest importance
enum Level { LL_MINOR, LL_MEDIUM, LL_DEFAULT, LL_HIGH, LL_ALARM, LL_FORCE };
//! (local) log-modes (see class description)
enum LogMode { LM_GLOBAL, LM_GLOBALLOG, LM_LOG, LM_STATISTIC };
// CONSTRUCTORS //////////////////////////////////////
//! creates a new Logger-object with LM_GLOBAL and local log-level equal globalLogLevel
Logger() :
m_loglevel(m_globalloglevel), m_logmode(LM_GLOBAL) {}
//! creates a new Logger-object with given log-mode and local log-level equal globalLogLevel
Logger(LogMode m) :
m_loglevel(m_globalloglevel), m_logmode(m) {}
//! creates a new Logger-object with LM_GLOBAL and given local log-level
Logger(Level l) :
m_loglevel(l), m_logmode(LM_GLOBAL) {}
//! creates a new Logger-object with given log-mode and given local log-level
Logger(LogMode m, Level l) :
m_loglevel(l), m_logmode(m) {}
// USAGE //////////////////////////////////////
//! returns true if such an lout command will result in text being printed
bool is_lout(Level l = LL_DEFAULT) const {
return ((!m_globalstatisticmode && m_logmode==LM_GLOBAL) || m_logmode==LM_GLOBALLOG)
? ( (l >= m_globalloglevel) ? true : false )
: ( (m_logmode==LM_LOG && l >= m_loglevel && l >= m_minimumloglevel) ? true : false );
}
//! stream for logging-output (local)
std::ostream& lout(Level l = LL_DEFAULT) const {
return (is_lout(l)) ? *world : nirvana;
}
//! stream for statistic-output (local)
std::ostream& sout() const {
return ((m_globalstatisticmode && m_logmode==LM_GLOBAL) || (m_logmode == LM_STATISTIC)) ? *world : nirvana;
}
//! stream for forced output (local)
std::ostream& fout() const {
return sfout();
}
// STATIC USAGE ///////////////////////////////
//! returns true if such an slout command will result in text being printed
static bool is_slout(Level l = LL_DEFAULT) {
return ((!m_globalstatisticmode) && l >= m_globalloglevel) ? true : false;
}
//! stream for logging-output (global)
static std::ostream& slout(Level l = LL_DEFAULT) {
return (is_slout(l)) ? *world : nirvana;
}
//! stream for statistic-output (global)
static std::ostream& ssout() {
return (m_globalstatisticmode) ? *world : nirvana;
}
//! stream for forced output (global)
static std::ostream& sfout() {
return *world;
}
// STATIC INTERNAL_LIBRARY_USAGE ///////////////////////////////
//! stream for logging-output (global; used by internal libraries, e.g. Abacus)
//! returns true if such an ilout command will result in text being printed
static bool is_ilout(Level l = LL_DEFAULT) {
return ((!m_globalstatisticmode) && l >= m_globallibraryloglevel) ? true : false;
}
static std::ostream& ilout(Level l = LL_DEFAULT) {
return (is_ilout(l)) ? *world : nirvana;
}
//! stream for forced output (global; used by internal libraries, e.g. Abacus)
static std::ostream& ifout() {
return *world;
}
// LOCAL //////////////////////////////////////
//! gives the local log-level
Level localLogLevel() const {
return m_loglevel;
}
//! sets the local log-level
void localLogLevel(Level l) {
m_loglevel = l;
}
//! gives the local log-mode
LogMode localLogMode() const {
return m_logmode;
}
//! sets the local log-mode
void localLogMode(LogMode m) {
m_logmode = m;
}
// GLOBAL //////////////////////////////////////
//! gives the global log-level
static Level globalLogLevel() { return m_globalloglevel; }
//! sets the global log-level
static void globalLogLevel(Level l) {
m_globalloglevel = l;
if( m_globalloglevel < m_minimumloglevel )
m_minimumloglevel = m_globalloglevel;
}
//! gives the internal-library log-level
static Level globalInternalLibraryLogLevel() { return m_globallibraryloglevel; }
//! sets the internal-library log-level
static void globalInternalLibraryLogLevel(Level l) { m_globallibraryloglevel = l; }
//! gives the globally minimally required log-level
static Level globalMinimumLogLevel() { return m_minimumloglevel; }
//! sets the globally minimally required log-level
static void globalMinimumLogLevel(Level l) {
m_minimumloglevel = l;
if( m_globalloglevel < m_minimumloglevel )
m_globalloglevel = m_minimumloglevel;
}
//! returns true if we are globally in statistic mode
static bool globalStatisticMode() { return m_globalstatisticmode; }
//! sets whether we are globally in statistic mode
static void globalStatisticMode(bool s) { m_globalstatisticmode = s; }
//! change the stream to which allowed output is written (by default: cout)
static void setWorldStream(std::ostream& o) { world = &o; }
// EFFECTIVE //////////////////////////////////////
//! obtain the effective log-level for the Logger-object (i.e., resolve the dependencies on the global settings)
Level effectiveLogLevel() const {
if(m_logmode==LM_GLOBAL || m_logmode==LM_GLOBALLOG)
return m_globalloglevel;
else
return (m_loglevel > m_minimumloglevel) ? m_loglevel : m_minimumloglevel;
}
//! returns true if the Logger-object is effectively in statistic-mode (as this might be depending on the global settings)
bool effectiveStatisticMode() const {
return m_logmode==LM_STATISTIC || (m_logmode==LM_GLOBAL && m_globalstatisticmode);
}
private:
static std::ostream nirvana;
static std::ostream* world;
static Level m_globalloglevel;
static Level m_globallibraryloglevel;
static Level m_minimumloglevel;
static bool m_globalstatisticmode;
Level m_loglevel;
LogMode m_logmode;
};
}
#endif // OGDF_LOGGER_H
|