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 171 inline int level()
const {
return _level; }
174 inline operator int()
const {
return _level; }
207 if (s ==
"LONGDEBUG") {
209 }
else if (s ==
"DEBUG") {
211 }
else if (s ==
"INFO") {
213 }
else if (s ==
"WARNING") {
215 }
else if (s ==
"ERROR") {
251 return (level <= baselevel);
261 template<
int Level,
int BaseLevel>
264 value = (Level <= BaseLevel)
338 HasFilterByOrigin = 0
351 template<
typename LoggerType>
359 namespace tomo_internal {
363 template<
bool hasOwnGetLevel>
364 class LoggerRuntimeLevel {
366 LoggerRuntimeLevel(
int level)
371 inline int level()
const 377 inline void setLogLevel(
int level)
389 class LoggerRuntimeLevel<true> {
391 LoggerRuntimeLevel(
int )
395 inline void setLogLevel(
int) {
396 tomographer_assert(0 &&
"Call to LoggerRuntimeLevel::setLogLevel() for Logger which defines HasOwnGetLevel=1!");
427 template<
typename Derived>
429 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
430 :
public tomo_internal::LoggerRuntimeLevel<LoggerTraits<Derived>::HasOwnGetLevel>
457 : tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>(level_)
469 inline void error(
const char * origin,
const char * fmt, ...);
477 inline void error(
const char * origin,
const std::string & msg);
484 template<
typename Fn>
485 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
486 error(
const char * origin, Fn f);
496 inline void warning(
const char * origin,
const char * fmt, ...);
504 inline void warning(
const char * origin,
const std::string & msg);
511 template<
typename Fn>
512 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
513 warning(
const char * origin, Fn f);
523 inline void info(
const char * origin,
const char * fmt, ...);
531 inline void info(
const char * origin,
const std::string & msg);
538 template<
typename Fn>
539 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
540 info(
const char * origin, Fn f);
560 inline void debug(
const char * origin,
const char * fmt, ...);
578 inline void debug(
const char * origin,
const std::string & msg);
607 template<
typename Fn>
608 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
609 debug(
const char * origin, Fn f);
619 inline void longdebug(
const char * origin,
const char * fmt, ...);
627 inline void longdebug(
const char * origin,
const std::string & msg);
634 template<
typename Fn>
635 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
636 longdebug(
const char * origin, Fn f);
649 inline void log(
int level,
const char * origin,
const char * fmt, ...);
659 inline void log(
int level,
const char * origin,
const std::string & msg);
669 template<
typename Fn>
670 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
671 log(
int level,
const char * origin, Fn f);
685 inline void log(
const char * origin,
const char * fmt, ...);
696 inline void log(
const char * origin,
const char * fmt,
va_list ap);
706 inline void log(
const char * origin,
const std::string & msg);
715 template<
int Level,
typename Fn>
716 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
717 log(
const char * origin, Fn f);
745 StaticMinimumSeverityLevel
761 return derived()->staticallyEnabledFor(level_) &&
765 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 790 TOMOGRAPHER_ENABLED_IF(!HasOwnGetLevel)
791 inline int getLevel()
const 794 return tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>::level();
797 TOMOGRAPHER_ENABLED_IF(HasOwnGetLevel)
798 inline int getLevel()
const 800 return derived()->level();
804 inline Derived * derived()
806 return static_cast<Derived*
>(
this);
808 inline const Derived * derived()
const 810 return static_cast<const Derived*
>(
this);
813 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 839 namespace tomo_internal {
842 template<
typename Derived,
bool derivedHasFilterByOrigin>
843 struct LoggerBaseHelperFilterByOrigin {
854 template<
typename Derived>
855 struct LoggerBaseHelperFilterByOrigin<Derived, true> {
859 return static_cast<const Derived*
>(loggerbase)->filterByOrigin(level, origin);
867 template<
typename Derived>
868 struct LoggerBaseHelperDynamic {
874 static_cast<Derived*
>(loggerbase)->emitLog(level, origin, msg);
882 static inline bool test_should_emit(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin)
884 if ( ! static_cast<const Derived*>(loggerbase)->enabledFor(level) ) {
888 ::test_logger_filter(loggerbase, level, origin) ) {
894 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
897 if ( ! test_should_emit(loggerbase, level, origin) ) {
901 call_emit_log(loggerbase, level, origin, msg);
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) ) {
912 call_emit_log(loggerbase, level, origin, msg);
920 template<
typename Fn>
922 ENABLE_IF_Fn_CALLABLE_OSTREAM
923 test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
int level,
const char * origin, Fn f)
925 if ( ! test_should_emit(loggerbase, level, origin) ) {
932 call_emit_log(loggerbase, level, origin, sstr.
str());
947 template<
typename Derived,
int Level,
bool isStaticallyDiscarded = false>
948 struct LoggerBaseHelperStatic2 {
949 template<
typename... Args>
950 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
953 LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(loggerbase, Level, origin, args...);
957 template<
typename Derived,
int Level>
958 struct LoggerBaseHelperStatic2<Derived, Level, true> {
959 template<
typename... Args>
969 template<
typename Derived,
int Level>
970 struct LoggerBaseHelperStatic {
971 template<
typename... Args>
972 static inline void test_and_call_emit_log(
LoggerBase<Derived> * loggerbase,
const char * origin,
980 LoggerBaseHelperStatic2<
983 >::test_and_call_emit_log(
984 loggerbase, origin, args...
993 template<
typename Derived>
998 derived()->template log<ERROR>(origin, fmt, ap);
1002 template<
typename Derived>
1005 derived()->template log<ERROR>(origin, msg);
1008 template<
typename Derived>
1009 template<
typename Fn>
1010 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1013 derived()->template log<ERROR>(origin, f);
1017 template<
typename Derived>
1022 derived()->template log<WARNING>(origin, fmt, ap);
1026 template<
typename Derived>
1029 derived()->template log<WARNING>(origin, msg);
1032 template<
typename Derived>
1033 template<
typename Fn>
1034 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1037 derived()->template log<WARNING>(origin, f);
1040 template<
typename Derived>
1045 derived()->template log<INFO>(origin, fmt, ap);
1049 template<
typename Derived>
1052 derived()->template log<INFO>(origin, msg);
1055 template<
typename Derived>
1056 template<
typename Fn>
1057 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1060 derived()->template log<INFO>(origin, f);
1063 template<
typename Derived>
1068 derived()->template log<DEBUG>(origin, fmt, ap);
1072 template<
typename Derived>
1075 derived()->template log<DEBUG>(origin, msg);
1078 template<
typename Derived>
1079 template<
typename Fn>
1080 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1083 derived()->template log<DEBUG>(origin, f);
1086 template<
typename Derived>
1091 derived()->template log<LONGDEBUG>(origin, fmt, ap);
1095 template<
typename Derived>
1098 derived()->template log<LONGDEBUG>(origin, msg);
1101 template<
typename Derived>
1102 template<
typename Fn>
1103 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1106 derived()->template log<LONGDEBUG>(origin, f);
1110 template<
typename Derived>
1115 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, fmt, ap);
1119 template<
typename Derived>
1122 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, msg);
1125 template<
typename Derived>
1126 template<
typename Fn>
1127 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1130 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, f);
1134 template<
typename Derived>
1140 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1144 template<
typename Derived>
1148 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1151 template<
typename Derived>
1155 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, msg);
1158 template<
typename Derived>
1159 template<
int Level,
typename Fn>
1160 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1163 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, f);
1222 display_origin = display_origin_;
1225 inline void emitLog(
int level,
const char * origin,
const std::string & msg)
1246 if (fp != stdout && fp != stderr) {
1254 bool display_origin;
1272 StaticMinimumSeverityLevel = -1
1283 inline void emitLog(
int ,
const char * ,
const std::string & )
1327 inline void emitLog(
int ,
const char * origin,
const std::string& msg)
1330 << msg.
c_str() <<
"\n";
1359 return buffer.str();
1369 template<
typename BaseLogger,
int Level>
1376 StaticMinimumSeverityLevel = Level,
1394 template<
typename BaseLogger,
int Level>
1398 BaseLogger & baselogger;
1413 baselogger.emitLog(level, origin, msg);
1419 return baselogger.level();
1423 template<
bool dummy = true>
1427 return baselogger.filterByOrigin(level, origin);
1432 namespace tomo_internal {
1442 while (s[k] == pattern[k]) {
1454 template<
typename BaseLogger>
1460 HasFilterByOrigin = 1
1484 template<
typename BaseLogger>
1489 BaseLogger & baselogger;
1502 baselogger(baselogger_),
1518 levels_set[origin_pattern] =
level;
1528 auto it = levels_set.
find(s);
1529 if (it == levels_set.
end()) {
1530 this->warning(
"OriginFilteredLogger<BaseLogger>::removeDomainSetting",
"domain not set: `%s'", s.
c_str());
1533 levels_set.
erase(it);
1555 baselogger.emitLog(level, origin, msg);
1573 for (ConstIterator it = levels_set.
begin(); it != levels_set.
end(); ++it) {
1574 const std::size_t mlen = tomo_internal::matched_length((*it).first, s);
1575 if (mlen > last_matched_length) {
1576 loglevel = (*it).second;
1577 last_matched_length = mlen;
1580 if (loglevel == -1) {
1582 loglevel = baselogger.level();
1610 : origin_prefix(s), origin_prefix_add(
""), glue(gl) { }
1613 : origin_prefix(s), origin_prefix_add(s2), glue(gl) { }
1616 namespace tomo_internal {
1618 struct extractTomoOrigin_helper {
1622 return ( fn.substr_e(after_prelast_doublecolons, last_doublecolons) == fn.substr(last_doublecolons+2)
1632 return (prelast_doublecolons_found == std::string::npos) ? 0 : prelast_doublecolons_found+2;
1636 return last_doublecolons == std::string::npos || last_doublecolons == 0
1638 : step2(fn, last_doublecolons, afterprelast_doublecolons(fn.rfind(
"::", last_doublecolons-1)));
1643 return step1(fn, fn.rfind(
"::"));
1660 #define TOMO_ORIGIN Tomographer::Logger::tomo_internal::extractTomoOrigin(TOMO_FUNCTION) 1668 namespace tomo_internal {
1670 template<
typename BaseLoggerType>
1671 struct is_local_logger {
1674 template<
typename BaseLoggerType>
1679 template<
typename BaseLoggerType>
1680 struct local_logger_parent {
1683 template<
typename BaseLoggerType>
1685 typedef typename local_logger_parent<BaseLoggerType>::ParentType ParentType;
1690 template<
typename BaseLoggerType_>
1758 template<
typename BaseLoggerType_>
1760 :
public LoggerBase<LocalLogger<BaseLoggerType_> >
1774 BaseLoggerType & _baselogger;
1788 : Base_(), _origin_prefix(origin_fn_name), _glue(
"::"), _baselogger(logger_)
1790 this->longdebug(
"[begin]");
1799 : Base_(), _origin_prefix(origin_prefix), _glue(glue), _baselogger(logger_)
1801 this->longdebug(
"[begin]");
1809 : Base_(), _origin_prefix(spec.origin_prefix.to_string()+spec.origin_prefix_add.to_string()),
1810 _glue(spec.glue.to_string()), _baselogger(logger_)
1812 this->longdebug(
"[begin]");
1819 : Base_(), _origin_prefix(
std::move(movecopy._origin_prefix)), _glue(
std::move(movecopy._glue)),
1820 _baselogger(movecopy._baselogger)
1822 this->longdebug(
"[logger moved]");
1826 : Base_(), _origin_prefix(other._origin_prefix), _glue(other._glue),
1827 _baselogger(other._baselogger)
1829 this->longdebug(
"[logger copied]");
1834 this->longdebug(
"[done]");
1858 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN 1876 typedef typename tomo_internal::local_logger_parent<BaseLoggerType>::ParentType ParentLoggerType;
1879 inline ParentLoggerType & parentLogger()
1881 return baseLogger();
1884 inline ParentLoggerType & parentLogger() {
1885 return baseLogger().parentLogger();
1927 PRINTF2_ARGS_SAFE
inline void longdebug(
const char * fmt, ...)
1928 {
va_list ap; va_start(ap, fmt); log<LONGDEBUG>(fmt, ap); va_end(ap); }
1933 PRINTF2_ARGS_SAFE
inline void debug(
const char * fmt, ...)
1934 {
va_list ap; va_start(ap, fmt); log<DEBUG>(fmt, ap); va_end(ap); }
1939 PRINTF2_ARGS_SAFE
inline void info(
const char * fmt, ...)
1940 {
va_list ap; va_start(ap, fmt); log<INFO>(fmt, ap); va_end(ap); }
1945 PRINTF2_ARGS_SAFE
inline void warning(
const char * fmt, ...)
1946 {
va_list ap; va_start(ap, fmt); log<WARNING>(fmt, ap); va_end(ap); }
1951 PRINTF2_ARGS_SAFE
inline void error(
const char * fmt, ...)
1952 {
va_list ap; va_start(ap, fmt); log<ERROR>(fmt, ap); va_end(ap); }
1958 template<
typename... Args>
1959 inline void longdebug(Args &&... a) { log<Tomographer::Logger::LONGDEBUG>(std::forward<Args>(a)...); }
1964 template<
typename... Args>
1965 inline void debug(Args &&... a) { log<Tomographer::Logger::DEBUG>(std::forward<Args>(a)...); }
1970 template<
typename... Args>
1971 inline void info(Args &&... a) { log<Tomographer::Logger::INFO>(std::forward<Args>(a)...); }
1976 template<
typename... Args>
1977 inline void warning(Args &&... a) { log<Tomographer::Logger::WARNING>(std::forward<Args>(a)...); }
1982 template<
typename... Args>
1983 inline void error(Args &&... a) { log<Tomographer::Logger::ERROR>(std::forward<Args>(a)...); }
1989 template<
int Level,
typename... Args>
1992 Base_::template log<Level>(
"", args...);
2008 return ( origin == NULL || origin[0] == 0
2010 : _origin_prefix + _glue + origin );
2018 _baselogger.emitLog(level, getSubOrigin(origin).c_str(), msg);
2024 return _baselogger.level();
2029 inline
bool filterByOrigin(
int level, const
char * origin)
2031 return _baselogger.filterByOrigin(level, getSubOrigin(origin).c_str());
2053 template<
typename BaseLoggerType>
2064 template<
typename BaseLoggerType>
2066 BaseLoggerType & baselogger)
2076 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.