5367ebddbd
- aggiornamento prototipi.
230 lines
7.1 KiB
C++
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 ;
|
|
}
|
|
}
|
|
} ;
|
|
}
|