-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from njoy/develop
Adding the Log tool
- Loading branch information
Showing
5 changed files
with
193 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ if( DEFINED PROJECT_NAME ) | |
endif() | ||
|
||
project( tools | ||
VERSION 0.1.0 | ||
VERSION 0.2.0 | ||
LANGUAGES CXX | ||
) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#ifndef NJOY_TOOLS_LOG | ||
#define NJOY_TOOLS_LOG | ||
|
||
// system includes | ||
|
||
// other includes | ||
#include "spdlog/spdlog.h" | ||
#include "spdlog/sinks/stdout_color_sinks.h" | ||
#include "spdlog/sinks/basic_file_sink.h" | ||
|
||
namespace njoy { | ||
namespace tools { | ||
|
||
/** | ||
* @brief A singleton logger for njoy components | ||
*/ | ||
class Log { | ||
|
||
static auto initialize_logger() { | ||
|
||
auto instance = spdlog::stdout_color_st( "njoy" ); | ||
instance->set_pattern( "[%^%l%$] %v" ); | ||
#ifndef NDEBUG | ||
instance->set_level( spdlog::level::debug ); | ||
#endif | ||
return instance; | ||
} | ||
|
||
static auto& logger() { | ||
|
||
static auto instance = initialize_logger(); | ||
return instance; | ||
} | ||
|
||
/* constructors */ | ||
Log() {}; // private to avoid creation of Log instances | ||
|
||
public: | ||
|
||
Log( const Log& ) = delete; | ||
void operator=( const Log& ) = delete; | ||
|
||
/** | ||
* @brief Direct the logger output to the given file | ||
*/ | ||
static void add_sink( const std::string& filename ) { | ||
|
||
auto sink_ptr = std::make_shared< spdlog::sinks::basic_file_sink_st >( filename ); | ||
sink_ptr->set_pattern( "[%^%l%$] %v" ); | ||
logger()->sinks().push_back( sink_ptr ); | ||
} | ||
|
||
/** | ||
* @brief Flush the logger | ||
*/ | ||
static void flush() { | ||
|
||
logger()->flush(); | ||
} | ||
|
||
/** | ||
* @brief Print a message at the info level | ||
* | ||
* For example: | ||
* | ||
* int value = 10; | ||
* utility::Log::info( "Some message with a value {}", value ); | ||
*/ | ||
template< typename... Args > | ||
static void info( Args... args ) { | ||
|
||
logger()->info( std::forward< Args >( args )... ); | ||
} | ||
|
||
/** | ||
* @brief Print a message at the warning level | ||
* | ||
* For example: | ||
* | ||
* int value = 10; | ||
* utility::Log::warning( "Some message with a value {}", value ); | ||
*/ | ||
template< typename... Args > | ||
static void warning( Args... args ) { | ||
|
||
logger()->warn( std::forward< Args >( args )... ); | ||
} | ||
|
||
/** | ||
* @brief Print a message at the error level | ||
* | ||
* For example: | ||
* | ||
* int value = 10; | ||
* utility::Log::info( "Some message with a value {}", value ); | ||
*/ | ||
template< typename... Args > | ||
static void error( Args... args ) { | ||
|
||
logger()->error( std::forward< Args >( args )... ); | ||
} | ||
|
||
/** | ||
* @brief Print a message at the debug level | ||
* | ||
* This only prints when NDEBUG is defined when compiling this code. | ||
* | ||
* For example: | ||
* | ||
* int value = 10; | ||
* utility::Log::debug( "Some message with a value {}", value ); | ||
*/ | ||
#ifdef NDEBUG | ||
template< typename... Args > | ||
static void debug( Args... ) {} | ||
#else | ||
template< typename... Args > | ||
static void debug( Args... args ) { | ||
|
||
logger()->debug( std::forward< Args >( args )... ); | ||
} | ||
#endif | ||
}; | ||
|
||
} // tools namespace | ||
|
||
/* type alias - for backwards compatibility reasons */ | ||
using Log = tools::Log; | ||
|
||
} // njoy namespace | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
add_cpp_test( Log Log.test.cpp ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// include Catch2 | ||
#include <catch2/catch_test_macros.hpp> | ||
|
||
// what we are testing | ||
#include "tools/Log.hpp" | ||
|
||
// other includes | ||
#include <fstream> | ||
#include <sstream> | ||
#include <filesystem> | ||
|
||
// convenience typedefs | ||
using namespace njoy::tools; | ||
|
||
std::string getContent( std::string filename ) { | ||
|
||
std::stringstream ss; | ||
std::ifstream fs( filename, std::ifstream::in ); | ||
ss << fs.rdbuf(); | ||
return ss.str(); | ||
} | ||
|
||
SCENARIO( "Log" ) { | ||
|
||
GIVEN( "a file name" ) { | ||
|
||
std::string filename = "output.txt"; | ||
std::filesystem::remove( filename ); // ensure the file is not there | ||
|
||
WHEN( "the Log redirects to a file" ) { | ||
|
||
Log::add_sink( filename ); | ||
|
||
THEN( "the file contains the log after flushing" ) { | ||
|
||
Log::error( "Some error occurred" ); | ||
Log::warning( "Some warning was issued" ); | ||
Log::info( "Some info was printed" ); | ||
Log::debug( "Some debug info was given" ); | ||
Log::flush(); | ||
|
||
std::string content = getContent( filename ); | ||
|
||
#ifdef NDEBUG | ||
CHECK( "[error] Some error occurred\n" | ||
"[warning] Some warning was issued\n" | ||
"[info] Some info was printed\n" == content ); | ||
#else | ||
CHECK( "[error] Some error occurred\n" | ||
"[warning] Some warning was issued\n" | ||
"[info] Some info was printed\n" | ||
"[debug] Some debug info was given\n" == content ); | ||
#endif | ||
} // THEN | ||
} // WHEN | ||
} // GIVEN | ||
} // SCENARIO |