From 2662ed89e2cd41477582140e482f1ddbbfdb235e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 3 Dec 2013 18:27:20 +0100 Subject: Add a logger class --- CMakeLists.txt | 15 ++++++++++- src/irc/irc_client.cpp | 1 + src/logger/logger.cpp | 41 +++++++++++++++++++++++++++++ src/logger/logger.hpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.cpp | 9 +++++++ 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/logger/logger.cpp create mode 100644 src/logger/logger.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index daa6cf6..51253cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,10 @@ set(${PROJECT_NAME}_VERSION_MINOR 1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og") +# Define a __FILENAME__ macro to get the filename of each file, instead of +# the full path as in __FILE__ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + # ## Look for external libraries # @@ -46,6 +50,14 @@ file(GLOB source_config add_library(config STATIC ${source_config}) target_link_libraries(config utils) +# +## logger +# +file(GLOB source_logger + src/logger/*.[hc]pp) +add_library(logger STATIC ${source_logger}) +target_link_libraries(logger config) + # ## network # @@ -99,6 +111,7 @@ target_link_libraries(test irc bridge utils - config) + config + logger) configure_file(config.h.cmake src/config.h) diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp index 0061561..4e5efe1 100644 --- a/src/irc/irc_client.cpp +++ b/src/irc/irc_client.cpp @@ -4,6 +4,7 @@ #include #include +// #include #include #include diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp new file mode 100644 index 0000000..eac833f --- /dev/null +++ b/src/logger/logger.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +Logger::Logger(const int log_level): + log_level(log_level), + stream(std::cout.rdbuf()) +{ + std::cout << "Logger(1)" << std::endl; +} + +Logger::Logger(const int log_level, const std::string& log_file): + log_level(log_level), + ofstream(log_file.data(), std::ios_base::app), + stream(ofstream.rdbuf()) +{ + std::cout << "Logger(" << this->log_level << ")" << std::endl; +} + +std::unique_ptr& Logger::instance() +{ + static std::unique_ptr instance; + + if (!instance) + { + const std::string log_file = Config::get("log_file", ""); + const int log_level = Config::get_int("log_level", 0); + if (log_file.empty()) + instance = std::make_unique(log_level); + else + instance = std::make_unique(log_level, log_file); + } + return instance; +} + +std::ostream& Logger::get_stream(const int lvl) +{ + if (lvl >= this->log_level) + return this->stream; + return this->null_stream; +} diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp new file mode 100644 index 0000000..182c517 --- /dev/null +++ b/src/logger/logger.hpp @@ -0,0 +1,70 @@ +#ifndef LOGGER_INCLUDED +# define LOGGER_INCLUDED + +/** + * Singleton used in logger macros to write into files or stdout, with + * various levels of severity. + * Only the macros should be used. + * @class Logger + */ + +#include +#include +#include + +#define debug_lvl 0 +#define info_lvl 1 +#define warning_lvl 2 +#define error_lvl 3 + +// Macro defined to get the filename instead of the full path. But if it is +// not properly defined by the build system, we fallback to __FILE__ +#ifndef __FILENAME__ +# define __FILENAME__ __FILE__ +#endif + +#define WHERE\ + __FILENAME__ << ":" << __LINE__ + +#define log_debug(text)\ + Logger::instance()->get_stream(debug_lvl) << "[DEBUG]:" << WHERE << ":\t" << text << std::endl; + +#define log_info(text)\ + Logger::instance()->get_stream(info_lvl) << "[INFO]:" << WHERE << ":\t" << text << std::endl; + +#define log_warning(text)\ + Logger::instance()->get_stream(warning_lvl) << "[WARNING]:" << WHERE << ":\t" << text << std::endl; + +#define log_error(text)\ + Logger::instance()->get_stream(error_lvl) << "[ERROR]:" << WHERE << ":\t" << text << std::endl; + +/** + * Juste a structure representing a stream doing nothing with its input. + */ +class nullstream: public std::ostream +{ +public: + nullstream(): + std::ostream(0) + { } +}; + +class Logger +{ +public: + static std::unique_ptr& instance(); + std::ostream& get_stream(const int); + Logger(const int log_level, const std::string& log_file); + Logger(const int log_level); + +private: + Logger(const Logger&); + Logger& operator=(const Logger&); + + const int log_level; + std::ofstream ofstream; + nullstream null_stream; + std::ostream stream; +}; + +#endif // LOGGER_INCLUDED diff --git a/src/test.cpp b/src/test.cpp index 234ab2d..ac1a85d 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -170,5 +171,13 @@ int main() } assert(error == false); + Config::set("log_level", "3"); + Config::set("log_file", ""); + + log_debug("coucou"); + log_info("coucou"); + log_warning("coucou"); + log_error("coucou"); + return 0; } -- cgit v1.2.3