@ -1,12 +1,15 @@
# include "LogManager.h"
# include <stdarg.h>
# include <iostream>
# include "ResourceManager.h"
# define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
# include <experimental/filesystem>
namespace fs = std : : experimental : : filesystem ;
static const char * log_codes [ ] = { " CRITICAL " , " ERROR " , " Message " , " Warning " , " Notice " , " [verbose] " , " Debug " } ;
LogManager : : LogManager ( )
{
}
@ -94,36 +97,11 @@ void LogManager::configure(json config, const std::string &defaultDir)
const json & loglevel_obj = config [ " loglevel " ] ;
/*-------------------------------------------------*\
| If the log level is configured per section , set |
| loglevel for each section |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( loglevel_obj . is_object ( ) )
{
for ( size_t section = 0 ; section < sections . size ( ) ; + + section )
{
if ( loglevel_obj . contains ( sections [ section ] ) )
{
const json & val = loglevel_obj [ sections [ section ] ] ;
if ( val . is_number_integer ( ) )
{
loglevels [ section ] = val ;
}
}
}
}
/*-------------------------------------------------*\
| If the log level is configured globally , set same |
| loglevel for each section |
| Set the log level if configured |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
else if( loglevel_obj . is_number_integer ( ) )
if ( loglevel_obj . is_number_integer ( ) )
{
int l = loglevel_obj ;
for ( size_t section = 0 ; section < sections . size ( ) ; + + section )
{
loglevels [ section ] = l ;
}
loglevel = loglevel_obj ;
}
}
@ -142,10 +120,18 @@ void LogManager::_flush()
{
for ( size_t msg = 0 ; msg < temp_messages . size ( ) ; + + msg )
{
int sec = temp_sections [ msg ] ;
if ( temp_levels [ msg ] < = loglevels [ sec ] )
if ( temp_messages [ msg ] - > level < = loglevel )
{
log_stream < < temp_messages [ msg ] < < std : : endl ;
// Put the timestamp here
log_stream < < log_codes [ temp_messages [ msg ] - > level ] < < " : " ;
log_stream < < temp_messages [ msg ] - > buffer ;
if ( print_source )
{
log_stream < < " [ " < < temp_messages [ msg ] - > filename < < " : " < < temp_messages [ msg ] - > line < < " ] " ;
}
log_stream < < std : : endl ;
}
}
@ -153,8 +139,6 @@ void LogManager::_flush()
| Clear temp message buffers after writing them out |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
temp_messages . clear ( ) ;
temp_levels . clear ( ) ;
temp_sections . clear ( ) ;
}
/*-------------------------------------------------*\
@ -169,78 +153,164 @@ void LogManager::flush()
_flush ( ) ;
}
void LogManager : : append( int section , int level , const char * fmt , . . . )
void LogManager : : _append( const char * filename , int line , unsigned int level , const char * fmt , va_list va )
{
std : : lock_guard < std : : mutex > grd ( entry_mutex ) ;
/*-------------------------------------------------*\
| If a critical message occurs , enable source |
| printing and set loglevel and verbosity to highest |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( level = = LL_CRITICAL )
{
print_source = true ;
loglevel = LL_DEBUG ;
verbosity = LL_DEBUG ;
}
char buf [ 1024 ] ;
/*-------------------------------------------------*\
| Create a new message |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PLogMessage mes = std : : make_shared < LogMessage > ( ) ;
/*-------------------------------------------------*\
| Start the variable argument list |
| Resize the buffer , then fill in the message text |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
va_list va ;
va_start ( va , fmt ) ;
int len = vsnprintf ( nullptr , 0 , fmt , va ) ;
mes - > buffer . resize ( len ) ;
vsnprintf ( & mes - > buffer [ 0 ] , len + 1 , fmt , va ) ;
/*-------------------------------------------------*\
| Fill in message information |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
mes - > level = level ;
mes - > filename = filename ;
mes - > line = line ;
/*-------------------------------------------------*\
| Return if the log is already open |
| If the message is within the current verbosity , |
| print it on the screen |
| TODO : Put the timestamp here |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( ! log_stream . is_open ( ) & & level > loglevels [ section ] )
if ( level < = verbosity )
{
return ;
std : : cout < < mes - > buffer ;
if ( print_source )
{
std : : cout < < " [ " < < mes - > filename < < " : " < < mes - > line < < " ] " ;
}
std : : cout < < std : : endl ;
}
/*-------------------------------------------------*\
| Print the section to the log entry |
| If the message level is LL_MESSAGE or lower , add |
| it to the error queue |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int off = sprintf ( buf , " [%s]: " , sections [ section ] . c_str ( ) ) ;
if ( level < = LL_MESSAGE )
{
for ( size_t idx = 0 ; idx < error_callbacks . size ( ) ; + + idx )
{
error_callbacks [ idx ] . first ( error_callbacks [ idx ] . second , mes ) ;
}
}
/*-------------------------------------------------*\
| Print the log text to the log entry |
| Add the message to the logfile queue |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
vsnprintf ( buf + off , 1024 - off , fmt , va ) ;
temp_messages. push_back ( mes ) ;
/*-------------------------------------------------*\
| Write the log entry |
| Flush the queues |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( log_stream . is_open ( ) )
_flush ( ) ;
}
void LogManager : : append ( const char * filename , int line , unsigned int level , const char * fmt , va_list va )
{
std : : lock_guard < std : : mutex > grd ( entry_mutex ) ;
_append ( filename , line , level , fmt , va ) ;
}
void LogManager : : append ( const char * filename , int line , unsigned int level , const char * fmt , . . . )
{
va_list va ;
va_start ( va , fmt ) ;
std : : lock_guard < std : : mutex > grd ( entry_mutex ) ;
_append ( filename , line , level , fmt , va ) ;
va_end ( va ) ;
}
void LogManager : : setLoglevel ( unsigned int level )
{
/*-------------------------------------------------*\
| Check that the new log level is valid , otherwise |
| set it within the valid range |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( level < LL_CRITICAL )
{
log_stream < < buf < < std : : endl ;
l evel = LL_CRITICAL ;
}
else
if ( level > LL_DEBUG )
{
temp_levels . push_back ( level ) ;
temp_messages . push_back ( buf ) ;
temp_sections . push_back ( section ) ;
level = LL_DEBUG ;
}
LOG_DEBUG ( " Loglevel set to %d " , level ) ;
/*-------------------------------------------------*\
| End the variable argument list |
| Set the new log level |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
va_end ( va ) ;
loglevel = level ;
}
int LogManager : : registerSection ( const char * name , int loglevel )
void LogManager : : setVerbosity ( unsigned int level)
{
std : : lock_guard < std : : mutex > grd ( section_mutex ) ;
size_t section ;
/*-------------------------------------------------*\
| Check to see if section already exists , if so , |
| return the existing section value |
| Check that the new verbosity is valid , otherwise |
| set it within the valid range |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
for ( section = 0 ; section < sections . size ( ) ; section + + )
if( level < LL_CRITICAL )
{
if ( sections [ section ] = = name )
{
return section ;
}
level = LL_CRITICAL ;
}
if ( level > LL_DEBUG )
{
level = LL_DEBUG ;
}
LOG_DEBUG ( " Verbosity set to %d " , level ) ;
/*-------------------------------------------------*\
| If section does not already exist , create it |
| Set the new verbosity |
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
sections . push_back ( name ) ;
loglevels . push_back ( loglevel ) ;
verbosity = level ;
}
void LogManager : : setPrintSource ( bool v )
{
LOG_DEBUG ( " Source code location printouts were %s " , v ? " enabled " : " disabled " ) ;
print_source = v ;
}
void LogManager : : registerErrorCallback ( LogErrorCallback callback , void * receiver )
{
std : : lock_guard < std : : mutex > grd ( entry_mutex ) ;
error_callbacks . push_back ( LogErrorBlock ( callback , receiver ) ) ;
}
void LogManager : : unregisterErrorCallback ( LogErrorCallback callback , void * receiver )
{
std : : lock_guard < std : : mutex > grd ( entry_mutex ) ;
return section ;
for ( size_t idx = 0 ; idx < error_callbacks . size ( ) ; + + idx )
{
if ( error_callbacks [ idx ] . first = = callback & & error_callbacks [ idx ] . second = = receiver )
{
error_callbacks . erase ( error_callbacks . begin ( ) + idx ) ;
}
}
}