27 #ifndef TOMOGRAPHER_TOOLS_LOGGERS_H 28 #define TOMOGRAPHER_TOOLS_LOGGERS_H 37 #include <type_traits> 40 #include <boost/algorithm/string.hpp> 54 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN 56 #define ENABLE_IF_Fn_CALLABLE_OSTREAM \ 57 typename std::enable_if<std::is_convertible<Fn,std::function<void(std::ostream&)> >::value, void>::type 170 inline int level()
const {
return _level; }
173 inline operator int()
const {
return _level; }
206 if (s ==
"LONGDEBUG") {
208 }
else if (s ==
"DEBUG") {
210 }
else if (s ==
"INFO") {
212 }
else if (s ==
"WARNING") {
214 }
else if (s ==
"ERROR") {
250 return (level <= baselevel);
260 template<
int Level,
int BaseLevel>
263 value = (Level <= BaseLevel)
337 HasFilterByOrigin = 0
350 template<
typename LoggerType>
358 namespace tomo_internal {
362 template<
bool hasOwnGetLevel>
363 class LoggerRuntimeLevel {
365 LoggerRuntimeLevel(
int level)
370 inline int level()
const 376 inline void setLogLevel(
int level)
388 class LoggerRuntimeLevel<true> {
390 LoggerRuntimeLevel(
int )
394 inline void setLogLevel(
int) {
395 tomographer_assert(0 &&
"Call to LoggerRuntimeLevel::setLogLevel() for Logger which defines HasOwnGetLevel=1!");
426 template<
typename Derived>
428 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
429 :
public tomo_internal::LoggerRuntimeLevel<LoggerTraits<Derived>::HasOwnGetLevel>
456 : tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>(level_)
468 inline void error(
const char * origin,
const char * fmt, ...);
476 inline void error(
const char * origin,
const std::string & msg);
483 template<
typename Fn>
484 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
485 error(
const char * origin, Fn f);
495 inline void warning(
const char * origin,
const char * fmt, ...);
503 inline void warning(
const char * origin,
const std::string & msg);
510 template<
typename Fn>
511 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
512 warning(
const char * origin, Fn f);
522 inline void info(
const char * origin,
const char * fmt, ...);
530 inline void info(
const char * origin,
const std::string & msg);
537 template<
typename Fn>
538 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
539 info(
const char * origin, Fn f);
559 inline void debug(
const char * origin,
const char * fmt, ...);
577 inline void debug(
const char * origin,
const std::string & msg);
606 template<
typename Fn>
607 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
608 debug(
const char * origin, Fn f);
618 inline void longdebug(
const char * origin,
const char * fmt, ...);
626 inline void longdebug(
const char * origin,
const std::string & msg);
633 template<
typename Fn>
634 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
635 longdebug(
const char * origin, Fn f);
648 inline void log(
int level,
const char * origin,
const char * fmt, ...);
658 inline void log(
int level,
const char * origin,
const std::string & msg);
668 template<
typename Fn>
669 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
670 log(
int level,
const char * origin, Fn f);
684 inline void log(
const char * origin,
const char * fmt, ...);
695 inline void log(
const char * origin,
const char * fmt,
va_list ap);
705 inline void log(
const char * origin,
const std::string & msg);
714 template<
int Level,
typename Fn>
715 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
716 log(
const char * origin, Fn f);
744 StaticMinimumSeverityLevel
760 return derived()->staticallyEnabledFor(level_) &&
764 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 789 TOMOGRAPHER_ENABLED_IF(!HasOwnGetLevel)
790 inline int getLevel()
const 793 return tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>::level();
796 TOMOGRAPHER_ENABLED_IF(HasOwnGetLevel)
797 inline int getLevel()
const 799 return derived()->level();
803 inline Derived * derived()
805 return static_cast<Derived*
>(
this);
807 inline const Derived * derived()
const 809 return static_cast<const Derived*
>(
this);
812 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 838 namespace tomo_internal {
841 template<
typename Derived,
bool derivedHasFilterByOrigin>
842 struct LoggerBaseHelperFilterByOrigin {
853 template<
typename Derived>
854 struct LoggerBaseHelperFilterByOrigin<Derived, true> {
858 return static_cast<const Derived*
>(loggerbase)->filterByOrigin(level, origin);
866 template<
typename Derived>
867 struct LoggerBaseHelperDynamic {
873 static_cast<Derived*
>(loggerbase)->emitLog(level, origin, msg);
876 "Warning in LoggerBaseHelperDynamic::call_emit_log(%d, \"%s\", msg):" 877 " Exception caught: %s\n",
878 level, origin, e.
what());
881 static inline bool test_should_emit(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin)
883 if ( ! static_cast<const Derived*>(loggerbase)->enabledFor(level) ) {
887 ::test_logger_filter(loggerbase, level, origin) ) {
893 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
896 if ( ! test_should_emit(loggerbase, level, origin) ) {
900 call_emit_log(loggerbase, level, origin, msg);
902 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
903 const char * fmt,
va_list ap)
throw()
905 if ( ! test_should_emit(loggerbase, level, origin) ) {
911 call_emit_log(loggerbase, level, origin, msg);
914 "Warning in LoggerBase::test_and_call_emit_log(%d, \"%s\", \"%s\", ...):" 915 " Exception caught for vfmts(): %s\n",
916 level, origin, fmt, e.
what());
919 template<
typename Fn>
921 ENABLE_IF_Fn_CALLABLE_OSTREAM
922 test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin, Fn f)
throw()
924 if ( ! test_should_emit(loggerbase, level, origin) ) {
931 call_emit_log(loggerbase, level, origin, sstr.
str());
933 std::fprintf(stderr,
"Warning in LoggerBase::test_and_call_emit_log(%d, \"%s\", f(ostream)):" 934 " Exception caught: %s\n",
935 level, origin, e.
what());
946 template<
typename Derived,
int Level,
bool isStaticallyDiscarded = false>
947 struct LoggerBaseHelperStatic2 {
948 template<
typename... Args>
949 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
950 Args... args)
throw()
952 LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(loggerbase, Level, origin, args...);
956 template<
typename Derived,
int Level>
957 struct LoggerBaseHelperStatic2<Derived, Level, true> {
958 template<
typename... Args>
959 static inline void test_and_call_emit_log(
LoggerBase<Derived> *,
const char *, Args...)
throw()
968 template<
typename Derived,
int Level>
969 struct LoggerBaseHelperStatic {
970 template<
typename... Args>
971 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
972 Args... args)
throw()
979 LoggerBaseHelperStatic2<
982 >::test_and_call_emit_log(
983 loggerbase, origin, args...
992 template<
typename Derived>
997 derived()->template log<ERROR>(origin, fmt, ap);
1001 template<
typename Derived>
1004 derived()->template log<ERROR>(origin, msg);
1007 template<
typename Derived>
1008 template<
typename Fn>
1009 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1012 derived()->template log<ERROR>(origin, f);
1016 template<
typename Derived>
1021 derived()->template log<WARNING>(origin, fmt, ap);
1025 template<
typename Derived>
1028 derived()->template log<WARNING>(origin, msg);
1031 template<
typename Derived>
1032 template<
typename Fn>
1033 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1036 derived()->template log<WARNING>(origin, f);
1039 template<
typename Derived>
1044 derived()->template log<INFO>(origin, fmt, ap);
1048 template<
typename Derived>
1051 derived()->template log<INFO>(origin, msg);
1054 template<
typename Derived>
1055 template<
typename Fn>
1056 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1059 derived()->template log<INFO>(origin, f);
1062 template<
typename Derived>
1067 derived()->template log<DEBUG>(origin, fmt, ap);
1071 template<
typename Derived>
1074 derived()->template log<DEBUG>(origin, msg);
1077 template<
typename Derived>
1078 template<
typename Fn>
1079 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1082 derived()->template log<DEBUG>(origin, f);
1085 template<
typename Derived>
1090 derived()->template log<LONGDEBUG>(origin, fmt, ap);
1094 template<
typename Derived>
1097 derived()->template log<LONGDEBUG>(origin, msg);
1100 template<
typename Derived>
1101 template<
typename Fn>
1102 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1105 derived()->template log<LONGDEBUG>(origin, f);
1109 template<
typename Derived>
1114 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, fmt, ap);
1118 template<
typename Derived>
1121 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, msg);
1124 template<
typename Derived>
1125 template<
typename Fn>
1126 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1129 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, f);
1133 template<
typename Derived>
1139 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1143 template<
typename Derived>
1147 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1150 template<
typename Derived>
1154 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, msg);
1157 template<
typename Derived>
1158 template<
int Level,
typename Fn>
1159 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1162 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, f);
1221 display_origin = display_origin_;
1224 inline void emitLog(
int level,
const char * origin,
const std::string & msg)
1245 if (fp != stdout && fp != stderr) {
1253 bool display_origin;
1271 StaticMinimumSeverityLevel = -1
1282 inline void emitLog(
int ,
const char * ,
const std::string & )
1326 inline void emitLog(
int ,
const char * origin,
const std::string& msg)
1329 << msg.
c_str() <<
"\n";
1358 return buffer.
str();
1368 template<
typename BaseLogger,
int Level>
1375 StaticMinimumSeverityLevel = Level,
1393 template<
typename BaseLogger,
int Level>
1397 BaseLogger & baselogger;
1412 baselogger.emitLog(level, origin, msg);
1418 return baselogger.level();
1422 template<
bool dummy = true>
1426 return baselogger.filterByOrigin(level, origin);
1431 namespace tomo_internal {
1441 while (s[k] == pattern[k]) {
1453 template<
typename BaseLogger>
1459 HasFilterByOrigin = 1
1483 template<
typename BaseLogger>
1487 BaseLogger & baselogger;
1500 baselogger(baselogger_),
1516 levels_set[origin_pattern] =
level;
1526 auto it = levels_set.
find(s);
1527 if (it == levels_set.
end()) {
1528 this->warning(
"OriginFilteredLogger<BaseLogger>::removeDomainSetting",
"domain not set: `%s'", s.
c_str());
1531 levels_set.
erase(it);
1553 baselogger.emitLog(level, origin, msg);
1570 int last_matched_length = 0;
1571 for (ConstIterator it = levels_set.
begin(); it != levels_set.
end(); ++it) {
1572 const int mlen = tomo_internal::matched_length((*it).first, s);
1573 if (mlen > last_matched_length) {
1574 loglevel = (*it).second;
1575 last_matched_length = mlen;
1578 if (loglevel == -1) {
1580 loglevel = baselogger.level();
1608 : origin_prefix(s), origin_prefix_add(
""), glue(gl) { }
1611 : origin_prefix(s), origin_prefix_add(s2), glue(gl) { }
1614 namespace tomo_internal {
1616 struct extractTomoOrigin_helper {
1620 return ( fn.substr_e(after_prelast_doublecolons, last_doublecolons) == fn.substr(last_doublecolons+2)
1630 return (prelast_doublecolons_found == std::string::npos) ? 0 : prelast_doublecolons_found+2;
1634 return last_doublecolons == std::string::npos || last_doublecolons == 0
1636 : step2(fn, last_doublecolons, afterprelast_doublecolons(fn.rfind(
"::", last_doublecolons-1)));
1641 return step1(fn, fn.rfind(
"::"));
1658 #define TOMO_ORIGIN Tomographer::Logger::tomo_internal::extractTomoOrigin(TOMO_FUNCTION) 1666 namespace tomo_internal {
1668 template<
typename BaseLoggerType>
1669 struct is_local_logger {
1672 template<
typename BaseLoggerType>
1677 template<
typename BaseLoggerType>
1678 struct local_logger_parent {
1681 template<
typename BaseLoggerType>
1683 typedef typename local_logger_parent<BaseLoggerType>::ParentType ParentType;
1688 template<
typename BaseLoggerType_>
1756 template<
typename BaseLoggerType_>
1771 BaseLoggerType & _baselogger;
1785 : _origin_prefix(origin_fn_name), _glue(
"::"), _baselogger(logger_)
1795 : _origin_prefix(origin_prefix), _glue(glue), _baselogger(logger_)
1804 : _origin_prefix(spec.origin_prefix.to_string()+spec.origin_prefix_add.to_string()),
1805 _glue(spec.glue.to_string()), _baselogger(logger_)
1813 : _origin_prefix(movecopy._origin_prefix), _glue(movecopy._glue),
1814 _baselogger(movecopy._baselogger)
1841 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 1859 typedef typename tomo_internal::local_logger_parent<BaseLoggerType>::ParentType ParentLoggerType;
1862 inline ParentLoggerType & parentLogger()
1864 return baseLogger();
1867 inline ParentLoggerType & parentLogger() {
1868 return baseLogger().parentLogger();
1910 PRINTF2_ARGS_SAFE
inline void longdebug(
const char * fmt, ...)
1911 {
va_list ap; va_start(ap, fmt); log<LONGDEBUG>(fmt, ap); va_end(ap); }
1916 PRINTF2_ARGS_SAFE
inline void debug(
const char * fmt, ...)
1917 {
va_list ap; va_start(ap, fmt); log<DEBUG>(fmt, ap); va_end(ap); }
1922 PRINTF2_ARGS_SAFE
inline void info(
const char * fmt, ...)
1923 {
va_list ap; va_start(ap, fmt); log<INFO>(fmt, ap); va_end(ap); }
1928 PRINTF2_ARGS_SAFE
inline void warning(
const char * fmt, ...)
1929 {
va_list ap; va_start(ap, fmt); log<WARNING>(fmt, ap); va_end(ap); }
1934 PRINTF2_ARGS_SAFE
inline void error(
const char * fmt, ...)
1935 {
va_list ap; va_start(ap, fmt); log<ERROR>(fmt, ap); va_end(ap); }
1941 template<
typename... Args>
1942 inline void longdebug(Args &&... a) { log<Tomographer::Logger::LONGDEBUG>(std::forward<Args>(a)...); }
1947 template<
typename... Args>
1948 inline void debug(Args &&... a) { log<Tomographer::Logger::DEBUG>(std::forward<Args>(a)...); }
1953 template<
typename... Args>
1954 inline void info(Args &&... a) { log<Tomographer::Logger::INFO>(std::forward<Args>(a)...); }
1959 template<
typename... Args>
1960 inline void warning(Args &&... a) { log<Tomographer::Logger::WARNING>(std::forward<Args>(a)...); }
1965 template<
typename... Args>
1966 inline void error(Args &&... a) { log<Tomographer::Logger::ERROR>(std::forward<Args>(a)...); }
1972 template<
int Level,
typename... Args>
1975 Base_::template log<Level>(
"", args...);
1991 return ( origin == NULL || origin[0] == 0
1993 : _origin_prefix + _glue + origin );
2001 _baselogger.emitLog(level, getSubOrigin(origin).c_str(), msg);
2007 return _baselogger.level();
2012 inline
bool filterByOrigin(
int level, const
char * origin)
2014 return _baselogger.filterByOrigin(level, getSubOrigin(origin).c_str());
2036 template<
typename BaseLoggerType>
2047 template<
typename BaseLoggerType>
2049 BaseLoggerType & baselogger)
2059 template<
typename BaseLoggerType>
Utilities for formatting strings.
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.
Log messages into an internal memory buffer.
Base namespace for the Tomographer project.
void debug(const char *fmt,...)
Generate a log message with level Logger::DEBUG (printf-like syntax)
constexpr LocalLoggerOriginSpec(const Tools::conststr &s, const Tools::conststr &s2, const Tools::conststr &gl)
complete constructor.
void clear()
Clears the internal memory buffer.
std::string originPrefix() const
The fixed origin specified at the constructor.
void debug(Args &&...a)
Generate a log message with level Logger::DEBUG.
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.
int level() const
Get the log level set for this logger.
LocalLogger(const std::string &origin_prefix, const std::string &glue, BaseLoggerType &logger_)
Construct a local logger.
std::string getContents() const
get the contents of the internal buffer
void error(const char *fmt,...)
Generate a log message with level Logger::ERROR (printf-like syntax)
std::string getSubOrigin(const char *origin) const
The full origin string to use for a sub-logger.
void log(int level, const char *origin, const char *fmt,...)
emit a log message at the given log level.
Highest severity possible.
void longdebug(Args &&...a)
Generate a log message with level Logger::LONGDEBUG.
const Tools::conststr glue
the glue to use in the local logger
void log(Args...args)
Generate a log message with level Level.
Logger that discards all messages.
std::string glue() const
The "glue" string to use to concatenate origins from sub-loggers.
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
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 setLogLevel(int level)
Store a new run-time log level.
void error(Args &&...a)
Generate a log message with level Logger::ERROR.
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.
void longdebug(const char *fmt,...)
Generate a log message with level Logger::LONGDEBUG (printf-like syntax)
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.
void warning(Args &&...a)
Generate a log message with level Logger::WARNING.
int level() const
Get the base logger's set level.
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.
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.
void info(const char *fmt,...)
Generate a log message with level Logger::INFO (printf-like syntax)
void info(Args &&...a)
Generate a log message with level Logger::INFO.
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
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()
int level() const
Get the stored level code. See LogLevelCode.
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.
bool enabledFor(int level_) const
Check whether messages at the given log level are enabled.
_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.
LogLevel(const char *s)
Construct a level using a string level name.
LogLevel(int level_=INFO)
Construct a level using an integer level code. See LogLevelCode.
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.
int level() const
Unconditionally return LOWEST_SEVERITY_LEVEL for the underlying logging engine.
LocalLogger(LocalLogger &&movecopy)
LocalLogger< LocalLogger< BaseLoggerType > > subLogger(const LocalLoggerOriginSpec &spec)
Create a sub-logger.
Information logging level.
std::string levelName() const
Get the stored level name.
A logger which filters entries according to where they originated from.
void warning(const char *fmt,...)
Generate a log message with level Logger::WARNING (printf-like syntax)