39const char*
Logger::__levels[] = {
"None",
"Error",
"Warning",
"Info",
"Debug",
"Constructors",
"Locks" };
45 if ( param ==
nullptr )
return nullptr;
48# ifdef H2CORE_HAVE_DEBUG
51 freopen(
"CONOUT$",
"wt", stdout );
54 FILE* log_file =
nullptr;
56 log_file = fopen( logger->
m_sLogFilePath.toLocal8Bit().data(),
"w" );
58 fprintf( stderr,
"%s",
59 QString(
"Error: can't open log file [%1] for writing...\n" )
64 Logger::queue_t::iterator it, last;
67 pthread_mutex_lock( &logger->
__mutex );
69 pthread_mutex_unlock( &logger->
__mutex );
70 if( !queue->empty() ) {
71 for( it = last = queue->begin() ; it != queue->end() ; ++it ) {
74 fprintf( stdout,
"%s", it->toLocal8Bit().data() );
78 fprintf( log_file,
"%s", it->toLocal8Bit().data() );
83 pthread_mutex_lock( &logger->
__mutex );
84 queue->erase( queue->begin(), last );
86 pthread_mutex_unlock( &logger->
__mutex );
90 fprintf( log_file,
"Stop logger" );
98 pthread_exit(
nullptr );
115 m_sLogFilePath( sLogFilePath ),
116 m_bUseStdout( bUseStdout ) {
121 QFileInfo fiParentFolder( fiLogFile.absolutePath() );
122 if ( ( fiLogFile.exists() && ! fiLogFile.isWritable() ) ||
123 ( ! fiLogFile.exists() && ! fiParentFolder.isWritable() ) ) {
132 pthread_attr_init( &attr );
133 pthread_mutex_init( &
__mutex,
nullptr );
144void Logger::log(
unsigned level,
const QString& class_name,
const char* func_name,
const QString& msg ) {
150 const char* prefix[] = {
"",
"(E) ",
"(W) ",
"(I) ",
"(D) ",
"(C)",
"(L) " };
152 const char* color[] = {
"",
"",
"",
"",
"",
"",
"" };
154 const char* color[] = {
"",
"\033[31m",
"\033[36m",
"\033[32m",
"\033[35m",
"\033[35;1m",
"\033[35;1m" };
182 QString tmp = QString(
"%1%2%3::%4 %5\033[0m\n" )
189 pthread_mutex_lock( &
__mutex );
191 pthread_mutex_unlock( &
__mutex );
198 for (
int ii = 0; ii < nTimeout; ++ii ) {
203 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
212 }
else if ( 0 == strncasecmp( level,
__levels[1], strlen(
__levels[1] ) ) ) {
214 }
else if ( 0 == strncasecmp( level,
__levels[2], strlen(
__levels[2] ) ) ) {
216 }
else if ( 0 == strncasecmp( level,
__levels[3], strlen(
__levels[3] ) ) ) {
218 }
else if ( 0 == strncasecmp( level,
__levels[4], strlen(
__levels[4] ) ) ) {
220 }
else if ( 0 == strncasecmp( level,
__levels[5], strlen(
__levels[5] ) ) ) {
222 }
else if ( 0 == strncasecmp( level,
__levels[6], strlen(
__levels[6] ) ) ) {
226 int val = sscanf( level,
"%x",&log_level );
231 log_level =
hextoi( level, -1 );
232 if( log_level==-1 ) {
246 bool leading_zero =
false;
249 if( ( len!=-1 ) && ( pos>=len ) ) {
255 }
else if( c==
'x' || c==
'X' ) {
256 if ( ( pos==1 ) && leading_zero ) {
263 }
else if( c>=
'a' ) {
265 }
else if( c>=
'A' ) {
267 }
else if( c>=
'0' ) {
268 if ( ( c==
'0' ) && ( pos==0 ) ) {
279 res = ( res << 4 ) | v;
280 assert( ( res & 0xF ) == ( v & 0xF ) );
297 pThisContext =
new QString( sContext );
303 if ( pThisContext ) {
static QString log_file_path()
returns the full path (including filename) of the logfile
CrashContext(QString *pContext)
Class for writing logs to the console.
static Logger * create_instance(const QString &sLogFilePath=QString(), bool bUseStdout=true)
If __instance equals 0, a new H2Core::Logger singleton will be created and stored in it.
pthread_cond_t __messages_available
bool __use_file
write log to file if set to true
void log(unsigned level, const QString &class_name, const char *func_name, const QString &msg)
the log function
std::list< QString > queue_t
message queue type
pthread_mutex_t __mutex
lock for adding or removing elements only
void flush() const
Waits till the logger thread poped all remaining messages from __msg_queue.
bool __running
set to true when the logger thread is running
static Logger * __instance
Object holding the current H2Core::Logger singleton.
Logger(const QString &sLogFilePath=QString(), bool bUseStdout=true)
constructor
static int hextoi(const char *str, long len)
convert an hex string to an integer.
static Logger * bootstrap(unsigned msk, const QString &sLogFilePath=QString(), bool bUseStdout=true)
create the logger instance if not exists, set the log level and return the instance
queue_t __msg_queue
the message queue
static thread_local QString * pCrashContext
static const char * __levels[]
levels strings
static void set_bit_mask(unsigned msk)
set the bitmask
static unsigned parse_log_level(const char *lvl)
parse a log level string and return the corresponding bit mask
static unsigned __bit_msk
the bitmask of log_level_t
friend void * loggerThread_func(void *param)
needed for being able to access logger internal
void * loggerThread_func(void *param)