Add a path::preferred_string() function that generates a string in the platform's preferred format, using backslashes on win32 (uses boost::filesystem::path::make_preferred()).
Modify the log file configuration and rotating code to call to_native_ansi_path() and do more paths manipulation in fc::path objects and less in std::strings, in an attempt to improve BitShares/bitshares_toolkit#791
This commit is contained in:
parent
6cddd42cfe
commit
8def04f341
5 changed files with 87 additions and 50 deletions
|
|
@ -54,9 +54,14 @@ namespace fc {
|
||||||
fc::path parent_path()const;
|
fc::path parent_path()const;
|
||||||
fc::string string()const;
|
fc::string string()const;
|
||||||
fc::string generic_string()const;
|
fc::string generic_string()const;
|
||||||
|
/** On windows, returns a path where all path separators are '\' suitable for displaying
|
||||||
|
* to users. On other platforms, it does the same as generic_string()
|
||||||
|
*/
|
||||||
|
fc::string preferred_string() const;
|
||||||
|
|
||||||
std::wstring wstring() const;
|
std::wstring wstring() const;
|
||||||
std::wstring generic_wstring() const;
|
std::wstring generic_wstring() const;
|
||||||
|
std::wstring preferred_wstring() const;
|
||||||
|
|
||||||
/** Retrieves native string path representation and next converts it into
|
/** Retrieves native string path representation and next converts it into
|
||||||
ANSI UTF-8 representation.
|
ANSI UTF-8 representation.
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,14 @@
|
||||||
namespace fc {
|
namespace fc {
|
||||||
class path;
|
class path;
|
||||||
struct appender_config {
|
struct appender_config {
|
||||||
appender_config(const fc::string& n="",const fc::string& t="", variant a=variant())
|
appender_config(const string& name = "",
|
||||||
:name(n),type(t),args(fc::move(a)),enabled(true){}
|
const string& type = "",
|
||||||
|
variant args = variant()) :
|
||||||
|
name(name),
|
||||||
|
type(type),
|
||||||
|
args(fc::move(args)),
|
||||||
|
enabled(true)
|
||||||
|
{}
|
||||||
string name;
|
string name;
|
||||||
string type;
|
string type;
|
||||||
variant args;
|
variant args;
|
||||||
|
|
@ -13,7 +19,7 @@ namespace fc {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logger_config {
|
struct logger_config {
|
||||||
logger_config(const fc::string& n=""):name(n),enabled(true),additivity(false){}
|
logger_config(const fc::string& name = ""):name(name),enabled(true),additivity(false){}
|
||||||
string name;
|
string name;
|
||||||
ostring parent;
|
ostring parent;
|
||||||
/// if not set, then parents level is used.
|
/// if not set, then parents level is used.
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ void lzma_compress_file( const path& src_path,
|
||||||
FC_ASSERT( !exists( dst_path ) );
|
FC_ASSERT( !exists( dst_path ) );
|
||||||
|
|
||||||
boost::iostreams::mapped_file_source src_file;
|
boost::iostreams::mapped_file_source src_file;
|
||||||
src_file.open( src_path.string() );
|
src_file.open( src_path.to_native_ansi_path() );
|
||||||
FC_ASSERT( src_file.is_open() );
|
FC_ASSERT( src_file.is_open() );
|
||||||
|
|
||||||
elzma_compress_handle handle = NULL;
|
elzma_compress_handle handle = NULL;
|
||||||
|
|
@ -174,7 +174,7 @@ void lzma_decompress_file( const path& src_path,
|
||||||
FC_ASSERT( !exists( dst_path ) );
|
FC_ASSERT( !exists( dst_path ) );
|
||||||
|
|
||||||
boost::iostreams::mapped_file_source src_file;
|
boost::iostreams::mapped_file_source src_file;
|
||||||
src_file.open( src_path.string() );
|
src_file.open( src_path.to_native_ansi_path() );
|
||||||
FC_ASSERT( src_file.is_open() );
|
FC_ASSERT( src_file.is_open() );
|
||||||
|
|
||||||
elzma_decompress_handle handle = NULL;
|
elzma_decompress_handle handle = NULL;
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,11 @@ namespace fc {
|
||||||
return _p->generic_string();
|
return _p->generic_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fc::string path::preferred_string() const
|
||||||
|
{
|
||||||
|
return boost::filesystem::path(*_p).make_preferred().string();
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring path::wstring() const
|
std::wstring path::wstring() const
|
||||||
{
|
{
|
||||||
return _p->wstring();
|
return _p->wstring();
|
||||||
|
|
@ -101,6 +106,11 @@ namespace fc {
|
||||||
return _p->generic_wstring();
|
return _p->generic_wstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring path::preferred_wstring() const
|
||||||
|
{
|
||||||
|
return boost::filesystem::path(*_p).make_preferred().wstring();
|
||||||
|
}
|
||||||
|
|
||||||
std::string path::to_native_ansi_path() const
|
std::string path::to_native_ansi_path() const
|
||||||
{
|
{
|
||||||
std::wstring path = generic_wstring();
|
std::wstring path = generic_wstring();
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,10 @@
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
||||||
static const string compression_extension( ".lzma" );
|
static const string compression_extension( ".lzma" );
|
||||||
|
|
||||||
class file_appender::impl : public fc::retainable {
|
class file_appender::impl : public fc::retainable
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
config cfg;
|
config cfg;
|
||||||
ofstream out;
|
ofstream out;
|
||||||
|
|
@ -43,7 +44,7 @@ namespace fc {
|
||||||
return time_point::from_iso_string( str );
|
return time_point::from_iso_string( str );
|
||||||
}
|
}
|
||||||
|
|
||||||
void compress_file( const string& filename )
|
void compress_file( const fc::path& filename )
|
||||||
{
|
{
|
||||||
FC_ASSERT( cfg.rotate && cfg.rotation_compression );
|
FC_ASSERT( cfg.rotate && cfg.rotation_compression );
|
||||||
FC_ASSERT( _compression_thread );
|
FC_ASSERT( _compression_thread );
|
||||||
|
|
@ -55,7 +56,7 @@ namespace fc {
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lzma_compress_file( filename, filename + compression_extension );
|
lzma_compress_file( filename, filename.parent_path() / (filename.filename().string() + compression_extension) );
|
||||||
remove_all( filename );
|
remove_all( filename );
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
|
|
@ -101,11 +102,11 @@ namespace fc {
|
||||||
void rotate_files( bool initializing = false )
|
void rotate_files( bool initializing = false )
|
||||||
{
|
{
|
||||||
FC_ASSERT( cfg.rotate );
|
FC_ASSERT( cfg.rotate );
|
||||||
const auto now = time_point::now();
|
fc::time_point now = time_point::now();
|
||||||
const auto start_time = get_file_start_time( now, cfg.rotation_interval );
|
fc::time_point_sec start_time = get_file_start_time( now, cfg.rotation_interval );
|
||||||
const auto timestamp_string = timestamp_to_string( start_time );
|
string timestamp_string = timestamp_to_string( start_time );
|
||||||
const auto link_filename = cfg.filename.string();
|
fc::path link_filename = cfg.filename;
|
||||||
const auto log_filename = link_filename + "." + timestamp_string;
|
fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string);
|
||||||
|
|
||||||
{
|
{
|
||||||
fc::scoped_lock<boost::mutex> lock( slock );
|
fc::scoped_lock<boost::mutex> lock( slock );
|
||||||
|
|
@ -114,7 +115,9 @@ namespace fc {
|
||||||
{
|
{
|
||||||
if( start_time <= _current_file_start_time )
|
if( start_time <= _current_file_start_time )
|
||||||
{
|
{
|
||||||
_rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(2)" );
|
_rotation_task = schedule( [this]() { rotate_files(); },
|
||||||
|
_current_file_start_time + cfg.rotation_interval.to_seconds(),
|
||||||
|
"rotate_files(2)" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,36 +125,39 @@ namespace fc {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
out.open( log_filename.c_str() );
|
out.open( log_filename.to_native_ansi_path() );
|
||||||
}
|
}
|
||||||
remove_all( link_filename );
|
remove_all( link_filename );
|
||||||
create_hard_link( log_filename, link_filename );
|
create_hard_link( log_filename, link_filename );
|
||||||
|
|
||||||
/* Delete old log files */
|
/* Delete old log files */
|
||||||
const auto limit_time = now - cfg.rotation_limit;
|
fc::time_point limit_time = now - cfg.rotation_limit;
|
||||||
auto itr = directory_iterator( fc::path( link_filename ).parent_path() );
|
string link_filename_string = link_filename.filename().to_native_ansi_path();
|
||||||
|
directory_iterator itr(link_filename.parent_path());
|
||||||
for( ; itr != directory_iterator(); itr++ )
|
for( ; itr != directory_iterator(); itr++ )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto current_filename = itr->string();
|
string current_filename = itr->filename().string();
|
||||||
auto current_pos = current_filename.find( link_filename );
|
if (current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 ||
|
||||||
if( current_pos != 0 ) continue;
|
current_filename.size() <= link_filename_string.size() + 1)
|
||||||
current_pos = link_filename.size() + 1;
|
continue;
|
||||||
const auto current_timestamp_str = string( current_filename.begin() + current_pos, /* substr not working */
|
string current_timestamp_str = current_filename.substr(link_filename_string.size() + 1,
|
||||||
current_filename.begin() + current_pos + timestamp_string.size() );
|
timestamp_string.size());
|
||||||
const auto current_timestamp = string_to_timestamp( current_timestamp_str );
|
fc::time_point_sec current_timestamp = string_to_timestamp( current_timestamp_str );
|
||||||
if( current_timestamp < start_time )
|
if( current_timestamp < start_time )
|
||||||
{
|
{
|
||||||
if( current_timestamp < limit_time || file_size( current_filename ) <= 0 )
|
if( current_timestamp < limit_time || file_size( current_filename ) <= 0 )
|
||||||
{
|
{
|
||||||
remove_all( current_filename );
|
remove_all( *itr );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !cfg.rotation_compression ) continue;
|
if( !cfg.rotation_compression )
|
||||||
if( current_filename.find( compression_extension ) != string::npos ) continue;
|
continue;
|
||||||
compress_file( current_filename );
|
if( current_filename.find( compression_extension ) != string::npos )
|
||||||
|
continue;
|
||||||
|
compress_file( *itr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
|
|
@ -160,30 +166,37 @@ namespace fc {
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_file_start_time = start_time;
|
_current_file_start_time = start_time;
|
||||||
_rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(3)" );
|
_rotation_task = schedule( [this]() { rotate_files(); },
|
||||||
|
_current_file_start_time + cfg.rotation_interval.to_seconds(),
|
||||||
|
"rotate_files(3)" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
file_appender::config::config( const fc::path& p )
|
|
||||||
:format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
|
|
||||||
filename(p),flush(true),truncate(true),rotate(false),rotation_compression(true){}
|
|
||||||
|
|
||||||
file_appender::file_appender( const variant& args )
|
file_appender::config::config(const fc::path& p) :
|
||||||
:my( new impl( args.as<config>() ) )
|
format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
|
||||||
|
filename(p),
|
||||||
|
flush(true),
|
||||||
|
truncate(true),
|
||||||
|
rotate(false),
|
||||||
|
rotation_compression(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
file_appender::file_appender( const variant& args ) :
|
||||||
|
my( new impl( args.as<config>() ) )
|
||||||
{
|
{
|
||||||
std::string log_filename;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
log_filename = my->cfg.filename.string();
|
fc::create_directories(my->cfg.filename.parent_path());
|
||||||
|
|
||||||
fc::create_directories( fc::path( log_filename ).parent_path() );
|
if(!my->cfg.rotate)
|
||||||
|
my->out.open(my->cfg.filename.to_native_ansi_path().c_str());
|
||||||
if( !my->cfg.rotate ) my->out.open( log_filename.c_str() );
|
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
{
|
{
|
||||||
std::cerr << "error opening log file: " << log_filename << "\n";
|
std::cerr << "error opening log file: " << my->cfg.filename.string() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_appender::~file_appender(){}
|
file_appender::~file_appender(){}
|
||||||
|
|
||||||
// MS THREAD METHOD MESSAGE \t\t\t File:Line
|
// MS THREAD METHOD MESSAGE \t\t\t File:Line
|
||||||
|
|
@ -191,22 +204,24 @@ namespace fc {
|
||||||
{
|
{
|
||||||
std::stringstream line;
|
std::stringstream line;
|
||||||
//line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms ";
|
//line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms ";
|
||||||
line << std::string(m.get_context().get_timestamp()) << " ";
|
line << string(m.get_context().get_timestamp()) << " ";
|
||||||
line << std::setw( 21 ) << (m.get_context().get_thread_name().substr(0,9) + string(":") + m.get_context().get_task_name()).c_str() <<" ";
|
line << std::setw( 21 ) << (m.get_context().get_thread_name().substr(0,9) + string(":") + m.get_context().get_task_name()).c_str() << " ";
|
||||||
|
|
||||||
auto me = m.get_context().get_method();
|
string method_name = m.get_context().get_method();
|
||||||
// strip all leading scopes...
|
// strip all leading scopes...
|
||||||
if( me.size() )
|
if( method_name.size() )
|
||||||
{
|
{
|
||||||
uint32_t p = 0;
|
uint32_t p = 0;
|
||||||
for( uint32_t i = 0;i < me.size(); ++i )
|
for( uint32_t i = 0;i < method_name.size(); ++i )
|
||||||
{
|
{
|
||||||
if( me[i] == ':' ) p = i;
|
if( method_name[i] == ':' ) p = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( me[p] == ':' ) ++p;
|
if( method_name[p] == ':' )
|
||||||
|
++p;
|
||||||
line << std::setw( 20 ) << m.get_context().get_method().substr(p,20).c_str() <<" ";
|
line << std::setw( 20 ) << m.get_context().get_method().substr(p,20).c_str() <<" ";
|
||||||
}
|
}
|
||||||
|
|
||||||
line << "] ";
|
line << "] ";
|
||||||
fc::string message = fc::format_string( m.get_format(), m.get_data() );
|
fc::string message = fc::format_string( m.get_format(), m.get_data() );
|
||||||
line << message.c_str();
|
line << message.c_str();
|
||||||
|
|
@ -217,8 +232,9 @@ namespace fc {
|
||||||
|
|
||||||
{
|
{
|
||||||
fc::scoped_lock<boost::mutex> lock( my->slock );
|
fc::scoped_lock<boost::mutex> lock( my->slock );
|
||||||
my->out << line.str() << "\t\t\t" << m.get_context().get_file() <<":"<<m.get_context().get_line_number()<<"\n";
|
my->out << line.str() << "\t\t\t" << m.get_context().get_file() << ":" << m.get_context().get_line_number() << "\n";
|
||||||
if( my->cfg.flush ) my->out.flush();
|
if( my->cfg.flush )
|
||||||
|
my->out.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue