diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 6a4a0792..1fedde76 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -106,7 +106,7 @@ namespace ngcore protected: bool shallow_to_python = false; std::map version_map = GetLibraryVersions(); - std::shared_ptr logger = GetLogger("Archive"); + std::shared_ptr logger = GetLogger("Archive"); public: Archive() = delete; Archive(const Archive&) = delete; @@ -211,6 +211,7 @@ namespace ngcore // don't use it that often anyway) Archive& operator& (std::vector& v) { + logger->debug("In special archive for std::vector"); size_t size; if(Output()) size = v.size(); @@ -295,11 +296,11 @@ namespace ngcore { if(Output()) { - NETGEN_DEBUG_LOG(logger, "Store shared ptr of type " + Demangle(typeid(T).name())); + logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name())); // save -2 for nullptr if(!ptr) { - NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + logger->debug("Storing nullptr"); return (*this) << -2; } @@ -308,8 +309,9 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + - Demangle(typeid(*ptr).name())); + logger->debug("Typids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*ptr).name()) @@ -318,7 +320,7 @@ namespace ngcore // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) { - NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); neededDowncast = true; } } @@ -326,8 +328,8 @@ namespace ngcore // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) { - NETGEN_DEBUG_LOG(logger, "Didn't find the shared_ptr, create new registry entry at " + - std::to_string(shared_ptr_count)); + logger->debug("Didn't find the shared_ptr, create new registry entry at {}", + shared_ptr_count); auto p = ptr.get(); (*this) << -1; (*this) & neededDowncast & p; @@ -338,27 +340,27 @@ namespace ngcore return *this; } // if found store the position and if it has to be downcasted and how - NETGEN_DEBUG_LOG(logger, "Found shared_ptr at position " + std::to_string(pos->second)); + logger->debug("Found shared_ptr at position {}", pos->second); (*this) << pos->second << neededDowncast; if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); } else // Input { - NETGEN_DEBUG_LOG(logger, "Reading shared_ptr of type " + Demangle(typeid(T).name())); + logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; // -2 restores a nullptr if(nr == -2) { - NETGEN_DEBUG_LOG(logger, "Reading a nullptr"); + logger->debug("Reading a nullptr"); ptr = nullptr; return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { - NETGEN_DEBUG_LOG(logger, "Createing new shared_ptr"); + logger->debug("Createing new shared_ptr"); T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; @@ -366,7 +368,7 @@ namespace ngcore // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { - NETGEN_DEBUG_LOG(logger, "Shared pointer needed downcasting"); + logger->debug("Shared pointer needed downcasting"); std::string name; (*this) & name; auto info = GetArchiveRegister(name); @@ -378,19 +380,19 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need downcasting"); + logger->debug("Shared pointer didn't need downcasting"); nr2shared_ptr.push_back(ptr); } } else { - NETGEN_DEBUG_LOG(logger, "Reading already existing pointer at entry " + std::to_string(nr)); + logger->debug("Reading already existing pointer at entry {}", nr); auto other = nr2shared_ptr[nr]; bool neededDowncast; (*this) & neededDowncast; if(neededDowncast) { - NETGEN_DEBUG_LOG(logger, "Shared pointer needed pointer downcast"); + logger->debug("Shared pointer needed pointer downcast"); // if there was a downcast we can expect the class to be registered (since archiving // wouldn't have worked else) std::string name; @@ -404,7 +406,7 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need pointer casts"); + logger->debug("Shared pointer didn't need pointer casts"); ptr = std::static_pointer_cast(other); } } @@ -418,18 +420,19 @@ namespace ngcore { if (Output()) { - NETGEN_DEBUG_LOG(logger, "Store pointer of type " + Demangle(typeid(T).name())); + logger->debug("Store pointer of type {}",Demangle(typeid(T).name())); // if the pointer is null store -2 if (!p) { - NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + logger->debug("Storing nullptr"); return (*this) << -2; } auto reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { - NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + - Demangle(typeid(*p).name())); + logger->debug("Typeids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) @@ -437,20 +440,20 @@ namespace ngcore reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { - NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); } } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { - NETGEN_DEBUG_LOG(logger, "Didn't find pointer, create new registry entry at " + - std::to_string(ptr_count)); + logger->debug("Didn't find pointer, create new registry entry at {}", + ptr_count); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) { - NETGEN_DEBUG_LOG(logger, "Store standard class pointer (no virt. inh,...)"); + logger->debug("Store standard class pointer (no virt. inh,...)"); return (*this) << -1 & (*p); } else @@ -466,7 +469,7 @@ namespace ngcore throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); - NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); + logger->debug("Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } @@ -474,39 +477,37 @@ namespace ngcore { (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(p) ); - NETGEN_DEBUG_LOG(logger, "Store a the existing position in registry at " + - std::to_string(pos->second)); - NETGEN_DEBUG_LOG(logger, std::string("Pointer ") + (downcasted ? "needs " : "doesn't need ") + - "downcasting"); + logger->debug("Store a the existing position in registry at {}", pos->second); + logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need"); // store if the class has been downcasted and the name (*this) << downcasted << Demangle(typeid(*p).name()); } } else { - NETGEN_DEBUG_LOG(logger, "Reading pointer of type " + Demangle(typeid(T).name())); + logger->debug("Reading pointer of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; if (nr == -2) // restore a nullptr { - NETGEN_DEBUG_LOG(logger, "Loading a nullptr"); + logger->debug("Loading a nullptr"); p = nullptr; } else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - NETGEN_DEBUG_LOG(logger, "Load a new pointer to a simple class"); + logger->debug("Load a new pointer to a simple class"); p = detail::constructIfPossible(); nr2ptr.push_back(p); (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - NETGEN_DEBUG_LOG(logger, "Load a new pointer to a potentially more complicated class " - "(allows for multiple/virtual inheritance,...)"); + logger->debug("Load a new pointer to a potentially more complicated class " + "(allows for multiple/virtual inheritance,...)"); // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; - NETGEN_DEBUG_LOG(logger, "Name = " + name); + logger->debug("Name = {}", name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) @@ -518,13 +519,11 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Restoring pointer to already existing object at registry position " + - std::to_string(nr)); + logger->debug("Restoring pointer to already existing object at registry position {}", nr); bool downcasted; std::string name; (*this) & downcasted & name; - NETGEN_DEBUG_LOG(logger, std::string(downcasted ? "Downcasted" : "Not downcasted") + - " object of type " + name); + logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name); if(downcasted) { // if the class has been downcasted we can assume it is in the register diff --git a/libsrc/core/logging.cpp b/libsrc/core/logging.cpp index 467255cd..eaaedf02 100644 --- a/libsrc/core/logging.cpp +++ b/libsrc/core/logging.cpp @@ -1,15 +1,29 @@ - #include "logging.hpp" #ifdef NETGEN_USE_SPDLOG +#include #include #include +#else // NETGEN_USE_SPDLOG +#include #endif // NETGEN_USE_SPDLOG + namespace ngcore { + + void Logger::log(level::level_enum level, std::string && s) + { +#ifdef NETGEN_USE_SPDLOG + logger->log(spdlog::level::level_enum(level), s); +#else // NETGEN_USE_SPDLOG + if(level>level::debug) + std::clog << s << '\n'; +#endif // NETGEN_USE_SPDLOG + } + #ifdef NETGEN_USE_SPDLOG namespace detail { @@ -28,12 +42,12 @@ namespace ngcore } } // namespace detail - std::shared_ptr GetLogger(const std::string& name) + std::shared_ptr GetLogger(const std::string& name) { auto logger = spdlog::get(name); if(!logger) logger = detail::CreateDefaultLogger(name); - return logger; + return std::make_shared(logger); } void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) @@ -49,7 +63,7 @@ namespace ngcore auto sink = std::make_shared(filename); sink->set_level(level); if(!logger.empty()) - GetLogger(logger)->sinks().push_back(sink); + GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); @@ -62,7 +76,7 @@ namespace ngcore auto sink = std::make_shared(); sink->set_level(level); if(!logger.empty()) - GetLogger(logger)->sinks().push_back(sink); + GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); @@ -73,7 +87,7 @@ namespace ngcore void ClearLoggingSinks(const std::string& logger) { if(!logger.empty()) - GetLogger(logger)->sinks().clear(); + GetLogger(logger)->logger->sinks().clear(); else { detail::GetDefaultSinks().clear(); @@ -84,26 +98,40 @@ namespace ngcore void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger) { if(!logger.empty()) - GetLogger(logger)->flush_on(level); + GetLogger(logger)->logger->flush_on(level); else spdlog::flush_on(level); } #else // NETGEN_USE_SPDLOG +} //namespace ngcore + +namespace spdlog +{ + class logger + { + public: + logger() = default; + }; +} // namespace spdlog + +namespace ngcore +{ // Dummy functions if no spdlog is available - std::shared_ptr GetLogger(const std::string& /*unused*/) + std::shared_ptr GetLogger(const std::string& /*unused*/) { - return std::make_shared(); + return std::make_shared(std::make_shared()); } - void SetLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} - void AddFileSink(const std::string& /*unused*/, spdlog::level::level_enum /*unused*/, - const std::string& /*unused*/) + + void SetLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddFileSink(const std::string& /*unused*/, level::level_enum /*unused*/, + const std::string& /*unused*/) {} - void AddConsoleSink(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddConsoleSink(level::level_enum /*unused*/, const std::string& /*unused*/) {} void ClearLoggingSinks(const std::string& /*unused*/) {} - void FlushOnLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} +} //namespace ngcore #endif // NETGEN_USE_SPDLOG -} //namespace ngcore diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index d5fbf1ac..1553ad54 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -1,108 +1,124 @@ #ifndef NETGEN_CORE_LOGGING_HPP #define NETGEN_CORE_LOGGING_HPP +#undef NETGEN_USE_SPDLOG +#include #include #include #include +#include "exception.hpp" #include "ngcore_api.hpp" +#include "utils.hpp" #ifdef NETGEN_USE_SPDLOG - +#include +#include // to be able to parse anything to logger that implements operator << ostream #ifdef NETGEN_LOG_DEBUG #define SPDLOG_DEBUG_ON -#endif // NETGEN_LOG_DEBUG - -#include -#include -#include - #define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) +#endif // NETGEN_LOG_DEBUG +#endif // NETGEN_USE_SPDLOG -#else // NETGEN_USE_SPDLOG - -#include +#ifndef NETGEN_DEBUG_LOG +#define NETGEN_DEBUG_LOG(logger, ...) +#endif // NETGEN_DEBUG_LOG namespace spdlog { - // Dummys if Netgen is compiled with USE_SPDLOG=OFF. - namespace level - { - enum level_enum - { - trace = 0, - debug = 1, - info = 2, - warn = 3, - err = 4, - critical = 5, - off = 6 - }; - } // namespace level - - class logger - { - public: - void log_helper() {} - - template - void log_helper( T t) { std::clog << t; } - - template - void log_helper( T t, Args ... args) - { - std::clog << t; - log_helper(args...); - std::clog << ", "; - } - - template - void log( level::level_enum level, const char* fmt, Args ... args) - { - std::clog << level << ": " << fmt << "\t Arguments: "; - log_helper(args...); - std::clog << "\n"; - } - - template - void trace( const char* fmt, Args ... args) { log(level::level_enum::trace, fmt, args...); } - template - void debug( const char* fmt, Args ... args) { log(level::level_enum::debug, fmt, args...); } - template - void info( const char* fmt, Args ... args) { log(level::level_enum::info, fmt, args...); } - template - void warn( const char* fmt, Args ... args) { log(level::level_enum::warn, fmt, args...); } - template - void error( const char* fmt, Args ... args) { log(level::level_enum::err, fmt, args...); } - template - void critical( const char* fmt, Args ... args) { log(level::level_enum::critical, fmt, args...); } - }; - - namespace sinks - { - class sink {}; - } // namespace sinks - -} //namespace spdlog - -#define NETGEN_DEBUG_LOG(logger, ...) - -#endif // NETGEN_USE_SPDLOG + class logger; +} // namespace spdlog namespace ngcore { - namespace detail + namespace level { - std::vector>& GetDefaultSinks(); - inline std::shared_ptr CreateDefaultLogger(const std::string& name); - } //namespace detail + enum level_enum + { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 + }; + } // namespace level - NGCORE_API std::shared_ptr GetLogger(const std::string& name); - NGCORE_API void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name); - NGCORE_API void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger); - NGCORE_API void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger); + class Logger + { + public: + std::shared_ptr logger; + + Logger(std::shared_ptr l) : logger(std::move(l)) {} + + void NGCORE_API log( level::level_enum level, std::string && s); + +#ifdef NETGEN_USE_SPDLOG + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, fmt::format(str, args...)); + } +#else // NETGEN_USE_SPDLOG + template + std::string replace(std::string s, const T & t) + { + auto p0 = s.find_first_of('{'); + auto p1 = s.find_first_of('}', p0); + if(p0==std::string::npos || p1==std::string::npos) + throw Exception("invalid format string"); + s.replace(p0, p1-p0+1, ToString(t)); + return s; + } + + std::string log_helper(std::string s) + { + return s; + } + + template + std::string log_helper(std::string s, const T &t) + { + return replace(s,t); + } + + template + std::string log_helper( std::string s, const T &t, Args ... args) + { + return log_helper(replace(s,t), args...); + } + + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, log_helper(std::string(str), args...)); + } +#endif // NETGEN_USE_SPDLOG + + template + void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); } + template + void debug( const char* str, Args ... args) { log(level::level_enum::debug, str, args...); } + template + void info( const char* str, Args ... args) { log(level::level_enum::info, str, args...); } + template + void warn( const char* str, Args ... args) { log(level::level_enum::warn, str, args...); } + template + void error( const char* str, Args ... args) { log(level::level_enum::err, str, args...); } + template + void critical( const char* str, Args ... args) { log(level::level_enum::critical, str, args...); } + }; + + + + + NGCORE_API std::shared_ptr GetLogger(const std::string& name); + NGCORE_API void SetLoggingLevel(level::level_enum level, const std::string& name); + NGCORE_API void AddFileSink(const std::string& filename, level::level_enum level, const std::string& logger); + NGCORE_API void AddConsoleSink(level::level_enum level, const std::string& logger); NGCORE_API void ClearLoggingSinks(const std::string& logger); - NGCORE_API void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger); + NGCORE_API void FlushOnLoggingLevel(level::level_enum level, const std::string& logger); } // namespace ngcore #endif // NETGEN_CORE_LOGGING_HPP diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 23d9e49e..29a84d04 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -92,7 +92,7 @@ namespace ngcore FILE * ctrace_stream; TTimePoint start_time; - std::shared_ptr logger = GetLogger("PajeTrace"); + std::shared_ptr logger = GetLogger("PajeTrace"); double ConvertTime(TTimePoint t) { diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index c5169fdf..96684285 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -18,7 +18,7 @@ namespace ngcore using TClock = std::chrono::system_clock; protected: - std::shared_ptr logger = GetLogger("PajeTrace"); + std::shared_ptr logger = GetLogger("PajeTrace"); private: NGCORE_API static size_t max_tracefile_size; NGCORE_API static bool trace_thread_counter; diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index 29a69182..3302342d 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -13,7 +13,7 @@ namespace ngcore size_t NgProfiler::dummy_thread_flops[NgProfiler::SIZE]; size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops; // NOLINT - std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT + std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT NgProfiler :: NgProfiler() { diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index 96a3fc44..5a9b16e1 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -34,7 +34,7 @@ namespace ngcore NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; - NGCORE_API static std::shared_ptr logger; + NGCORE_API static std::shared_ptr logger; NGCORE_API static size_t dummy_thread_times[NgProfiler::SIZE]; NGCORE_API static size_t dummy_thread_flops[NgProfiler::SIZE]; private: diff --git a/libsrc/core/python_ngcore.cpp b/libsrc/core/python_ngcore.cpp index b7624e43..47c16740 100644 --- a/libsrc/core/python_ngcore.cpp +++ b/libsrc/core/python_ngcore.cpp @@ -8,14 +8,14 @@ using namespace ngcore; PYBIND11_MODULE(pyngcore, m) // NOLINT { - py::enum_(m, "LOG_LEVEL", "Logging level") - .value("Trace", spdlog::level::trace) - .value("Debug", spdlog::level::debug) - .value("Info", spdlog::level::info) - .value("Warn", spdlog::level::warn) - .value("Error", spdlog::level::err) - .value("Critical", spdlog::level::critical) - .value("Off", spdlog::level::off); + py::enum_(m, "LOG_LEVEL", "Logging level") + .value("Trace", level::trace) + .value("Debug", level::debug) + .value("Info", level::info) + .value("Warn", level::warn) + .value("Error", level::err) + .value("Critical", level::critical) + .value("Off", level::off); m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="", "Set logging level, if name is given only to the specific logger, else set the global logging level");