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
168 inline int level()
const {
return _level; }
171 inline operator int()
const {
return _level; }
204 if (s ==
"LONGDEBUG") {
206 }
else if (s ==
"DEBUG") {
208 }
else if (s ==
"INFO") {
210 }
else if (s ==
"WARNING") {
212 }
else if (s ==
"ERROR") {
248 return (level <= baselevel);
258 template<
int Level,
int BaseLevel>
261 value = (Level <= BaseLevel)
335 HasFilterByOrigin = 0
348 template<
typename LoggerType>
356 namespace tomo_internal {
360 template<
bool hasOwnGetLevel>
361 class LoggerRuntimeLevel {
363 LoggerRuntimeLevel(
int level)
368 inline int level()
const
374 inline void setLogLevel(
int level)
386 class LoggerRuntimeLevel<true> {
388 LoggerRuntimeLevel(
int )
392 inline void setLogLevel(
int) {
393 assert(0 &&
"Call to LoggerRuntimeLevel::setLogLevel() for Logger which defines HasOwnGetLevel=1!");
423 template<
typename Derived>
425 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
426 :
public tomo_internal::LoggerRuntimeLevel<LoggerTraits<Derived>::HasOwnGetLevel>
453 : tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>(level_)
465 inline void error(
const char * origin,
const char * fmt, ...);
473 inline void error(
const char * origin,
const std::string & msg);
480 template<
typename Fn>
481 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
482 error(
const char * origin, Fn f);
492 inline void warning(
const char * origin,
const char * fmt, ...);
500 inline void warning(
const char * origin,
const std::string & msg);
507 template<
typename Fn>
508 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
509 warning(
const char * origin, Fn f);
519 inline void info(
const char * origin,
const char * fmt, ...);
527 inline void info(
const char * origin,
const std::string & msg);
534 template<
typename Fn>
535 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
536 info(
const char * origin, Fn f);
556 inline void debug(
const char * origin,
const char * fmt, ...);
574 inline void debug(
const char * origin,
const std::string & msg);
603 template<
typename Fn>
604 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
605 debug(
const char * origin, Fn f);
615 inline void longdebug(
const char * origin,
const char * fmt, ...);
623 inline void longdebug(
const char * origin,
const std::string & msg);
630 template<
typename Fn>
631 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
632 longdebug(
const char * origin, Fn f);
645 inline void log(
int level,
const char * origin,
const char * fmt, ...);
655 inline void log(
int level,
const char * origin,
const std::string & msg);
665 template<
typename Fn>
666 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
667 log(
int level,
const char * origin, Fn f);
681 inline void log(
const char * origin,
const char * fmt, ...);
692 inline void log(
const char * origin,
const char * fmt,
va_list ap);
702 inline void log(
const char * origin,
const std::string & msg);
711 template<
int Level,
typename Fn>
712 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
713 log(
const char * origin, Fn f);
741 StaticMinimumSeverityLevel
757 return derived()->statically_enabled_for(level_) &&
761 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN
786 template<
bool dummy =
true,
788 inline int getLevel()
const
791 return tomo_internal::LoggerRuntimeLevel<HasOwnGetLevel>::level();
794 template<
bool dummy =
true,
796 inline int getLevel()
const
798 return derived()->level();
802 inline Derived * derived()
804 return static_cast<Derived*
>(
this);
806 inline const Derived * derived()
const
808 return static_cast<const Derived*
>(
this);
811 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN
837 namespace tomo_internal {
840 template<
typename Derived,
bool derivedHasFilterByOrigin>
841 struct LoggerBaseHelperFilterByOrigin {
842 static inline bool test_logger_filter(LoggerBase<Derived> * ,
int ,
852 template<
typename Derived>
853 struct LoggerBaseHelperFilterByOrigin<Derived, true> {
854 static inline bool test_logger_filter(LoggerBase<Derived> * loggerbase,
int level,
857 return static_cast<const Derived*
>(loggerbase)->filter_by_origin(level, origin);
865 template<
typename Derived>
866 struct LoggerBaseHelperDynamic {
867 static inline void call_emit_log(LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
872 static_cast<Derived*
>(loggerbase)->emit_log(level, origin, msg);
875 "Warning in LoggerBaseHelperDynamic::call_emit_log(%d, \"%s\", msg):"
876 " Exception caught: %s\n",
877 level, origin, e.
what());
880 static inline bool test_should_emit(LoggerBase<Derived> * loggerbase,
int level,
const char * origin)
882 if ( ! static_cast<const Derived*>(loggerbase)->enabled_for(level) ) {
885 if ( ! LoggerBaseHelperFilterByOrigin<Derived, LoggerTraits<Derived>::HasFilterByOrigin>
886 ::test_logger_filter(loggerbase, level, origin) ) {
892 static inline void test_and_call_emit_log(LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
895 if ( ! test_should_emit(loggerbase, level, origin) ) {
899 call_emit_log(loggerbase, level, origin, msg);
901 static inline void test_and_call_emit_log(LoggerBase<Derived> * loggerbase,
int level,
const char * origin,
902 const char * fmt,
va_list ap)
throw()
904 if ( ! test_should_emit(loggerbase, level, origin) ) {
910 call_emit_log(loggerbase, level, origin, msg);
913 "Warning in LoggerBase::test_and_call_emit_log(%d, \"%s\", \"%s\", ...):"
914 " Exception caught for vfmts(): %s\n",
915 level, origin, fmt, e.
what());
918 template<
typename Fn>
920 ENABLE_IF_Fn_CALLABLE_OSTREAM
921 test_and_call_emit_log(LoggerBase<Derived> * loggerbase,
int level,
const char * origin, Fn f)
throw()
923 if ( ! test_should_emit(loggerbase, level, origin) ) {
930 call_emit_log(loggerbase, level, origin, sstr.
str());
932 std::fprintf(stderr,
"Warning in LoggerBase::test_and_call_emit_log(%d, \"%s\", f(ostream)):"
933 " Exception caught: %s\n",
934 level, origin, e.
what());
945 template<
typename Derived,
int Level,
bool isStaticallyDiscarded = false>
946 struct LoggerBaseHelperStatic2 {
947 template<
typename... Args>
948 static inline void test_and_call_emit_log(LoggerBase<Derived> * loggerbase,
const char * origin,
949 Args... args) throw()
951 LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(loggerbase, Level, origin, args...);
955 template<
typename Derived,
int Level>
956 struct LoggerBaseHelperStatic2<Derived, Level, true> {
957 template<
typename... Args>
958 static inline void test_and_call_emit_log(LoggerBase<Derived> *,
const char *, Args...) throw()
967 template<
typename Derived,
int Level>
968 struct LoggerBaseHelperStatic {
969 template<
typename... Args>
970 static inline void test_and_call_emit_log(LoggerBase<Derived> * loggerbase,
const char * origin,
971 Args... args) throw()
978 LoggerBaseHelperStatic2<
980 ! static_is_at_least_of_severity<Level, LoggerTraits<Derived>::StaticMinimumSeverityLevel>::value
981 >::test_and_call_emit_log(
982 loggerbase, origin, args...
991 template<
typename Derived>
996 derived()->template log<ERROR>(origin, fmt, ap);
1000 template<
typename Derived>
1003 derived()->template log<ERROR>(origin, msg);
1006 template<
typename Derived>
1007 template<
typename Fn>
1008 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1011 derived()->template log<ERROR>(origin, f);
1015 template<
typename Derived>
1020 derived()->template log<WARNING>(origin, fmt, ap);
1024 template<
typename Derived>
1027 derived()->template log<WARNING>(origin, msg);
1030 template<
typename Derived>
1031 template<
typename Fn>
1032 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1035 derived()->template log<WARNING>(origin, f);
1038 template<
typename Derived>
1043 derived()->template log<INFO>(origin, fmt, ap);
1047 template<
typename Derived>
1050 derived()->template log<INFO>(origin, msg);
1053 template<
typename Derived>
1054 template<
typename Fn>
1055 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1058 derived()->template log<INFO>(origin, f);
1061 template<
typename Derived>
1066 derived()->template log<DEBUG>(origin, fmt, ap);
1070 template<
typename Derived>
1073 derived()->template log<DEBUG>(origin, msg);
1076 template<
typename Derived>
1077 template<
typename Fn>
1078 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1081 derived()->template log<DEBUG>(origin, f);
1084 template<
typename Derived>
1089 derived()->template log<LONGDEBUG>(origin, fmt, ap);
1093 template<
typename Derived>
1096 derived()->template log<LONGDEBUG>(origin, msg);
1099 template<
typename Derived>
1100 template<
typename Fn>
1101 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1104 derived()->template log<LONGDEBUG>(origin, f);
1108 template<
typename Derived>
1113 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, fmt, ap);
1117 template<
typename Derived>
1120 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, msg);
1123 template<
typename Derived>
1124 template<
typename Fn>
1125 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1128 tomo_internal::LoggerBaseHelperDynamic<Derived>::test_and_call_emit_log(
this, level, origin, f);
1132 template<
typename Derived>
1138 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1142 template<
typename Derived>
1146 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, fmt, ap);
1149 template<
typename Derived>
1153 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, msg);
1156 template<
typename Derived>
1157 template<
int Level,
typename Fn>
1158 inline ENABLE_IF_Fn_CALLABLE_OSTREAM
1161 tomo_internal::LoggerBaseHelperStatic<Derived, Level>::test_and_call_emit_log(
this, origin, f);
1194 FileLogger(FILE * fp_,
int level =
INFO,
bool display_origin_ =
true)
1220 display_origin = display_origin_;
1223 inline void emit_log(
int level,
const char * origin,
const std::string & msg)
1231 ( (level >= 0 && level < (int)std::extent<decltype(level_prefixes)>::value)
1244 if (fp != stdout && fp != stderr) {
1252 bool display_origin;
1270 StaticMinimumSeverityLevel = -1
1281 inline void emit_log(
int ,
const char * ,
const std::string & )
1325 inline void emit_log(
int ,
const char * origin,
const std::string& msg)
1328 << msg.
c_str() <<
"\n";
1357 return buffer.
str();
1368 template<
typename BaseLogger,
int Level>
1375 StaticMinimumSeverityLevel = Level,
1393 template<
typename BaseLogger,
int Level>
1394 class MinimumSeverityLogger :
public LoggerBase<MinimumSeverityLogger<BaseLogger,Level> >
1397 BaseLogger & baselogger;
1412 baselogger.emit_log(level, origin, msg);
1418 return baselogger.level();
1422 template<
bool dummy = true>
1426 return baselogger.filter_by_origin(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.emit_log(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)
1622 ? LocalLoggerOriginSpec(fn.substr(last_doublecolons+2),
"::")
1625 : LocalLoggerOriginSpec(fn.substr(last_doublecolons+2),
"()",
"/")
1630 return (prelast_doublecolons_found == std::string::npos) ? 0 : prelast_doublecolons_found+2;
1632 static inline constexpr LocalLoggerOriginSpec step1(
const Tools::conststr fn,
std::size_t last_doublecolons)
1634 return last_doublecolons == std::string::npos || last_doublecolons == 0
1635 ? LocalLoggerOriginSpec(fn,
"()",
"/")
1636 : step2(fn, last_doublecolons, afterprelast_doublecolons(fn.rfind(
"::", last_doublecolons-1)));
1639 static inline constexpr LocalLoggerOriginSpec extract_from_func_name(
const Tools::conststr fn)
1641 return step1(fn, fn.rfind(
"::"));
1646 constexpr
const LocalLoggerOriginSpec extractTomoOrigin(
const Tools::conststr fn)
1656 #define TOMO_ORIGIN Tomographer::Logger::tomo_internal::extractTomoOrigin(TOMO_FUNCTION)
1664 template<
typename BaseLoggerType_>
1719 template<
typename BaseLoggerType_>
1723 typedef BaseLoggerType_ BaseLoggerType;
1731 BaseLoggerType & _baselogger;
1734 LocalLogger(
const std::string & origin_fn_name, BaseLoggerType & logger_)
1735 : _origin_prefix(origin_fn_name), _glue(
"::"), _baselogger(logger_)
1739 : _origin_prefix(origin_prefix), _glue(glue), _baselogger(logger_)
1742 LocalLogger(
const LocalLoggerOriginSpec & spec, BaseLoggerType & logger_)
1744 _glue(spec.glue.
to_string()), _baselogger(logger_)
1748 inline std::string origin_prefix()
const {
return _origin_prefix; }
1751 inline BaseLoggerType & baselogger() {
return _baselogger; };
1753 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const std::string & new_prefix)
1755 return LocalLogger<LocalLogger<BaseLoggerType> >(new_prefix, *
this);
1757 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const std::string & new_prefix,
1760 return LocalLogger<LocalLogger<BaseLoggerType> >(new_prefix, new_glue, *
this);
1762 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const LocalLoggerOriginSpec & spec)
1764 return LocalLogger<LocalLogger<BaseLoggerType> >(spec, *
this);
1768 {
va_list ap; va_start(ap, fmt); log<LONGDEBUG>(fmt, ap); va_end(ap); }
1770 {
va_list ap; va_start(ap, fmt); log<DEBUG>(fmt, ap); va_end(ap); }
1772 {
va_list ap; va_start(ap, fmt); log<INFO>(fmt, ap); va_end(ap); }
1774 {
va_list ap; va_start(ap, fmt); log<WARNING>(fmt, ap); va_end(ap); }
1776 {
va_list ap; va_start(ap, fmt); log<ERROR>(fmt, ap); va_end(ap); }
1778 template<
typename... Args>
1779 inline void longdebug(Args &&... a) { log<Tomographer::Logger::LONGDEBUG>(std::forward<Args>(a)...); }
1780 template<
typename... Args>
1781 inline void debug(Args &&... a) { log<Tomographer::Logger::DEBUG>(std::forward<Args>(a)...); }
1782 template<
typename... Args>
1783 inline void info(Args &&... a) { log<Tomographer::Logger::INFO>(std::forward<Args>(a)...); }
1784 template<
typename... Args>
1785 inline void warning(Args &&... a) { log<Tomographer::Logger::WARNING>(std::forward<Args>(a)...); }
1786 template<
typename... Args>
1787 inline void error(Args &&... a) { log<Tomographer::Logger::ERROR>(std::forward<Args>(a)...); }
1789 template<
int Level,
typename... Args>
1790 inline void log(Args... args)
1792 Base_::template log<Level>(
"", args...);
1798 inline std::string get_origin(
const char * origin)
const
1800 return ( origin == NULL || origin[0] == 0
1802 : _origin_prefix + _glue + origin );
1810 _baselogger.emit_log(level, get_origin(origin).c_str(), msg);
1816 return _baselogger.level();
1821 inline
bool filter_by_origin(
int level, const
char * origin)
1823 return _baselogger.filter_by_origin(level, get_origin(origin).c_str());
Utilities for formatting strings.
Simple logger class which logs everything into a given FILE pointer.
void setlevel(std::string s)
Set the level to the given level name. See class doc.
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.
constexpr LocalLoggerOriginSpec(const Tools::conststr &s, const Tools::conststr &s2, const Tools::conststr &gl)
complete constructor.
void clear()
Clears the internal memory buffer.
bool filter_by_origin(int level, const char *origin) const
Message filtering by origin implementation.
void setDomainLevel(const std::string &origin_pattern, int level)
Set a rule to log messages based on their origin.
int level() const
Get the log level set for this logger.
void setlevel(int level)
Set the level to the given level code. See class doc and LogLevelCode.
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.
bool is_at_least_of_severity(int level, int baselevel)
Helper to compare severity levels.
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 enabled_for(int level_) const
Check whether messages at the given log level are enabled.
OriginFilteredLogger(BaseLogger &baselogger_)
Constructor based on a base logger reference.
std::string get_contents() const
get the contents of the internal buffer
void removeDomainSetting(const std::string &s)
Remove a rule set by setDomainLevel()
std::string levelname() const
Get the stored level name.
void setLogLevel(int level)
Store a new run-time log level.
std::enable_if< dummy &&LoggerTraits< BaseLogger >::HasFilterByOrigin, bool > filter_by_origin(int level, const char *origin)
If relevant for the base logger, filter the messages by origin from the base logger.
Logger which statically discards any messages less important than a fixed severity.
void emit_log(int level, const char *origin, const std::string &msg)
Emit a log by relaying to the base logger.
constexpr LocalLoggerOriginSpec(const Tools::conststr &s, const Tools::conststr &gl)
constructor. origin_prefix_add is left blank.
int level() const
Get the base logger's set level.
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.
std::ostream & operator<<(std::ostream &str, const LogLevel &l)
C++ output stream operator for LogLevel.
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.
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.
void info(const char *origin, const char *fmt,...)
emit an information/notice message
Traits template struct to be specialized for specific Logger implementations.
void emit_log(int level, const char *origin, const std::string &msg)
Emit a log message (relay to base logger).
Helper for statically determining if Level is at least as severe as BaseLevel.
void emit_log(int level, const char *origin, const std::string &msg)
Emit a log by relaying to the base logger.
std::istream & operator>>(std::istream &str, LogLevel &l)
C++ input stream operator for LogLevel.
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.
int level() const
Unconditionally return LOWEST_SEVERITY_LEVEL for the underlying logging engine.
Information logging level.
static bool statically_enabled_for()
Static version of statically_enabled_for()
A logger which filters entries according to where they originated from.
static bool statically_enabled_for(int level)
Check whether the logger is statically disabled for some levels.