__>>http://logging.apache.org/log4cxx/
КЛ>Спасибо за ссылку, но что-то типа этого у меня и было. Хотелось избавиться от вызова именно методов с фиксированным кол-ом параметров, и, следовательно, с конкатенацией строк.
В log4cxx вывод идёт через std::strstream — никаких методов с фиксированным кол-вом параметров.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, Константин Ленин, Вы писали:
Вот окончательная версия
namespace Logging
{
typedef ATL::CString String;
enum LogLevel
{
LogDebug = 0,
LogInfo,
LogWarning,
LogError,
LogNo
};
LPCTSTR LogLevelToString( LogLevel level );
class ILogger
{
protected:
virtual void WriteEntry_( LogLevel level, LPCTSTR message ) = 0;
~ILogger(){}
public:
void WriteEntry(LogLevel level, LPCTSTR message );
};
class LogEntry
{
private:
ILogger* pLogger_;
std::auto_ptr<String> pBuffer_;
LogLevel Level_;
LogEntry& operator =( const LogEntry& );
public:
LogEntry::LogEntry( LogLevel level, ILogger* pLogger )
: Level_( level ),
pLogger_( pLogger ),
pBuffer_( new String() )
{}
LogEntry::LogEntry( LogEntry& entry )
: Level_( entry.Level_ ),
pLogger_( entry.pLogger_ ),
pBuffer_( entry.pBuffer_ )
{
entry.pLogger_ = NULL;
}
LogEntry::~LogEntry()
{
try
{
if( pBuffer_.get() && !pBuffer_->IsEmpty() && pLogger_ ) pLogger_->WriteEntry( Level_, (*pBuffer_) );
}
catch(...){}
}
LogEntry LogEntry::print( LPCTSTR value )
{
if( value && _tcslen(value) ) (*pBuffer_) += value;
return *this;
}
};
template <typename Logger>
LogEntry log( LogLevel level )
{
return LogEntry(level, &Logger::Instance() );
}
class HR
{
public:
HRESULT HR_;
explicit HR( HRESULT hr )
: HR_(hr)
{}
};
LogEntry operator <<( LogEntry& entry, LPCTSTR value );
LogEntry operator <<( LogEntry& entry, int value );
LogEntry operator <<( LogEntry& entry, unsigned int value );
LogEntry operator <<( LogEntry& entry, long value );
LogEntry operator <<( LogEntry& entry, unsigned long value );
LogEntry operator <<( LogEntry& entry, const HR& hr );
LogEntry operator <<( LogEntry& entry, LogEntry (*manip)( LogEntry& ) );
//manipulators
LogEntry dot( LogEntry& entry );
LogEntry colon( LogEntry& entry );
LogEntry endl( LogEntry& entry );
LogEntry comma( LogEntry& entry );
//endof manipulators
template <typename MTPolicy>
class FileLogger : public Logging::ILogger, protected MTPolicy
{
private:
class AutoLock
{
const FileLogger* pLogger_;
public:
AutoLock( const FileLogger* pLogger )
: pLogger_( pLogger )
{
pLogger->Lock();
}
~AutoLock()
{
pLogger_->Unlock();
pLogger_ = NULL;
}
};
private:
FileLogger& operator =( const FileLogger& );
FileLogger( const FileLogger& );
~FileLogger();
public:
FileLogger();
static FileLogger& Instance()
{
static FileLogger fileLogger;
return fileLogger;
}
private:
//ILogger implementation
void WriteEntry_( LogLevel level, LPCTSTR message );
};
class MultiThreadedPolicy;
typedef FileLogger<MultiThreadedPolicy> DefaultLogger;
template <typename T>
LogEntry operator <<( LogLevel level, const T& value )
{
return LogEntry(level, &DefaultLogger::Instance() ) << value;
}
class MethodTracer
{
public:
MethodTracer::MethodTracer(LPCTSTR location, HRESULT* pHr)
: pHr_(pHr),
Location_(location)
{
LogInfo<<_T("Enter -> ") << Location_<< endl;
}
MethodTracer::~MethodTracer()
{
try
{
LogInfo<< _T("Return( ") << HR( pHr_ != NULL? *pHr_ : S_OK ) << _T(" ) <- ") << Location_ << endl;
}
catch( ... ){}
}
private:
String Location_;
HRESULT* pHr_;
};
//MT policies
class SingleThreadedPolicy
{
protected:
SingleThreadedPolicy(){}
void Lock(){}
void Unlock(){}
};
class MultiThreadedPolicy
{
mutable ATL::CComAutoCriticalSection Mutex_;
protected:
MultiThreadedPolicy(){}
void Lock() const
{
Mutex_.Lock();
}
void Unlock() const
{
Mutex_.Unlock();
}
};
}