Files
Include/EgtLogger.h
Dario Sassi 5367ebddbd Include :
- aggiornamento prototipi.
2023-12-29 13:08:44 +01:00

230 lines
7.1 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2023
//----------------------------------------------------------------------------
// File : EgtLogger.h Data : 15.12.23 Versione : 2.5l3
// Contenuto : Classi per logger.
//
//
//
// Modifiche : 06.12.13 DS Creazione modulo.
// 15.12.23 DS Ora default è thread safe.
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EgtILogger.h"
#include <iostream>
#include <vector>
#define NOMINMAX
#include <Windows.h>
#include <time.h>
//----------------------------------------------------------------------------
namespace egtlogger
{
//----------------------------------------------------------------------------
class IntraProcessLock
{
public :
IntraProcessLock( bool bThreadSafe)
: m_bThreadSafe( bThreadSafe)
{
if ( m_bThreadSafe)
InitializeCriticalSection( &m_cs) ;
}
~IntraProcessLock( void)
{
if ( m_bThreadSafe)
DeleteCriticalSection( &m_cs) ;
}
void Lock( void)
{
if ( m_bThreadSafe)
EnterCriticalSection( &m_cs) ;
}
void Unlock( void)
{
if ( m_bThreadSafe)
LeaveCriticalSection( &m_cs) ;
}
private :
bool m_bThreadSafe ;
CRITICAL_SECTION m_cs ;
} ;
//----------------------------------------------------------------------------
class Logger : public ILogger
{
private :
struct StreamInfo
{
std::ostream* pStream ;
bool bOwned ;
LogLevel nLevel ;
StreamInfo( std::ostream* pStream, bool bOwned, LogLevel nLevel)
{
this->pStream = pStream ;
this->bOwned = bOwned ;
this->nLevel = nLevel ;
}
} ;
public :
Logger( LogLevel nLevel, const char* szName, bool bThreadSafe = true,
int nLoggableItems = LI_DATETIME | LI_LOGGERNAME | LI_LOGGERLEVEL | LI_FUNCTION | LI_LINENUMBER)
: m_nLevel( nLevel), m_name( szName), m_threadProtect( bThreadSafe), m_loggableItem( nLoggableItems)
{}
~Logger( void)
{
ClearOutputStreams() ;
}
void AddOutputStream( std::ostream& os, bool bOwn, LogLevel nLevel)
{
AddOutputStream( &os, bOwn, nLevel) ;
}
void AddOutputStream( std::ostream& os, bool bOwn)
{
AddOutputStream( os, bOwn, m_nLevel) ;
}
void AddOutputStream( std::ostream* os, bool bOwn)
{
AddOutputStream( os, bOwn, m_nLevel) ;
}
void AddOutputStream( std::ostream* os, bool bOwn, LogLevel nLevel)
{
StreamInfo si( os, bOwn, nLevel) ;
m_outputStreams.push_back( si) ;
}
void ClearOutputStreams( void)
{
for ( auto iter = m_outputStreams.cbegin() ; iter < m_outputStreams.cend() ; ++iter) {
if ( iter->bOwned)
delete iter->pStream ;
}
m_outputStreams.clear() ;
}
void Log( LogLevel nLevel, const char* szFile, int nLine, const char* szFunc, const char* szText)
{
Log( nLevel, m_loggableItem, szFile, nLine, szFunc, szText) ;
}
void Log( LogLevel nLevel, int nItem, const char* szFile, int nLine, const char* szFunc, const char* szText)
{
m_threadProtect.Lock() ;
for ( auto iter = m_outputStreams.cbegin() ; iter < m_outputStreams.cend() ; ++iter) {
if ( nLevel < iter->nLevel)
continue ;
bool bWritten = false ;
std::ostream* pStream = iter->pStream ;
if ( pStream == nullptr)
continue ;
if ( nItem & LI_DATETIME)
bWritten = write_datetime( bWritten, pStream) ;
if ( nItem & LI_THREADID)
bWritten = write<int>( GetCurrentThreadId(), bWritten, pStream) ;
if ( nItem & LI_LOGGERNAME)
bWritten = write<const char*>( m_name.c_str(), bWritten, pStream) ;
if ( nItem & LI_LOGGERLEVEL) {
char strLevel[4] ;
LogLevelToString( nLevel, strLevel) ;
bWritten = write<const char*>( strLevel, bWritten, pStream) ;
}
if ( nItem & LI_FUNCTION)
bWritten = write<const char*>( szFunc, bWritten, pStream) ;
if ( nItem & LI_FILENAME)
bWritten = write<const char*>( szFile, bWritten, pStream) ;
if ( nItem & LI_LINENUMBER)
bWritten = write<int>( nLine, bWritten, pStream) ;
bWritten = write<const char*>( szText, bWritten, pStream) ;
if ( bWritten) {
(*pStream) << std::endl ;
pStream->flush() ;
}
}
m_threadProtect.Unlock() ;
}
private :
int m_loggableItem ;
LogLevel m_nLevel ;
std::string m_name ;
std::vector<StreamInfo> m_outputStreams ;
IntraProcessLock m_threadProtect ;
template <class T>
bool write( T data, bool bWritten, std::ostream* strm)
{
if ( bWritten)
(*strm) << " " ;
(*strm) << data ;
return true ;
}
bool write_datetime( bool bWritten, std::ostream* strm)
{
if ( bWritten)
(*strm) << " " ;
// seconds elapsed since midnight, January 1, 1970
time_t _time ;
time( &_time) ;
// structured time
tm _tm ;
if ( localtime_s( &_tm, &_time) != 0)
(*strm) << "time/date error" ;
// string format
const int DT_LEN = 24 ;
char szDateTime[DT_LEN] = { '\0'} ;
strftime( szDateTime, DT_LEN, "%Y/%m/%d %H:%M:%S", &_tm) ;
// output
(*strm) << szDateTime ;
return true ;
}
void LogLevelToString( LogLevel nLevel, char* strLevel)
{
switch ( nLevel) {
case LL_ERROR :
strcpy_s( strLevel, 4, "ERR") ;
break ;
case LL_WARN :
strcpy_s( strLevel, 4, "WRN") ;
break ;
case LL_INFO :
strcpy_s( strLevel, 4, "INF") ;
break ;
case LL_DEBUG :
strcpy_s( strLevel, 4, "DBG") ;
break ;
}
}
} ;
}