I wanted to make an extremely light-weight logging system. What are your thoughts on this and what can be done to improve it?
First, the usage:
int main( )
{
logging::level = logging::fatal | logging::warning;
mini_log( logging::fatal, "entry point", "nothing", " is ", "happening!" );
}
Now, the code:
#if defined( NDEBUG )
#define mini_log( ... ) static_cast< void >( 0 )
#else
namespace logging
{
enum level_t
{
none = 0b00000,
information = 0b00001,
debug = 0b00010,
warning = 0b00100,
error = 0b01000,
fatal = 0b10000,
all = 0b11111
} inline level = all; // level should only be used in the entry point
inline std::mutex stream;
}
#define mini_log \
[ ]( logging::level_t const level_message, \
std::string_view const location, \
auto &&... message ) -> void \
{ \
std::lock_guard< std::mutex > lock_stream( logging::stream ); \
struct tm buf; \
auto time = [ & ]( ) \
{ \
auto t = std::time( nullptr ); \
localtime_s( &buf, \
&t ); \
return std::put_time( &buf, \
"[%H:%M:%S]" ); \
}; \
auto level = [ = ]( ) -> std::string \
{ \
switch( level_message ) \
{ \
case logging::information: \
return " [" __FILE__ "@" stringize_val( __LINE__ ) "] [Info] ["; \
case logging::debug: \
return " [" __FILE__ "@" stringize_val( __LINE__ ) "] [Dbug] ["; \
case logging::warning: \
return " [" __FILE__ "@" stringize_val( __LINE__ ) "] [Warn] ["; \
case logging::error: \
return " [" __FILE__ "@" stringize_val( __LINE__ ) "] [Erro] ["; \
case logging::fatal: \
return " [" __FILE__ "@" stringize_val( __LINE__ ) "] [Fatl] ["; \
} \
}; \
if( level_message & logging::level ) \
( ( std::cout << time( ) << level( ) << location << "]: " << message ) << ... ) << '\n'; \
}
#endif