corelib/src/TextFileLogger.cc

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;
}
}