Loading lib/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ target_include_directories( set_target_properties(cargo PROPERTIES PUBLIC_HEADER "${public_headers}") target_link_libraries(cargo PRIVATE logger fmt::fmt thallium) target_link_libraries(cargo PRIVATE logger::logger fmt::fmt thallium) ## Install library + targets ################################################### Loading src/CMakeLists.txt +0 −2 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ ################################################################################ add_subdirectory(utils) add_subdirectory(config) add_subdirectory(logger) add_subdirectory(net) add_subdirectory(posix_file) Loading Loading @@ -52,7 +51,6 @@ target_include_directories( target_link_libraries( cargo_server PRIVATE config logger rpc_server cargo fmt::fmt Loading src/logger/CMakeLists.txt +11 −3 Original line number Diff line number Diff line Loading @@ -22,10 +22,18 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ add_subdirectory(logger) # get the parent directory of the current directory so we can include # headers from these libraries as `<logger/*.hpp>` get_filename_component(PARENT_DIRECTORY "../" ABSOLUTE) target_include_directories( logger INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} add_library(logger STATIC) target_sources( logger INTERFACE logger.h logger.hpp macros.h PRIVATE logger.cpp ) target_include_directories(logger PUBLIC ${PARENT_DIRECTORY}) target_link_libraries(logger PUBLIC spdlog::spdlog fmt::fmt) set_property(TARGET logger PROPERTY POSITION_INDEPENDENT_CODE ON) add_library(logger::logger ALIAS logger) src/logger/logger.cpp 0 → 100644 +221 −0 Original line number Diff line number Diff line /****************************************************************************** * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). * * This file is part of Cargo. * * Cargo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cargo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cargo. If not, see <https://www.gnu.org/licenses/>. * * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ #include <spdlog/spdlog.h> #include <spdlog/async.h> #include <spdlog/sinks/stdout_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/basic_file_sink.h> #include <spdlog/sinks/syslog_sink.h> #include <utility> #include <cstdarg> #include "logger.hpp" #include "logger.h" //////////////////////////////////////////////////////////////////////////////// // Function implementations for the C API //////////////////////////////////////////////////////////////////////////////// void logger_setup(const char* ident, logger_type type, const char* log_file) { constexpr auto get_cxx_type = [](logger_type t) { switch(t) { case CONSOLE_LOGGER: return logger::logger_type::console; case CONSOLE_COLOR_LOGGER: return logger::logger_type::console_color; case FILE_LOGGER: return logger::logger_type::file; case SYSLOG_LOGGER: return logger::logger_type::syslog; default: return logger::logger_type::console; } }; logger::create_default_logger( logger::logger_config{ident, get_cxx_type(type), log_file}); } void logger_log(enum logger_level level, const char* fmt, ...) { using logger::logger_base; if(const auto logger = logger_base::get_default_logger(); logger) { std::array<char, LOGGER_MSG_MAX_LEN> msg; // NOLINT va_list args; va_start(args, fmt); vsnprintf(msg.data(), msg.size(), fmt, args); va_end(args); switch(level) { case info: logger->info(msg.data()); break; case debug: logger->debug(msg.data()); break; case warn: logger->warn(msg.data()); break; case error: logger->error(msg.data()); break; case critical: logger->critical(msg.data()); break; } } } void logger_destroy() { using logger::logger_base; if(logger_base::get_default_logger()) { ::logger::destroy_default_logger(); } } //////////////////////////////////////////////////////////////////////////////// // Function implementations for the C++ API //////////////////////////////////////////////////////////////////////////////// namespace { /** * @brief Creates a logger of the given type. * * @tparam Logger Type of the logger to create. * @param config Configuration for the logger. * @return std::shared_ptr<spdlog::logger> Pointer to the created logger. */ template <typename Logger> std::shared_ptr<spdlog::logger> create_logger(const logger::logger_config& config) requires(std::is_same_v<Logger, logger::sync_logger> || std::is_same_v<Logger, logger::async_logger>) { const auto create_helper = [&config]() { switch(config.type()) { case logger::console: { if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::stdout_logger_st(config.ident()); } return spdlog::stdout_logger_mt<spdlog::async_factory>( config.ident()); } case logger::console_color: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::stdout_color_st(config.ident()); } return spdlog::stdout_color_mt<spdlog::async_factory>( config.ident()); case logger::file: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::basic_logger_st( config.ident(), config.log_file().value_or(""), true); } return spdlog::basic_logger_mt<spdlog::async_factory>( config.ident(), config.log_file().value_or(""), true); case logger::syslog: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::syslog_logger_st("syslog", config.ident(), LOG_PID); } return spdlog::syslog_logger_mt("syslog", config.ident(), LOG_PID); default: throw std::invalid_argument("Unknown logger type"); } }; try { auto logger = create_helper(); assert(logger != nullptr); logger->set_pattern(logger::default_pattern); #ifdef LOGGER_ENABLE_DEBUG logger->set_level(spdlog::level::debug); #endif spdlog::drop_all(); return logger; } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } } // namespace namespace logger { logger_base::logger_base(logger::logger_config config) : m_config(std::move(config)), m_internal_logger(::create_logger<async_logger>(m_config)) {} const logger_config& logger_base::config() const { return m_config; } std::shared_ptr<logger_base>& logger_base::get_default_logger() { static std::shared_ptr<logger_base> s_global_logger; return s_global_logger; } void logger_base::enable_debug() const { m_internal_logger->set_level(spdlog::level::debug); } void logger_base::flush() { m_internal_logger->flush(); } async_logger::async_logger(const logger_config& config) : logger_base(config) { try { m_internal_logger = ::create_logger<async_logger>(config); } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } sync_logger::sync_logger(const logger_config& config) : logger_base(config) { try { m_internal_logger = ::create_logger<sync_logger>(config); } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } } // namespace logger src/logger/logger.h 0 → 100644 +79 −0 Original line number Diff line number Diff line /****************************************************************************** * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). * * This file is part of Cargo. * * Cargo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cargo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cargo. If not, see <https://www.gnu.org/licenses/>. * * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ #ifndef SCORD_LOGGER_H #define SCORD_LOGGER_H #include "macros.h" #ifdef __cplusplus extern "C" { #endif #define LOGGER_MSG_MAX_LEN 2048 enum logger_type { CONSOLE_LOGGER, CONSOLE_COLOR_LOGGER, FILE_LOGGER, SYSLOG_LOGGER }; enum logger_level { info, debug, warn, error, critical }; /** * Initialize a global logger. * * Valid logger types: * - console * - console color * - file * * @param ident The identifier that should be used when emitting messages * @param type The type of logger desired. * @param log_file The path to the log file where messages should be written. */ void setup_logger(const char* ident, enum logger_type type, const char* log_file); /** * Emit a message. * * @param level The level for the message. * @param fmt A vprintf()-compatible format string. * @param ... A sequence of arguments corresponding to the format string. */ void logger_log(enum logger_level level, const char* fmt, ...); /** * Destroy the global logger. */ void destroy_logger(); #ifdef __cplusplus }; // extern "C" #endif #endif // SCORD_LOGGER_H Loading
lib/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ target_include_directories( set_target_properties(cargo PROPERTIES PUBLIC_HEADER "${public_headers}") target_link_libraries(cargo PRIVATE logger fmt::fmt thallium) target_link_libraries(cargo PRIVATE logger::logger fmt::fmt thallium) ## Install library + targets ################################################### Loading
src/CMakeLists.txt +0 −2 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ ################################################################################ add_subdirectory(utils) add_subdirectory(config) add_subdirectory(logger) add_subdirectory(net) add_subdirectory(posix_file) Loading Loading @@ -52,7 +51,6 @@ target_include_directories( target_link_libraries( cargo_server PRIVATE config logger rpc_server cargo fmt::fmt Loading
src/logger/CMakeLists.txt +11 −3 Original line number Diff line number Diff line Loading @@ -22,10 +22,18 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ add_subdirectory(logger) # get the parent directory of the current directory so we can include # headers from these libraries as `<logger/*.hpp>` get_filename_component(PARENT_DIRECTORY "../" ABSOLUTE) target_include_directories( logger INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} add_library(logger STATIC) target_sources( logger INTERFACE logger.h logger.hpp macros.h PRIVATE logger.cpp ) target_include_directories(logger PUBLIC ${PARENT_DIRECTORY}) target_link_libraries(logger PUBLIC spdlog::spdlog fmt::fmt) set_property(TARGET logger PROPERTY POSITION_INDEPENDENT_CODE ON) add_library(logger::logger ALIAS logger)
src/logger/logger.cpp 0 → 100644 +221 −0 Original line number Diff line number Diff line /****************************************************************************** * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). * * This file is part of Cargo. * * Cargo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cargo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cargo. If not, see <https://www.gnu.org/licenses/>. * * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ #include <spdlog/spdlog.h> #include <spdlog/async.h> #include <spdlog/sinks/stdout_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/basic_file_sink.h> #include <spdlog/sinks/syslog_sink.h> #include <utility> #include <cstdarg> #include "logger.hpp" #include "logger.h" //////////////////////////////////////////////////////////////////////////////// // Function implementations for the C API //////////////////////////////////////////////////////////////////////////////// void logger_setup(const char* ident, logger_type type, const char* log_file) { constexpr auto get_cxx_type = [](logger_type t) { switch(t) { case CONSOLE_LOGGER: return logger::logger_type::console; case CONSOLE_COLOR_LOGGER: return logger::logger_type::console_color; case FILE_LOGGER: return logger::logger_type::file; case SYSLOG_LOGGER: return logger::logger_type::syslog; default: return logger::logger_type::console; } }; logger::create_default_logger( logger::logger_config{ident, get_cxx_type(type), log_file}); } void logger_log(enum logger_level level, const char* fmt, ...) { using logger::logger_base; if(const auto logger = logger_base::get_default_logger(); logger) { std::array<char, LOGGER_MSG_MAX_LEN> msg; // NOLINT va_list args; va_start(args, fmt); vsnprintf(msg.data(), msg.size(), fmt, args); va_end(args); switch(level) { case info: logger->info(msg.data()); break; case debug: logger->debug(msg.data()); break; case warn: logger->warn(msg.data()); break; case error: logger->error(msg.data()); break; case critical: logger->critical(msg.data()); break; } } } void logger_destroy() { using logger::logger_base; if(logger_base::get_default_logger()) { ::logger::destroy_default_logger(); } } //////////////////////////////////////////////////////////////////////////////// // Function implementations for the C++ API //////////////////////////////////////////////////////////////////////////////// namespace { /** * @brief Creates a logger of the given type. * * @tparam Logger Type of the logger to create. * @param config Configuration for the logger. * @return std::shared_ptr<spdlog::logger> Pointer to the created logger. */ template <typename Logger> std::shared_ptr<spdlog::logger> create_logger(const logger::logger_config& config) requires(std::is_same_v<Logger, logger::sync_logger> || std::is_same_v<Logger, logger::async_logger>) { const auto create_helper = [&config]() { switch(config.type()) { case logger::console: { if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::stdout_logger_st(config.ident()); } return spdlog::stdout_logger_mt<spdlog::async_factory>( config.ident()); } case logger::console_color: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::stdout_color_st(config.ident()); } return spdlog::stdout_color_mt<spdlog::async_factory>( config.ident()); case logger::file: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::basic_logger_st( config.ident(), config.log_file().value_or(""), true); } return spdlog::basic_logger_mt<spdlog::async_factory>( config.ident(), config.log_file().value_or(""), true); case logger::syslog: if constexpr(std::is_same_v<Logger, logger::sync_logger>) { return spdlog::syslog_logger_st("syslog", config.ident(), LOG_PID); } return spdlog::syslog_logger_mt("syslog", config.ident(), LOG_PID); default: throw std::invalid_argument("Unknown logger type"); } }; try { auto logger = create_helper(); assert(logger != nullptr); logger->set_pattern(logger::default_pattern); #ifdef LOGGER_ENABLE_DEBUG logger->set_level(spdlog::level::debug); #endif spdlog::drop_all(); return logger; } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } } // namespace namespace logger { logger_base::logger_base(logger::logger_config config) : m_config(std::move(config)), m_internal_logger(::create_logger<async_logger>(m_config)) {} const logger_config& logger_base::config() const { return m_config; } std::shared_ptr<logger_base>& logger_base::get_default_logger() { static std::shared_ptr<logger_base> s_global_logger; return s_global_logger; } void logger_base::enable_debug() const { m_internal_logger->set_level(spdlog::level::debug); } void logger_base::flush() { m_internal_logger->flush(); } async_logger::async_logger(const logger_config& config) : logger_base(config) { try { m_internal_logger = ::create_logger<async_logger>(config); } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } sync_logger::sync_logger(const logger_config& config) : logger_base(config) { try { m_internal_logger = ::create_logger<sync_logger>(config); } catch(const spdlog::spdlog_ex& ex) { throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } } // namespace logger
src/logger/logger.h 0 → 100644 +79 −0 Original line number Diff line number Diff line /****************************************************************************** * Copyright 2021-2023, Barcelona Supercomputing Center (BSC), Spain * * This software was partially supported by the EuroHPC-funded project ADMIRE * (Project ID: 956748, https://www.admire-eurohpc.eu). * * This file is part of Cargo. * * Cargo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cargo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cargo. If not, see <https://www.gnu.org/licenses/>. * * SPDX-License-Identifier: GPL-3.0-or-later *****************************************************************************/ #ifndef SCORD_LOGGER_H #define SCORD_LOGGER_H #include "macros.h" #ifdef __cplusplus extern "C" { #endif #define LOGGER_MSG_MAX_LEN 2048 enum logger_type { CONSOLE_LOGGER, CONSOLE_COLOR_LOGGER, FILE_LOGGER, SYSLOG_LOGGER }; enum logger_level { info, debug, warn, error, critical }; /** * Initialize a global logger. * * Valid logger types: * - console * - console color * - file * * @param ident The identifier that should be used when emitting messages * @param type The type of logger desired. * @param log_file The path to the log file where messages should be written. */ void setup_logger(const char* ident, enum logger_type type, const char* log_file); /** * Emit a message. * * @param level The level for the message. * @param fmt A vprintf()-compatible format string. * @param ... A sequence of arguments corresponding to the format string. */ void logger_log(enum logger_level level, const char* fmt, ...); /** * Destroy the global logger. */ void destroy_logger(); #ifdef __cplusplus }; // extern "C" #endif #endif // SCORD_LOGGER_H