159 lines
4.5 KiB
C++
159 lines
4.5 KiB
C++
/******************************************************************************/
|
|
/* LOGGING SYSTEM - BUILT-IN LOGGERS - TEXT FILE LOGGER ***********************/
|
|
/******************************************************************************/
|
|
|
|
#include <lw/lib/BuiltinLoggers.hh>
|
|
#include <lw/lib/SRDParser.hh>
|
|
using namespace lw;
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
char const* const V_Name_ = "text-file";
|
|
inline T_String Name_( ) { return T_String::Pooled( V_Name_ ); }
|
|
|
|
bool TFLCPath_( T_SRDParserData const& data )
|
|
{
|
|
auto const& ptok( (*data.input)[ 1 ] );
|
|
T_VFSPath path( ptok.stringValue( ) );
|
|
path = path.normalize( );
|
|
if ( path.type( ) != E_VFSPathType::ABSOLUTE ) {
|
|
data.errors.add( "invalid path" , ptok );
|
|
} else {
|
|
auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
|
|
( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setPath( std::move( path ) );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TFLCAppend_( T_SRDParserData const& data )
|
|
{
|
|
auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
|
|
( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setAppend( true );
|
|
return true;
|
|
}
|
|
|
|
bool TFLCTruncate_( T_SRDParserData const& data )
|
|
{
|
|
auto lconf( data.targetData->value< RP_LogWriterConfiguration >( ) );
|
|
( dynamic_cast< T_TextFileLogWriterCfg* >( lconf ) )->setAppend( false );
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*= T_TextFileLogWriterFactory ==================================================*/
|
|
|
|
T_TextFileLogWriterFactory::T_TextFileLogWriterFactory( T_VFS& vfs )
|
|
: A_LogWriterFactory( Name_( ) ) , vfs_( vfs )
|
|
{ }
|
|
|
|
RP_LogWriterConfiguration T_TextFileLogWriterFactory::createConfiguration( T_String const& name ) const
|
|
{
|
|
RP_LogWriterConfiguration p( new T_TextFileLogWriterCfg( ) );
|
|
p->setName( name );
|
|
return p;
|
|
}
|
|
|
|
OP_LogWriter T_TextFileLogWriterFactory::createLogWriter( OP_LogWriterConfiguration&& configuration ) const
|
|
{
|
|
T_TextFileLogWriter* p( new T_TextFileLogWriter( std::move( configuration ) , vfs_ ) );
|
|
return OwnRawPointer( p );
|
|
}
|
|
|
|
void T_TextFileLogWriterFactory::initializeSyntax( T_SRDParserDefs& , T_SRDContext& main ) const
|
|
{
|
|
using namespace lw::SRD;
|
|
main << ( Rule( ) << "file" << Text( ) << TFLCPath_ );
|
|
main << ( Rule( ) << "append" << TFLCAppend_ );
|
|
main << ( Rule( ) << "truncate" << TFLCTruncate_ );
|
|
}
|
|
|
|
|
|
/*= T_TextFileLogWriterCfg ======================================================*/
|
|
|
|
T_TextFileLogWriterCfg::T_TextFileLogWriterCfg( )
|
|
: T_LogWriterConfiguration( Name_( ) )
|
|
{ }
|
|
|
|
T_TextFileLogWriterCfg::T_TextFileLogWriterCfg( T_TextFileLogWriterCfg const& source )
|
|
: T_LogWriterConfiguration( source ) , path_( source.path_ ) ,
|
|
append_( source.append_ )
|
|
{ }
|
|
|
|
OP_LogWriterConfiguration T_TextFileLogWriterCfg::clone( )
|
|
{
|
|
T_TextFileLogWriterCfg* ptr( new T_TextFileLogWriterCfg( *this ) );
|
|
return OwnRawPointer( ptr );
|
|
}
|
|
|
|
void T_TextFileLogWriterCfg::check( T_SRDErrors& errors , T_SRDList const& input )
|
|
{
|
|
T_LogWriterConfiguration::check( errors , input );
|
|
if ( path_.type( ) == E_VFSPathType::UNKNOWN || path_.elements( ) == 0 ) {
|
|
errors.add( "no file selected" , input[ 0 ] );
|
|
}
|
|
}
|
|
|
|
|
|
/*= T_TextFileLogWriter =========================================================*/
|
|
|
|
T_TextFileLogWriter::T_TextFileLogWriter( OP_LogWriterConfiguration&& configuration , T_VFS& vfs )
|
|
: A_LogWriter( std::move( configuration ) ) , vfs_( vfs )
|
|
{ }
|
|
|
|
void T_TextFileLogWriter::log( T_LogTimestamp const& timestamp ,
|
|
E_LogLevel level , T_LogPath const& path ,
|
|
T_LogStringData const& data , uint32_t size )
|
|
{
|
|
using namespace std::chrono;
|
|
|
|
char timeBuffer[ 128 ];
|
|
std::time_t tst( T_LogTimestamp::clock::to_time_t( timestamp ) );
|
|
std::strftime( timeBuffer , 128 , "%Y-%m-%d %H:%M:%S" , std::gmtime( &tst ) );
|
|
const auto ms( ( duration_cast< milliseconds >( timestamp - T_LogTimestamp( ) ) ).count( ) % 1000 );
|
|
|
|
T_StringBuilder sb;
|
|
|
|
sb << timeBuffer << '.';
|
|
if ( ms < 100 ) {
|
|
sb << '0';
|
|
if ( ms < 10 ) {
|
|
sb << '0';
|
|
}
|
|
}
|
|
sb << ms << ' ' << path.toString( ) << " - " << level << ": ";
|
|
sb.append( &( (*data) [ 0 ] ) , size );
|
|
sb << '\n';
|
|
|
|
auto const& cfg( configuration< T_TextFileLogWriterCfg >( ) );
|
|
auto const& p( cfg.path( ) );
|
|
if ( !file_ ) {
|
|
vfs_.mkdir( p.parent( ) );
|
|
file_ = vfs_.file( p , cfg.append( ) ? E_FileMode::READ_WRITE : E_FileMode::OVERWRITE );
|
|
if ( !file_ ) {
|
|
disable( );
|
|
return;
|
|
}
|
|
|
|
try {
|
|
file_->open( );
|
|
} catch ( X_StreamError const& ) {
|
|
disable( );
|
|
file_.clear( );
|
|
return;
|
|
}
|
|
}
|
|
|
|
try {
|
|
file_->position( 0 , true );
|
|
file_->write( sb.data( ) , sb.size( ) );
|
|
file_->flush( );
|
|
} catch ( X_StreamError ) {
|
|
disable( );
|
|
file_.clear( );
|
|
return;
|
|
}
|
|
}
|