diff --git a/Documentation/Examples/CMakeLists.txt b/Documentation/Examples/CMakeLists.txt index 0871e4add1393c013c84a38ae509d6f2077b6e97..1592372c2c6a346def1c866508841097c4bbd1c2 100644 --- a/Documentation/Examples/CMakeLists.txt +++ b/Documentation/Examples/CMakeLists.txt @@ -8,12 +8,8 @@ target_link_libraries (particle_list_example CORSIKAparticles CORSIKAunits CORSI CORSIKA_ADD_EXAMPLE (geometry_example) target_link_libraries (geometry_example CORSIKAgeometry CORSIKAunits) -CORSIKA_ADD_EXAMPLE (logger_example) -target_link_libraries (logger_example CORSIKAunits CORSIKAlogging) - CORSIKA_ADD_EXAMPLE (stack_example) -target_link_libraries (stack_example SuperStupidStack CORSIKAunits - CORSIKAlogging) +target_link_libraries (stack_example SuperStupidStack CORSIKAunits) # address sanitizer is making this example too slow, so we only do "undefined" CORSIKA_ADD_EXAMPLE (boundary_example) diff --git a/Documentation/Examples/logger_example.cc b/Documentation/Examples/logger_example.cc deleted file mode 100644 index 2596307b9a7ac3c9ff977a42481cbf0622b5f6b7..0000000000000000000000000000000000000000 --- a/Documentation/Examples/logger_example.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#include <corsika/logging/Logger.h> -#include <boost/format.hpp> -#include <fstream> -#include <iostream> -#include <string> - -using namespace std; -using namespace corsika::logging; - -int main() { - { - cout << "writing to \"another.log\"" << endl; - ofstream logfile("another.log"); - sink::SinkStream unbuffered_sink(logfile); - sink::BufferedSinkStream sink(logfile, sink::StdBuffer(10000)); - Logger<MessageOn, sink::BufferedSinkStream> info("\033[32m", "info", sink); - Logger<MessageOn, sink::BufferedSinkStream> err("\033[31m", "error", sink); - // logger<ostream,messageconst,StdBuffer> info(std::cout, StdBuffer(10000)); - - /* - Logging& logs = Logging::GetInstance(); - logs.AddLogger<>("info", info); - auto& log_1 = logs.GetLogger("info"); // no so useful, since type of log_1 is - std::any - */ - - for (int i = 0; i < 10000; ++i) { - LOG(info, "irgendwas", " ", string("and more"), " ", - boost::format("error: %i message: %s. done."), i, "stupido"); - LOG(err, "Fehler"); - } - } - - { - sink::NoSink off; - Logger<MessageOff> info("", "", off); - - for (int i = 0; i < 10000; ++i) { - LOG(info, "irgendwas", string("and more"), - boost::format("error: %i message: %s. done."), i, "stupido", "a-number:", 8.99, - "ENDE"); - } - } - - return 0; -} diff --git a/Framework/Logging/BufferedSink.h b/Framework/Logging/BufferedSink.h deleted file mode 100644 index 26aeb6c5a94bbe029b017bb00498650b10d37c64..0000000000000000000000000000000000000000 --- a/Framework/Logging/BufferedSink.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika::logging { - - namespace sink { - - /** - Output buffer template. NoBuffer does nothingk. - */ - /* - struct NoBuffer { - inline bool Test(const std::string&) const { return false; } - inline std::string GetString() const { return std::string(""); } - inline void Clear() {} - inline void Add(const std::string&) {} - }; - */ - /** - Output buffer template. StdBuffer records fSize characters in - local memeory before passing it on to further output stages. - */ - - struct StdBuffer { - StdBuffer(const int size) - : fSize(size) {} - inline bool Test(const std::string& s) { - return int(fBuffer.tellp()) + s.length() < fSize; - } - inline std::string GetString() const { return fBuffer.str(); } - inline void Clear() { fBuffer.str(""); } - inline void Add(const std::string& s) { fBuffer << s; } - - private: - unsigned int fSize; - std::ostringstream fBuffer; - }; - - /** - Definition of Sink for log output. - */ - template <typename TStream, typename TBuffer = StdBuffer> - class BufferedSink { - public: - BufferedSink(TStream& out, TBuffer buffer = {}) - : fOutput(out) - , fBuffer(std::move(buffer)) {} - void operator<<(const std::string& msg) { - if (!fBuffer.Test(msg)) { - fOutput << fBuffer.GetString(); - fBuffer.Clear(); - } - if (!fBuffer.Test(msg)) - fOutput << msg; - else - fBuffer.Add(msg); - } - void Close() { fOutput << fBuffer.GetString(); } - - private: - TStream& fOutput; - TBuffer fBuffer; - }; - - typedef BufferedSink<std::ostream, StdBuffer> BufferedSinkStream; - - } // namespace sink -} // namespace corsika::logging diff --git a/Framework/Logging/CMakeLists.txt b/Framework/Logging/CMakeLists.txt index 4743b2b3400ea116126701bbe70027ec1b63b5ff..d74849f26c8f1c683899f51517cc150f9a787e3b 100644 --- a/Framework/Logging/CMakeLists.txt +++ b/Framework/Logging/CMakeLists.txt @@ -1,3 +1,4 @@ +# create the library add_library (CORSIKAlogging INTERFACE) # namespace of library -> location of header files @@ -9,15 +10,10 @@ set ( # header files of this library set ( CORSIKAlogging_HEADERS - Logger.h - Sink.h - MessageOn.h - MessageOff.h - NoSink.h - Sink.h - BufferedSink.h + Logging.h ) +# copy the headers into the namespace CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAlogging ${CORSIKAlogging_NAMESPACE} ${CORSIKAlogging_HEADERS} @@ -32,6 +28,13 @@ target_include_directories ( C8::ext:boost ) +# and link against spdlog +target_link_libraries( + CORSIKAlogging + INTERFACE + spdlog::spdlog +) + # install library install ( FILES ${CORSIKAlogging_HEADERS} @@ -41,10 +44,9 @@ install ( # ---------------- # code unit testing -#CORSIKA_ADD_TEST (testLogging) -#target_link_libraries ( -# testLogging -# CORSIKAlogging -# CORSIKAtesting -# ) - +CORSIKA_ADD_TEST (testLogging) +target_link_libraries ( + testLogging + CORSIKAlogging + CORSIKAtesting + ) diff --git a/Framework/Logging/Logger.h b/Framework/Logging/Logger.h deleted file mode 100644 index ae688460f236a02476b8d3a062a4dec3f9243328..0000000000000000000000000000000000000000 --- a/Framework/Logging/Logger.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -/** - @File Logger.h - - Everything around logfile generation and text output. - */ - -#pragma once - -#include <iosfwd> -#include <sstream> -#include <string> -#include <typeinfo> - -#include <boost/format.hpp> - -#include <corsika/logging/BufferedSink.h> -#include <corsika/logging/MessageOff.h> -#include <corsika/logging/MessageOn.h> -#include <corsika/logging/NoSink.h> -#include <corsika/logging/Sink.h> - -namespace corsika::logging { - - /** - @class Logger - - Defines one stream to accept messages, and to wrote those into - TSink. The helper class MessageOn will convert input at - compile-time into message strings. The helper class MessageOff, - will just do nothing and will be optimized away at compile time. - */ - template <typename MSG = MessageOn, typename TSink = sink::NoSink> - class Logger : private MSG { - - using MSG::Message; - - public: - // Logger() : fName("") {} - Logger(const std::string color, const std::string name, TSink& sink) - : fSink(sink) - , fName(color + "[" + name + "]\033[39m ") {} - ~Logger() { fSink.Close(); } - // Logger(const Logger&) = delete; - - /** - Function to add string-concatenation of all inputs to output - sink. - */ - template <typename... Strings> - void Log(const Strings&... inputs) { - fSink << MSG::Message(inputs...); - } - - const std::string& GetName() const { return fName; } - - private: - TSink& fSink; - std::string fName; - }; - -} // namespace corsika::logging - -/** - * @def LOG(...) - * - * This is the main interface to the logging facilities. If Logger - * object are defined (e.g. log1) use as - * @example LOG(log1, "var1=", variable1int, "var2=", variabl2double) - * for arbitrary long sequence - * of arguments. This may also include boost::format objects the - * output is concatenated, if log1 is switched off at compile time, - * the whole LOG command is optimized away by the compiler. - */ - -#define LOG(__LOGGER, ...) \ - __LOGGER.Log(__LOGGER.GetName(), __FILE__, ":", __LINE__, " (", __func__, ") -> ", \ - __VA_ARGS__); diff --git a/Framework/Logging/Logging.h b/Framework/Logging/Logging.h new file mode 100644 index 0000000000000000000000000000000000000000..09853d1b2abbd446b1408b46c994d03de6bbea02 --- /dev/null +++ b/Framework/Logging/Logging.h @@ -0,0 +1,96 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +/** + @File Logging.h + + CORSIKA8 logging utilities. + */ + +#pragma once + +#include <spdlog/spdlog.h> +#include "spdlog/sinks/stdout_color_sinks.h" + + +namespace corsika::logging { + + // bring spdlog into the corsika::logging namespace + using namespace spdlog; + + /** + * Create a new C8-style logger. + * + * @param name The unique name of the logger. + * @param defaultlog If True, set this as the default logger. + * @returns The constructed and formatted logger. + */ + auto CreateLogger(std::string const& name, bool const defaultlog = false) { + + // create the logger + auto logger = spdlog::stdout_color_mt(name); + + // set the default C8 format + logger->set_pattern("[%n:%^%-8l%$] %v"); + + // if defaultlog is True, we set this as the default spdlog logger. + if (defaultlog) { spdlog::set_default_logger(logger); } + + // and return the logger + return logger; + } + + /** + * Get a reference to a named logger. + * + * If the logger does not exist, it is created. + * + * @param name The name of the logger to get. + */ + auto GetLogger(std::string const& name, bool const defaultlog = false) { + + // attempt to get the logger from the registry + auto logger = spdlog::get(name); + + // weg found the logger, so just return it + if (logger) { + return logger; + } else { // logger was not found so create it + return CreateLogger(name, defaultlog); + } + } + + /** + * Set the default log level for all loggers. + * + * @param name The minimum log level required to print. + * + */ + auto SetDefaultLevel(level::level_enum minlevel) -> void { + spdlog::set_level(minlevel); + } + + // create the default CORSIKA logger + inline auto corsika = GetLogger("corsika", true); + +// define our macro-style loggers +#define C8LOG_DEBUG SPDLOG_DEBUG +#define C8LOG_INFO SPDLOG_INFO +#define C8LOG_WARN SPDLOG_WARN +#define C8LOG_ERROR SPDLOG_ERROR +#define C8LOG_CRITICAL SPDLOG_CRITICAL + +// and the specific logger versions +#define C8LOG_LOGGER_DEBUG SPDLOG_LOGGER_DEBUG +#define C8LOG_LOGGER_INFO SPDLOG_LOGGER_INFO +#define C8LOG_LOGGER_WARN SPDLOG_LOGGER_WARN +#define C8LOG_LOGGER_ERROR SPDLOG_LOGGER_ERROR +#define C8LOG_LOGGER_CRITICAL SPDLOG_LOGGER_CRITICAL + +} // namespace corsika::logging diff --git a/Framework/Logging/MessageOff.h b/Framework/Logging/MessageOff.h deleted file mode 100644 index e25a8b30af8c89af870230837d4d1e784b3355be..0000000000000000000000000000000000000000 --- a/Framework/Logging/MessageOff.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika::logging { - - /** - Helper class to ignore all arguments to MessagesOn::Message and - always return empty string "". - */ - class MessageOff { - protected: - template <typename First, typename... Strings> - std::string Message(const First&, const Strings&...) { - return ""; - } - }; - -} // namespace corsika::logging diff --git a/Framework/Logging/MessageOn.h b/Framework/Logging/MessageOn.h deleted file mode 100644 index 6c34936bf90a6e8eaecfae155482ad848eb85d57..0000000000000000000000000000000000000000 --- a/Framework/Logging/MessageOn.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika::logging { - - /** - Helper class to convert all input arguments of MessageOn::Message - into string-concatenated version and return this as string. - */ - class MessageOn { - protected: - std::string Message() { return "\n"; } - - template <typename First, typename... Strings> - std::string Message(const First& arg, const Strings&... rest) { - std::ostringstream ss; - ss << arg << Message(rest...); - return ss.str(); - } - - template <typename... Strings> - std::string Message(const int& arg, const Strings&... rest) { - return std::to_string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(const double& arg, const Strings&... rest) { - return std::to_string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(char const* arg, const Strings&... rest) { - return std::string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(const std::string& arg, const Strings&... rest) { - return arg + Message(rest...); - } - - // ---------------------- - // boost format - template <typename... Strings> - std::string Message(const boost::format& fmt, const Strings&... rest) { - boost::format FMT(fmt); - return bformat(FMT, rest...); - } - - template <typename Arg, typename... Strings> - std::string bformat(boost::format& fmt, const Arg& arg, const Strings&... rest) { - fmt % arg; - return bformat(fmt, rest...); - } - - std::string bformat(boost::format& fmt) { return fmt.str() + "\n"; } - }; - -} // namespace corsika::logging diff --git a/Framework/Logging/NoSink.h b/Framework/Logging/NoSink.h deleted file mode 100644 index 122cc255fd86275de8fc3a84b7e01a75e41dff31..0000000000000000000000000000000000000000 --- a/Framework/Logging/NoSink.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika::logging { - - namespace sink { - - struct NoSink { - inline void operator<<(const std::string&) {} - inline void Close() {} - }; - - } // namespace sink -} // namespace corsika::logging diff --git a/Framework/Logging/Sink.h b/Framework/Logging/Sink.h deleted file mode 100644 index be99c3c637c144cadbf6cd36f8f72741f4a8449c..0000000000000000000000000000000000000000 --- a/Framework/Logging/Sink.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#pragma once - -namespace corsika::logging { - - /** - a sink for the logger must implement the two functions - operator<<(const std::string&) - and - Close() - - See example: NoSink - */ - - namespace sink { - - /** - Definition of Sink for log output. - */ - template <typename TStream> - class Sink { - public: - Sink(TStream& out) - : fOutput(out) {} - void operator<<(const std::string& msg) { fOutput << msg; } - void Close() {} - - private: - TStream& fOutput; - }; - - typedef Sink<std::ostream> SinkStream; - - } // namespace sink -} // namespace corsika::logging diff --git a/Framework/Logging/testLogging.cc b/Framework/Logging/testLogging.cc index 2186894b7e570a481af968ed6d9e08ea53517dc9..2bead9a54ccc8a9a20b73c85aff673fd0e2593a7 100644 --- a/Framework/Logging/testLogging.cc +++ b/Framework/Logging/testLogging.cc @@ -1,23 +1,94 @@ /* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu * * This software is distributed under the terms of the GNU General Public * Licence version 3 (GPL Version 3). See file LICENSE for a full version of * the license. */ -#include <corsika/logging/Logger.h> +#include <corsika/logging/Logging.h> #include <catch2/catch.hpp> -/* - this does nothing yet - */ +using namespace corsika; TEST_CASE("Logging", "[Logging]") { - SECTION("sectionOne") {} + SECTION("top level functions using corsika logger") { + logging::info("This is an info message!"); + logging::warn("This is a warning message!"); + logging::debug("This is a debug message!"); + logging::error("This is an error message!"); + logging::critical("This is a critical error message!"); + } + + SECTION("create a specific logger") { + + // create a logger manually + auto logger = logging::CreateLogger("loggerA"); + + // set a custom pattern for this logger + logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); + + // and make sure we can log with this created object + logger->info("This is an info message!"); + logger->warn("This is a warning message!"); + logger->debug("This is a debug message!"); + logger->error("This is an error message!"); + logger->critical("This is a critical error message!"); + + // get a reference to the logger using Get + auto other = logging::GetLogger("loggerA"); + + // and make sure we can use this other reference to log + other->info("This is an info message!"); + other->warn("This is a warning message!"); + other->debug("This is a debug message!"); + other->error("This is an error message!"); + other->critical("This is a critical error message!"); + } + + SECTION("get a new logger") { + + // get a reference to an unknown logger + auto logger = logging::GetLogger("loggerB"); + + // and make sure we can log with this created object + logger->info("This is an info message!"); + logger->warn("This is a warning message!"); + logger->debug("This is a debug message!"); + logger->error("This is an error message!"); + logger->critical("This is a critical error message!"); + } + + SECTION("test log level") { + + // set the default log level + logging::SetDefaultLevel(logging::level::critical); + + // and make sure we can log with this created object + logging::info("This should NOT be printed!"); + logging::warn("This should NOT be printed!"); + logging::debug("This should NOT be printed!"); + logging::error("This should NOT be printed!"); + logging::critical("This SHOULD BE printed!!"); + + // and reset it for the next tests + logging::SetDefaultLevel(logging::level::debug); + } + + SECTION("test macro style printing") { + + // these print with the "corsika" logger + C8LOG_INFO("This is a macro info msg!"); + C8LOG_DEBUG("This is a macro debug msg!"); + C8LOG_ERROR("This is a macro error msg!"); + C8LOG_CRITICAL("This is a macro critical msg!"); - SECTION("sectionTwo") {} + // get a reference to an unknown logger + auto logger = logging::GetLogger("loggerD"); - SECTION("sectionThree") {} + // these print with the "loggerD" logger + C8LOG_LOGGER_INFO(logger, "This is a macro info msg!"); + C8LOG_LOGGER_WARN(logger, "This is a macro warn msg!"); + } } diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index f6817bf7f8cca23ad769751575987f92cfb705ae..13ea2ba05174de18daa7646059d3ab19295cc099 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -15,8 +15,10 @@ include(ExternalProject) set (ThirdPartyChoiceValues "C8;SYSTEM" CACHE STRING "List of possible values for the ThirdParty package choice") mark_as_advanced (ThirdPartyChoiceValues) - +############################################################################## +# Build spdlog +add_subdirectory(spdlog) ############################################################################## # check for boost: either use C8 or system-level installation