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)
1241 if (fp != stdout && fp != stderr && level <=
WARNING) {
1248 bool display_origin;
1266 StaticMinimumSeverityLevel = -1
1277 inline void emit_log(
int ,
const char * ,
const std::string & )
1321 inline void emit_log(
int ,
const char * origin,
const std::string& msg)
1324 << msg.
c_str() <<
"\n";
1353 return buffer.
str();
1364 template<
typename BaseLogger,
int Level>
1371 StaticMinimumSeverityLevel = Level,
1389 template<
typename BaseLogger,
int Level>
1390 class MinimumSeverityLogger :
public LoggerBase<MinimumSeverityLogger<BaseLogger,Level> >
1393 BaseLogger & baselogger;
1408 baselogger.emit_log(level, origin, msg);
1414 return baselogger.level();
1418 template<
bool dummy = true>
1422 return baselogger.filter_by_origin(level, origin);
1427 namespace tomo_internal {
1437 while (s[k] == pattern[k]) {
1449 template<
typename BaseLogger>
1455 HasFilterByOrigin = 1
1479 template<
typename BaseLogger>
1483 BaseLogger & baselogger;
1496 baselogger(baselogger_),
1512 levels_set[origin_pattern] = level;
1522 auto it = levels_set.
find(s);
1523 if (it == levels_set.
end()) {
1524 this->warning(
"OriginFilteredLogger<BaseLogger>::removeDomainSetting",
"domain not set: `%s'", s.
c_str());
1527 levels_set.
erase(it);
1549 baselogger.emit_log(level, origin, msg);
1566 int last_matched_length = 0;
1567 for (ConstIterator it = levels_set.
begin(); it != levels_set.
end(); ++it) {
1568 const int mlen = tomo_internal::matched_length((*it).first, s);
1569 if (mlen > last_matched_length) {
1570 loglevel = (*it).second;
1571 last_matched_length = mlen;
1574 if (loglevel == -1) {
1576 loglevel = baselogger.level();
1604 : origin_prefix(s), origin_prefix_add(
""), glue(gl) { }
1607 : origin_prefix(s), origin_prefix_add(s2), glue(gl) { }
1610 namespace tomo_internal {
1612 struct extractTomoOrigin_helper {
1616 return ( fn.substr_e(after_prelast_doublecolons, last_doublecolons) == fn.substr(last_doublecolons+2)
1618 ? LocalLoggerOriginSpec(fn.substr(last_doublecolons+2),
"::")
1621 : LocalLoggerOriginSpec(fn.substr(last_doublecolons+2),
"()",
"/")
1626 return (prelast_doublecolons_found == std::string::npos) ? 0 : prelast_doublecolons_found+2;
1628 static inline constexpr LocalLoggerOriginSpec step1(
const Tools::conststr fn,
std::size_t last_doublecolons)
1630 return last_doublecolons == std::string::npos || last_doublecolons == 0
1631 ? LocalLoggerOriginSpec(fn,
"()",
"/")
1632 : step2(fn, last_doublecolons, afterprelast_doublecolons(fn.rfind(
"::", last_doublecolons-1)));
1635 static inline constexpr LocalLoggerOriginSpec extract_from_func_name(
const Tools::conststr fn)
1637 return step1(fn, fn.rfind(
"::"));
1642 constexpr
const LocalLoggerOriginSpec extractTomoOrigin(
const Tools::conststr fn)
1652 #define TOMO_ORIGIN Tomographer::Logger::tomo_internal::extractTomoOrigin(TOMO_FUNCTION)
1660 template<
typename BaseLoggerType_>
1715 template<
typename BaseLoggerType_>
1719 typedef BaseLoggerType_ BaseLoggerType;
1727 BaseLoggerType & _baselogger;
1730 LocalLogger(
const std::string & origin_fn_name, BaseLoggerType & logger_)
1731 : _origin_prefix(origin_fn_name), _glue(
"::"), _baselogger(logger_)
1735 : _origin_prefix(origin_prefix), _glue(glue), _baselogger(logger_)
1738 LocalLogger(
const LocalLoggerOriginSpec & spec, BaseLoggerType & logger_)
1740 _glue(spec.glue.
to_string()), _baselogger(logger_)
1744 inline std::string origin_prefix()
const {
return _origin_prefix; }
1747 inline BaseLoggerType & baselogger() {
return _baselogger; };
1749 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const std::string & new_prefix)
1751 return LocalLogger<LocalLogger<BaseLoggerType> >(new_prefix, *
this);
1753 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const std::string & new_prefix,
1756 return LocalLogger<LocalLogger<BaseLoggerType> >(new_prefix, new_glue, *
this);
1758 inline LocalLogger<LocalLogger<BaseLoggerType> > sublogger(
const LocalLoggerOriginSpec & spec)
1760 return LocalLogger<LocalLogger<BaseLoggerType> >(spec, *
this);
1764 {
va_list ap; va_start(ap, fmt); log<LONGDEBUG>(fmt, ap); va_end(ap); }
1766 {
va_list ap; va_start(ap, fmt); log<DEBUG>(fmt, ap); va_end(ap); }
1768 {
va_list ap; va_start(ap, fmt); log<INFO>(fmt, ap); va_end(ap); }
1770 {
va_list ap; va_start(ap, fmt); log<WARNING>(fmt, ap); va_end(ap); }
1772 {
va_list ap; va_start(ap, fmt); log<ERROR>(fmt, ap); va_end(ap); }
1774 template<
typename... Args>
1775 inline void longdebug(Args... a) { log<Tomographer::Logger::LONGDEBUG>(a...); }
1776 template<
typename... Args>
1777 inline void debug(Args... a) { log<Tomographer::Logger::DEBUG>(a...); }
1778 template<
typename... Args>
1779 inline void info(Args... a) { log<Tomographer::Logger::INFO>(a...); }
1780 template<
typename... Args>
1781 inline void warning(Args... a) { log<Tomographer::Logger::WARNING>(a...); }
1782 template<
typename... Args>
1783 inline void error(Args... a) { log<Tomographer::Logger::ERROR>(a...); }
1785 template<
int Level,
typename... Args>
1786 inline void log(Args... args)
1788 Base_::template log<Level>(
"", args...);
1794 inline std::string get_origin(
const char * origin)
const
1796 return ( origin == NULL || origin[0] == 0
1798 : _origin_prefix + _glue + origin );
1806 _baselogger.emit_log(level, get_origin(origin).c_str(), msg);
1812 return _baselogger.level();
1817 inline
bool filter_by_origin(
int level, const
char * origin)
1819 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.