Skip to content

Commit

Permalink
Merge pull request #4 from njoy/develop
Browse files Browse the repository at this point in the history
Adding the Log tool
  • Loading branch information
whaeck authored Oct 12, 2023
2 parents b11bac0 + 5bcc6e9 commit 25c9273
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if( DEFINED PROJECT_NAME )
endif()

project( tools
VERSION 0.1.0
VERSION 0.2.0
LANGUAGES CXX
)

Expand Down
2 changes: 2 additions & 0 deletions cmake/unit_testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ endfunction()
#######################################################################
# Unit testing directories
#######################################################################

add_subdirectory( src/tools/Log/test )
132 changes: 132 additions & 0 deletions src/tools/Log.hpp
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
1 change: 1 addition & 0 deletions src/tools/Log/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_cpp_test( Log Log.test.cpp )
57 changes: 57 additions & 0 deletions src/tools/Log/test/Log.test.cpp
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

0 comments on commit 25c9273

Please sign in to comment.