Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7876941
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Subscribers
None
View Options
diff --git a/include/Rivet/Tools/Logging.hh b/include/Rivet/Tools/Logging.hh
--- a/include/Rivet/Tools/Logging.hh
+++ b/include/Rivet/Tools/Logging.hh
@@ -1,187 +1,183 @@
#ifndef RIVET_LOGGING_HH
#define RIVET_LOGGING_HH
#include "Rivet/Config/RivetCommon.hh"
namespace Rivet {
class Log {
public:
/// Log priority levels.
enum Level {
TRACE = 0, DEBUG = 10, INFO = 20, WARN = 30, WARNING = 30, ERROR = 40, CRITICAL = 50, ALWAYS = 50
};
/// Typedef for a collection of named logs.
- typedef std::map<std::string, Log*> LogMap;
+ typedef std::map<std::string, Log> LogMap;
/// Typedef for a collection of named log levels.
typedef std::map<std::string, int> LevelMap;
/// Typedef for a collection of shell color codes, accessed by log level.
typedef std::map<int, std::string> ColorCodes;
private:
/// A static map of existing logs: we don't make more loggers than necessary.
static LogMap existingLogs;
/// A static map of default log levels.
static LevelMap defaultLevels;
/// A static map of shell color codes for the log levels.
static ColorCodes colorCodes;
/// Shell color code for the end of the log levels.
static std::string endColorCode;
/// Show timestamp?
static bool showTimestamp;
/// Show log level?
static bool showLogLevel;
/// Show logger name?
static bool showLoggerName;
/// Use shell colour escape codes?
static bool useShellColors;
public:
/// Set the log levels
static void setLevel(const std::string& name, int level);
static void setLevels(const LevelMap& logLevels);
static void setShowTimestamp(bool showTime=true) {
showTimestamp = showTime;
}
static void setShowLevel(bool showLevel=true) {
showLogLevel = showLevel;
}
static void setShowLoggerName(bool showName=true) {
showLoggerName = showName;
}
static void setUseColors(bool useColors=true) {
useShellColors = useColors;
}
protected:
/// @name Hidden constructors etc.
//@{
/// Constructor 1
Log(const std::string& name);
/// Constructor 2
Log(const std::string& name, int level);
//@}
static std::string getColorCode(int level);
public:
/// Get a logger with the given name. The level will be taken from the
/// "requestedLevels" static map or will be INFO by default.
static Log& getLog(const std::string& name);
public:
/// Get the priority level of this logger.
int getLevel() const {
return _level;
}
/// Set the priority level of this logger.
Log& setLevel(int level) {
_level = level;
return *this;
}
/// Get a log level enum from a string.
static Level getLevelFromName(const std::string& level);
/// Get the std::string representation of a log level.
static std::string getLevelName(int level);
/// Get the name of this logger.
std::string getName() const {
return _name;
}
/// Set the name of this logger.
Log& setName(const std::string& name) {
_name = name;
return *this;
}
/// Will this log level produce output on this logger at the moment?
bool isActive(int level) const {
return (level >= _level);
}
/// @name Explicit log methods
//@{
void trace(const std::string& message) { log(TRACE, message); }
void debug(const std::string& message) { log(DEBUG, message); }
void info(const std::string& message) { log(INFO, message); }
void warn(const std::string& message) { log(WARN, message); }
void error(const std::string& message) { log(ERROR, message); }
//@}
private:
/// This logger's name
std::string _name;
/// Threshold level for this logger.
int _level;
protected:
/// Write a message at a particular level.
void log(int level, const std::string& message);
/// Turn a message string into the current log format.
std::string formatMessage(int level, const std::string& message);
public:
- /// A null output stream, used for piping discarded output to nowhere.
- /// @todo Hide this...
- std::ostream* const _nostream;
-
/// The streaming operator can use Log's internals.
friend std::ostream& operator<<(Log& log, int level);
};
/// Streaming output to a logger must have a Log::Level/int as its first argument.
std::ostream& operator<<(Log& log, int level);
}
// Neat CPU-conserving logging macros. Use by preference!
// NB. Only usable in classes where a getLog() method is provided
#define MSG_LVL(lvl, x) \
do { \
if (getLog().isActive(lvl)) { \
getLog() << lvl << x << endl; \
} \
} while (0)
#define MSG_TRACE(x) MSG_LVL(Log::TRACE, x)
#define MSG_DEBUG(x) MSG_LVL(Log::DEBUG, x)
#define MSG_INFO(x) MSG_LVL(Log::INFO, x)
#define MSG_WARNING(x) MSG_LVL(Log::WARNING, x)
#define MSG_ERROR(x) MSG_LVL(Log::ERROR, x)
#endif
diff --git a/src/Tools/Logging.cc b/src/Tools/Logging.cc
--- a/src/Tools/Logging.cc
+++ b/src/Tools/Logging.cc
@@ -1,198 +1,203 @@
#include "Rivet/Tools/Logging.hh"
#include <ctime>
#include <unistd.h>
using namespace std;
namespace Rivet {
Log::LogMap Log::existingLogs;
Log::LevelMap Log::defaultLevels;
Log::ColorCodes Log::colorCodes;
string Log::endColorCode;
bool Log::showTimestamp = false;
bool Log::showLogLevel = true;
bool Log::showLoggerName = true;
bool Log::useShellColors = true;
Log::Log(const string& name)
- : _name(name), _level(INFO), _nostream(new ostream(0)) { }
+ : _name(name), _level(INFO) { }
Log::Log(const string& name, int level)
- : _name(name), _level(level), _nostream(new ostream(0)) { }
+ : _name(name), _level(level) { }
/// @todo Add single static setLevel
void _updateLevels(const Log::LevelMap& defaultLevels, Log::LogMap& existingLogs) {
/// @todo Check ordering - "Foo" should come before "Foo.Bar"
for (Log::LevelMap::const_iterator lev = defaultLevels.begin(); lev != defaultLevels.end(); ++lev) {
for (Log::LogMap::iterator log = existingLogs.begin(); log != existingLogs.end(); ++log) {
if (log->first.find(lev->first) == 0) {
- log->second->setLevel(lev->second);
+ log->second.setLevel(lev->second);
}
}
}
}
void Log::setLevel(const string& name, int level) {
defaultLevels[name] = level;
//cout << name << " -> " << level << endl;
_updateLevels(defaultLevels, existingLogs);
}
void Log::setLevels(const LevelMap& logLevels) {
for (LevelMap::const_iterator lev = logLevels.begin(); lev != logLevels.end(); ++lev) {
defaultLevels[lev->first] = lev->second;
}
_updateLevels(defaultLevels, existingLogs);
}
Log& Log::getLog(const string& name) {
- if (existingLogs.find(name) == existingLogs.end()) {
+ auto theLog = existingLogs.find(name);
+ if (theLog == existingLogs.end()) {
int level = INFO;
// Try running through all parent classes to find an existing level
string tmpname = name;
bool triedAllParents = false;
while (! triedAllParents) {
// Is there a default level?
if (defaultLevels.find(tmpname) != defaultLevels.end()) {
level = defaultLevels.find(tmpname)->second;
break;
}
- // Is there already such a logger? (NB. tmpname != name)
+ // Is there already such a logger? (NB. tmpname != name in later iterations)
if (existingLogs.find(tmpname) != existingLogs.end()) {
- level = existingLogs.find(tmpname)->second->getLevel();
+ level = existingLogs.find(tmpname)->second.getLevel();
break;
}
// Crop the string back to the next parent level
size_t lastDot = tmpname.find_last_of(".");
if (lastDot != string::npos) {
tmpname = tmpname.substr(0, lastDot);
} else {
triedAllParents = true;
}
}
// for (LevelMap::const_iterator l = defaultLevels.begin(); l != defaultLevels.end(); ++l) {
//
// }
- existingLogs[name] = new Log(name, level);
+
+ // emplace returns pair<iterator,bool>
+ auto result = existingLogs.emplace(name, Log(name, level));
+ theLog = result.first;
}
- return *existingLogs[name];
+ return theLog->second;
}
string Log::getLevelName(int level) {
/// @todo Do the map::upper_limit thing to find nearest level...
switch(level) {
case TRACE:
return "TRACE";
case DEBUG:
return "DEBUG";
case INFO:
return "INFO";
case WARN:
return "WARN";
case ERROR:
return "ERROR";
default:
return "";
}
//throw Error("Enum value was not a valid log level. How did that happen?");
}
string Log::getColorCode(int level) {
if (!Log::useShellColors) return "";
// If the codes haven't been initialized, do so now.
if (Log::colorCodes.empty()) {
// If stdout is a valid tty, try to use the appropriate codes.
if (isatty(1)) {
/// @todo Test for VT100 compliance?
Log::colorCodes[TRACE] = "\033[0;36m";
Log::colorCodes[DEBUG] = "\033[0;34m";
Log::colorCodes[INFO] = "\033[0;32m";
Log::colorCodes[WARN] = "\033[0;33m";
Log::colorCodes[ERROR] = "\033[0;31m";
Log::endColorCode = "\033[0m";
} else {
Log::colorCodes[TRACE] = "";
Log::colorCodes[DEBUG] = "";
Log::colorCodes[INFO] = "";
Log::colorCodes[WARN] = "";
Log::colorCodes[ERROR] = "";
}
}
// Return the appropriate code from the colour map.
/// @todo Do the map::upper_limit thing to find nearest level...
return colorCodes[level];
}
Log::Level Log::getLevelFromName(const string& level) {
if (level == "TRACE") return TRACE;
if (level == "DEBUG") return DEBUG;
if (level == "INFO") return INFO;
if (level == "WARN") return WARN;
if (level == "ERROR") return ERROR;
throw Error("Couldn't create a log level from string '" + level + "'");
}
string Log::formatMessage(int level, const string& message) {
string out;
if (Log::useShellColors) {
out += getColorCode(level);
}
if (Log::showLoggerName) {
out += getName();
out += ": ";
}
if (Log::showLogLevel) {
out += Log::getLevelName(level);
out += " ";
}
if (Log::showTimestamp) {
time_t rawtime;
time(&rawtime);
char* timestr = ctime(&rawtime);
timestr[24] = ' ';
out += timestr;
out += " ";
}
if (Log::useShellColors) {
out += endColorCode;
}
out += " ";
out += message;
return out;
}
void Log::log(int level, const string& message) {
if (isActive(level)) {
cout << formatMessage(level, message) << endl;
}
}
ostream& operator<<(Log& log, int level) {
if (log.isActive(level)) {
cout << log.formatMessage(level, "");
return cout;
} else {
- return *(log._nostream);
+ static ostream devNull(nullptr);
+ return devNull;
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 2:41 PM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3804782
Default Alt Text
(11 KB)
Attached To
rRIVETHG rivethg
Event Timeline
Log In to Comment