28 #ifndef TOMOGRAPHER_TOOLS_LOGGERS_H 29 #define TOMOGRAPHER_TOOLS_LOGGERS_H 38 #include <type_traits> 41 #include <boost/algorithm/string.hpp> 55 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN 57 #define ENABLE_IF_Fn_CALLABLE_OSTREAM \ 58 typename std::enable_if<std::is_convertible<Fn,std::function<void(std::ostream&)> >::value, void>::type 64 #error "The macro ERROR is defined. You may be on a Windows system. Make sure that <tomographer/tools/logger.h> is included BEFORE any windows-related header." 176 inline int level()
const {
return _level; }
179 inline operator int()
const {
return _level; }
212 if (s ==
"LONGDEBUG") {
214 }
else if (s ==
"DEBUG") {
216 }
else if (s ==
"INFO") {
218 }
else if (s ==
"WARNING") {
220 }
else if (s ==
"ERROR") {
256 return (level <= baselevel);
266 template<
int Level,
int BaseLevel>
269 value = (Level <= BaseLevel)
343 HasFilterByOrigin = 0
356 template<
typename LoggerType>
364 namespace tomo_internal {
368 template<
bool hasOwnGetLevel>
374 LoggerRuntimeLevel(
int level)
379 inline int level()
const 385 inline void setLogLevel(
int level)
397 class TOMOGRAPHER_EXPORT LoggerRuntimeLevel<true>
400 LoggerRuntimeLevel(
int )
404 inline void setLogLevel(
int) {
405 tomographer_assert(0 &&
"Call to LoggerRuntimeLevel::setLogLevel() for Logger which defines HasOwnGetLevel=1!");
436 template<
typename Derived>
438 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
439 :
public tomo_internal::LoggerRuntimeLevel<LoggerTraits<Derived>::HasOwnGetLevel>
466 : tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>(level_)
478 inline void error(
const char * origin,
const char * fmt, ...);
486 inline void error(
const char * origin,
const std::string & msg);
493 template<
typename Fn>
494 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
495 error(
const char * origin, Fn f);
505 inline void warning(
const char * origin,
const char * fmt, ...);
513 inline void warning(
const char * origin,
const std::string & msg);
520 template<
typename Fn>
521 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
522 warning(
const char * origin, Fn f);
532 inline void info(
const char * origin,
const char * fmt, ...);
540 inline void info(
const char * origin,
const std::string & msg);
547 template<
typename Fn>
548 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
549 info(
const char * origin, Fn f);
569 inline void debug(
const char * origin,
const char * fmt, ...);
587 inline void debug(
const char * origin,
const std::string & msg);
616 template<
typename Fn>
617 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
618 debug(
const char * origin, Fn f);
628 inline void longdebug(
const char * origin,
const char * fmt, ...);
636 inline void longdebug(
const char * origin,
const std::string & msg);
643 template<
typename Fn>
644 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
645 longdebug(
const char * origin, Fn f);
658 inline void log(
int level,
const char * origin,
const char * fmt, ...);
668 inline void log(
int level,
const char * origin,
const std::string & msg);
678 template<
typename Fn>
679 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
680 log(
int level,
const char * origin, Fn f);
694 inline void log(
const char * origin,
const char * fmt, ...);
705 inline void log(
const char * origin,
const char * fmt,
va_list ap);
715 inline void log(
const char * origin,
const std::string & msg);
724 template<
int Level,
typename Fn>
725 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
726 log(
const char * origin, Fn f);
754 StaticMinimumSeverityLevel
770 return derived()->staticallyEnabledFor(level_) &&
774 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 799 TOMOGRAPHER_ENABLED_IF(!HasOwnGetLevel)
800 inline int getLevel()
const 803 return tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>::level();
806 TOMOGRAPHER_ENABLED_IF(HasOwnGetLevel)
807 inline int getLevel()
const 809 return derived()->level();
813 inline Derived * derived()
815 return static_cast<Derived*
>(
this);
817 inline const Derived * derived()
const 819 return static_cast<const Derived*
>(
this);
822 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 848 namespace tomo_internal {
851 template<
typename Derived,
bool derivedHasFilterByOrigin>
852 struct LoggerBaseHelperFilterByOrigin {
863 template<
typename Derived>
864 struct LoggerBaseHelperFilterByOrigin<Derived, true> {
868 return static_cast<const Derived*
>(loggerbase)->filterByOrigin(level, origin);
876 template<
typename Derived>
877 struct LoggerBaseHelperDynamic {
878 static inline void call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
883 static_cast<Derived*
>(loggerbase)->emitLog(level, origin, msg);
891 static inline bool test_should_emit(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin)
893 if ( ! static_cast<const Derived*>(loggerbase)->enabledFor(level) ) {
897 ::test_logger_filter(loggerbase, level, origin) ) {
903 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
906 if ( ! test_should_emit(loggerbase, level, origin) ) {
910 call_emit_log(loggerbase, level, origin, msg);
912 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
915 if ( ! test_should_emit(loggerbase, level, origin) ) {
921 call_emit_log(loggerbase, level, origin, msg);
929 template<
typename Fn>
931 ENABLE_IF_Fn_CALLABLE_OSTREAM
932 test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin, Fn f)
934 if ( ! test_should_emit(loggerbase, level, origin) ) {
941 call_emit_log(loggerbase, level, origin, sstr.
str());
956 template<
typename Derived,
int Level,
bool isStaticallyDiscarded = false>
957 struct LoggerBaseHelperStatic2 {
958 template<
typename... Args>
959 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
962 LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(loggerbase, Level, origin, args...);
966 template<
typename Derived,
int Level>
967 struct LoggerBaseHelperStatic2<Derived, Level, true> {
968 template<
typename... Args>
978 template<
typename Derived,
int Level>
979 struct LoggerBaseHelperStatic {
980 template<
typename... Args>
981 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
989 LoggerBaseHelperStatic2<
992 >::test_and_call_emit_log(
993 loggerbase, origin, args...
1002 template<
typename Derived>
1007 derived()->template log<ERROR>(origin, fmt, ap);
1011 template<
typename Derived>
1014 derived()->template log<ERROR>(origin, msg);
1017 template<
typename Derived>
1018 template<
typename Fn>
1019 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1022 derived()->template log<ERROR>(origin, f);
1026 template<
typename Derived>
1031 derived()->template log<WARNING>(origin, fmt, ap);
1035 template<
typename Derived>
1038 derived()->template log<WARNING>(origin, msg);
1041 template<
typename Derived>
1042 template<
typename Fn>
1043 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1046 derived()->template log<WARNING>(origin, f);
1049 template<
typename Derived>
1054 derived()->template log<INFO>(origin, fmt, ap);
1058 template<
typename Derived>
1061 derived()->template log<INFO>(origin, msg);
1064 template<
typename Derived>
1065 template<
typename Fn>
1066 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1069 derived()->template log<INFO>(origin, f);
1072 template<
typename Derived>
1077 derived()->template log<DEBUG>(origin, fmt, ap);
1081 template<
typename Derived>
1084 derived()->template log<DEBUG>(origin, msg);
1087 template<
typename Derived>
1088 template<
typename Fn>
1089 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1092 derived()->template log<DEBUG>(origin, f);
1095 template<
typename Derived>
1100 derived()->template log<LONGDEBUG>(origin, fmt, ap);
1104 template<
typename Derived>
1107 derived()->template log<LONGDEBUG>(origin, msg);
1110 template<
typename Derived>
1111 template<
typename Fn>
1112 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1115 derived()->template log<LONGDEBUG>(origin, f);
1119 template<
typename Derived>
1124 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, fmt, ap);
1128 template<
typename Derived>
1131 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, msg);
1134 template<
typename Derived>
1135 template<
typename Fn>
1136 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1139 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, f);
1143 template<
typename Derived>
1149 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1153 template<
typename Derived>
1157 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1160 template<
typename Derived>
1164 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, msg);
1167 template<
typename Derived>
1168 template<
int Level,
typename Fn>
1169 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1172 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, f);
1205 FileLogger(FILE * fp_,
int level =
INFO,
bool display_origin_ =
true)
1231 display_origin = display_origin_;
1234 inline void emitLog(
int level,
const char * origin,
const std::string & msg)
1255 if (fp != stdout && fp != stderr) {
1263 bool display_origin;
1281 StaticMinimumSeverityLevel = -1
1292 inline void emitLog(
int ,
const char * ,
const std::string & )
1336 inline void emitLog(
int ,
const char * origin,
const std::string& msg)
1339 << msg.
c_str() <<
"\n";
1368 return buffer.str();
1378 template<
typename BaseLogger,
int Level>
1385 StaticMinimumSeverityLevel = Level,
1403 template<
typename BaseLogger,
int Level>
1407 BaseLogger & baselogger;
1422 baselogger.emitLog(level, origin, msg);
1428 return baselogger.level();
1432 template<
bool dummy = true>
1436 return baselogger.filterByOrigin(level, origin);
1441 namespace tomo_internal {
1451 while (s[k] == pattern[k]) {
1463 template<
typename BaseLogger>
1469 HasFilterByOrigin = 1
1493 template<
typename BaseLogger>
1498 BaseLogger & baselogger;
1511 baselogger(baselogger_),
1527 levels_set[origin_pattern] = level;
1537 auto it = levels_set.
find(s);
1538 if (it == levels_set.
end()) {
1539 this->warning(
"OriginFilteredLogger<BaseLogger>::removeDomainSetting",
"domain not set: `%s'", s.
c_str());
1542 levels_set.
erase(it);
1564 baselogger.emitLog(level, origin, msg);
1582 for (ConstIterator it = levels_set.
begin(); it != levels_set.
end(); ++it) {
1583 const std::size_t mlen = tomo_internal::matched_length((*it).first, s);
1584 if (mlen > last_matched_length) {
1585 loglevel = (*it).second;
1586 last_matched_length = mlen;
1589 if (loglevel == -1) {
1591 loglevel = baselogger.level();
1619 : origin_prefix(s), origin_prefix_add(
""), glue(gl) { }
1622 : origin_prefix(s), origin_prefix_add(s2), glue(gl) { }
1625 namespace tomo_internal {
1627 struct extractTomoOrigin_helper {
1631 return ( fn.substr_e(after_prelast_doublecolons, last_doublecolons) == fn.substr(last_doublecolons+2)
1641 return (prelast_doublecolons_found == std::string::npos) ? 0 : prelast_doublecolons_found+2;
1645 return last_doublecolons == std::string::npos || last_doublecolons == 0
1647 : step2(fn, last_doublecolons, afterprelast_doublecolons(fn.rfind(
"::", last_doublecolons-1)));
1652 return step1(fn, fn.rfind(
"::"));
1669 #define TOMO_ORIGIN Tomographer::Logger::tomo_internal::extractTomoOrigin(TOMO_FUNCTION) 1677 namespace tomo_internal {
1679 template<
typename BaseLoggerType>
1680 struct is_local_logger {
1683 template<
typename BaseLoggerType>
1688 template<
typename BaseLoggerType>
1689 struct local_logger_parent {
1692 template<
typename BaseLoggerType>
1694 typedef typename local_logger_parent<BaseLoggerType>::ParentType ParentType;
1699 template<
typename BaseLoggerType_>
1700 struct LoggerTraits<
LocalLogger<BaseLoggerType_> > :
public LoggerTraits<BaseLoggerType_>
1767 template<
typename BaseLoggerType_>
1769 :
public LoggerBase<LocalLogger<BaseLoggerType_> >
1783 BaseLoggerType & _baselogger;
1797 : Base_(), _origin_prefix(origin_fn_name), _glue(
"::"), _baselogger(logger_)
1799 this->longdebug(
"[begin]");
1808 : Base_(), _origin_prefix(origin_prefix), _glue(glue), _baselogger(logger_)
1810 this->longdebug(
"[begin]");
1818 : Base_(), _origin_prefix(spec.origin_prefix.to_string()+spec.origin_prefix_add.to_string()),
1819 _glue(spec.glue.to_string()), _baselogger(logger_)
1821 this->longdebug(
"[begin]");
1828 : Base_(), _origin_prefix(
std::move(movecopy._origin_prefix)), _glue(
std::move(movecopy._glue)),
1829 _baselogger(movecopy._baselogger)
1831 this->longdebug(
"[logger moved]");
1835 : Base_(), _origin_prefix(other._origin_prefix), _glue(other._glue),
1836 _baselogger(other._baselogger)
1838 this->longdebug(
"[logger copied]");
1843 this->longdebug(
"[done]");
1867 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 1885 typedef typename tomo_internal::local_logger_parent<BaseLoggerType>::ParentType ParentLoggerType;
1888 inline ParentLoggerType & parentLogger()
1890 return baseLogger();
1893 inline ParentLoggerType & parentLogger() {
1894 return baseLogger().parentLogger();
1936 PRINTF2_ARGS_SAFE
inline void longdebug(
const char * fmt, ...)
1937 {
va_list ap; va_start(ap, fmt); log<LONGDEBUG>(fmt, ap); va_end(ap); }
1942 PRINTF2_ARGS_SAFE
inline void debug(
const char * fmt, ...)
1943 {
va_list ap; va_start(ap, fmt); log<DEBUG>(fmt, ap); va_end(ap); }
1948 PRINTF2_ARGS_SAFE
inline void info(
const char * fmt, ...)
1949 {
va_list ap; va_start(ap, fmt); log<INFO>(fmt, ap); va_end(ap); }
1954 PRINTF2_ARGS_SAFE
inline void warning(
const char * fmt, ...)
1955 {
va_list ap; va_start(ap, fmt); log<WARNING>(fmt, ap); va_end(ap); }
1960 PRINTF2_ARGS_SAFE
inline void error(
const char * fmt, ...)
1961 {
va_list ap; va_start(ap, fmt); log<ERROR>(fmt, ap); va_end(ap); }
1967 template<
typename... Args>
1968 inline void longdebug(Args &&... a) { log<Tomographer::Logger::LONGDEBUG>(std::forward<Args>(a)...); }
1973 template<
typename... Args>
1974 inline void debug(Args &&... a) { log<Tomographer::Logger::DEBUG>(std::forward<Args>(a)...); }
1979 template<
typename... Args>
1980 inline void info(Args &&... a) { log<Tomographer::Logger::INFO>(std::forward<Args>(a)...); }
1985 template<
typename... Args>
1986 inline void warning(Args &&... a) { log<Tomographer::Logger::WARNING>(std::forward<Args>(a)...); }
1991 template<
typename... Args>
1992 inline void error(Args &&... a) { log<Tomographer::Logger::ERROR>(std::forward<Args>(a)...); }
1998 template<
int Level,
typename... Args>
2001 Base_::template log<Level>(
"", args...);
2017 return ( origin == NULL || origin[0] == 0
2019 : _origin_prefix + _glue + origin );
2027 _baselogger.emitLog(level, getSubOrigin(origin).c_str(), msg);
2033 return _baselogger.level();
2038 inline
bool filterByOrigin(
int level, const
char * origin)
2040 return _baselogger.filterByOrigin(level, getSubOrigin(origin).c_str());
2062 template<
typename BaseLoggerType>
2073 template<
typename BaseLoggerType>
2075 BaseLoggerType & baselogger)
2085 template<
typename BaseLoggerType>
Utilities for formatting strings.
std::string originPrefix() const
The fixed origin specified at the constructor.
Simple logger class which logs everything into a given FILE pointer.
static bool staticallyEnabledFor(int level)
Check whether the logger is statically disabled for some levels.
Local logger: avoid having to repeat origin at each emitted message.
Lowest severity possible.
void debug(Args &&... a)
Generate a log message with level Logger::DEBUG.
void info(Args &&... a)
Generate a log message with level Logger::INFO.
Log messages into an internal memory buffer.
Base namespace for the Tomographer project.
constexpr LocalLoggerOriginSpec(const Tools::conststr &s, const Tools::conststr &s2, const Tools::conststr &gl)
complete constructor.
void clear()
Clears the internal memory buffer.
void setDomainLevel(const std::string &origin_pattern, int level)
Set a rule to log messages based on their origin.
void emitLog(int level, const char *origin, const std::string &msg)
Emit a log message (relay to base logger).
LocalLogger< BaseLoggerType > makeLocalLogger(const std::string &origin_fn_name, BaseLoggerType &baselogger)
Create a local logger.
void setLevel(std::string s)
Set the level to the given level name. See class doc.
LocalLogger(const std::string &origin_prefix, const std::string &glue, BaseLoggerType &logger_)
Construct a local logger.
void log(int level, const char *origin, const char *fmt,...)
emit a log message at the given log level.
Highest severity possible.
const Tools::conststr glue
the glue to use in the local logger
Logger that discards all messages.
Object which stores a log level and can initialize from a string.
int level() const
Get the base logger's set level.
void error(const char *origin, const char *fmt,...)
emit an error message
int level() const
Get the stored level code. See LogLevelCode.
bool filterByOrigin(int level, const char *origin) const
Message filtering by origin implementation.
OriginFilteredLogger(BaseLogger &baselogger_)
Constructor based on a base logger reference.
ParentLoggerType & parentLogger()
The parent logger responsible for actually emitting the messages in some useful way.
void setLevel(int level)
Set the level to the given level code. See class doc and LogLevelCode.
void removeDomainSetting(const std::string &s)
Remove a rule set by setDomainLevel()
void longdebug(Args &&... a)
Generate a log message with level Logger::LONGDEBUG.
void setLogLevel(int level)
Store a new run-time log level.
std::string getSubOrigin(const char *origin) const
The full origin string to use for a sub-logger.
std::string levelName() const
Get the stored level name.
LocalLogger< LocalLogger< BaseLoggerType > > subLogger(const std::string &new_prefix)
Create a sub-logger.
Helper for statically determining if Level is at least as severe as BaseLevel.
BaseLoggerType & baseLogger()
The base logger type specified to the constructor.
std::string glue() const
The "glue" string to use to concatenate origins from sub-loggers.
int level() const
Get the base logger's set level.
bool enabledFor(int level_) const
Check whether messages at the given log level are enabled.
void warning(Args &&... a)
Generate a log message with level Logger::WARNING.
Logger which statically discards any messages less important than a fixed severity.
constexpr LocalLoggerOriginSpec(const Tools::conststr &s, const Tools::conststr &gl)
constructor. origin_prefix_add is left blank.
BaseLoggerType_ BaseLoggerType
The base logger type (see class documentation)
MinimumSeverityLogger(BaseLogger &baselogger_)
Constructor from a base logger.
void setDisplayOrigin(bool display_origin_)
Tool to specify arguments to LocalLogger.
void error(Args &&... a)
Generate a log message with level Logger::ERROR.
const Tools::conststr origin_prefix
Origin prefix for the local logger.
void emitLog(int level, const char *origin, const std::string &msg)
Emit a log by relaying to the base logger.
std::ostream & operator<<(std::ostream &str, const LogLevel &l)
C++ output stream operator for LogLevel.
LocalLogger< LocalLogger< BaseLoggerType > > subLogger(const std::string &new_prefix, const std::string &new_glue)
Create a sub-logger.
void warning(const char *origin, const char *fmt,...)
emit a warning message
A constexpr string type, suitable for basic compile-time string processing.
void debug(const char *origin, const char *fmt,...)
emit an debug message
LocalLogger(const LocalLogger &other)
Make the local-logger copyable – there's nothing wrong with that.
Default traits for Logger implementations.
void emitLog(int level, const char *origin, const std::string &msg)
Emit a log by relaying to the base logger.
static bool staticallyEnabledFor()
Static version of staticallyEnabledFor()
void log(Args... args)
Generate a log message with level Level.
void longdebug(const char *origin, const char *fmt,...)
emit a very verbose debugging message
void setLevel(int level)
Changes the runtime log level to a new value.
bool isAtLeastOfSeverity(int level, int baselevel)
Helper to compare severity levels.
void info(const char *origin, const char *fmt,...)
emit an information/notice message
Traits template struct to be specialized for specific Logger implementations.
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
_PARENT_LOGGER_TYPE ParentLoggerType
Type of the parent logger type, ultimately responsible for actually emitting the messages in some use...
LocalLogger(const LocalLoggerOriginSpec &spec, BaseLoggerType &logger_)
Construct a local logger.
std::istream & operator>>(std::istream &str, LogLevel &l)
C++ input stream operator for LogLevel.
std::enable_if< dummy &&LoggerTraits< BaseLogger >::HasFilterByOrigin, bool > filterByOrigin(int level, const char *origin)
If relevant for the base logger, filter the messages by origin from the base logger.
LoggerBase(int level_=INFO)
Construct the base logger object.
LogLevelCode
Possible logging levels.
const Tools::conststr origin_prefix_add
optionally some string to append to origin_prefix
Long Debug logging level.
std::string getContents() const
get the contents of the internal buffer
LogLevel(const char *s)
Construct a level using a string level name.
int level() const
Unconditionally return LOWEST_SEVERITY_LEVEL for the underlying logging engine.
LogLevel(int level_=INFO)
Construct a level using an integer level code. See LogLevelCode.
int level() const
Get the log level set for this logger.
LogLevel(const std::string &s)
Construct a level using a string level name.
LocalLogger(const std::string &origin_fn_name, BaseLoggerType &logger_)
Construct a local logger.
LocalLogger(LocalLogger &&movecopy)
LocalLogger< LocalLogger< BaseLoggerType > > subLogger(const LocalLoggerOriginSpec &spec)
Create a sub-logger.
Information logging level.
#define tomographer_assert(...)
Assertion test macro.
A logger which filters entries according to where they originated from.