Factored console_appender into its own header/cpp

Added file_appender
Updated tests
This commit is contained in:
Daniel Larimer 2013-02-05 00:06:16 -05:00
parent 71ea16cf8b
commit b527bbbab6
10 changed files with 215 additions and 105 deletions

View file

@ -50,6 +50,8 @@ include_directories( include )
set( sources
src/logger.cpp
src/console_appender.cpp
src/file_appender.cpp
src/appender.cpp
src/logger_config.cpp
src/ssh.cpp

View file

@ -0,0 +1,56 @@
#pragma once
#include <fc/appender.hpp>
#include <fc/logger.hpp>
namespace fc {
class console_appender : public appender {
public:
struct color {
enum type {
red,
green,
brown,
blue,
magenta,
cyan,
white,
console_default,
};
};
struct stream { enum type { std_out, std_error }; };
struct level_color {
level_color( log_level::type l=log_level::all,
color::type c=color::console_default )
:level(l),color(c){}
log_level::type level;
console_appender::color::type color;
};
struct config {
config()
:format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
stream(console_appender::stream::std_error),flush(true){}
fc::string format;
console_appender::stream::type stream;
fc::vector<level_color> level_colors;
bool flush;
};
console_appender( const value& args );
const char* get_color( log_level::type l )const;
virtual void log( const log_message& m );
private:
config cfg;
color::type lc[log_level::off+1];
};
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT_ENUM( fc::console_appender::stream::type, (std_out)(std_error) )
FC_REFLECT_ENUM( fc::console_appender::color::type, (red)(green)(brown)(blue)(magenta)(cyan)(white)(console_default) )
FC_REFLECT( fc::console_appender::level_color, (level)(color) )
FC_REFLECT( fc::console_appender::config, (format)(stream)(level_colors)(flush) )

View file

@ -0,0 +1,29 @@
#pragma once
#include <fc/appender.hpp>
#include <fc/logger.hpp>
#include <fc/filesystem.hpp>
namespace fc {
class file_appender : public appender {
public:
struct config {
config( const fc::path& p = "log.txt" );
fc::string format;
fc::path filename;
bool flush;
bool truncate;
};
file_appender( const value& args );
~file_appender();
virtual void log( const log_message& m );
private:
class impl;
fc::shared_ptr<impl> my;
};
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT( fc::file_appender::config, (format)(filename)(flush)(truncate) )

View file

@ -22,6 +22,7 @@ namespace fc {
ostring context;
ostring thread;
ostring fiber;
ostring host;
string file;
int line;
string method;
@ -102,7 +103,7 @@ namespace fc {
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT( fc::log_message, (when)(level)(context)(thread)(method)(file)(line)(format)(args)(meta) )
FC_REFLECT( fc::log_message, (when)(level)(context)(thread)(fiber)(host)(method)(file)(line)(format)(args)(meta) )
FC_REFLECT_ENUM( fc::log_level::type, (all)(trace)(debug)(info)(warn)(error)(fatal)(off) )
#define fc_scope_log( LOGGER, FORMAT, ... ) \

View file

@ -22,6 +22,8 @@ namespace fc {
/// if any appenders are sepecified, then parent's appenders are not set.
bool additivity;
fc::vector<string> appenders;
logger_config& add_appender( const string& s );
};
struct logging_config {

View file

@ -9,11 +9,9 @@
#include <fc/console_defines.h>
#include <fc/log.hpp>
#include <fc/value_cast.hpp>
#include <boost/thread/mutex.hpp>
#include <fc/console_appender.hpp>
#include <fc/file_appender.hpp>
#ifndef WIN32
#include <unistd.h>
#endif
namespace fc {
@ -46,101 +44,7 @@ namespace fc {
get_appender_map()[name] = ap;
return ap;
}
class console_appender : public appender{
public:
struct color {
enum type {
red,
green,
brown,
blue,
magenta,
cyan,
white,
console_default,
};
};
struct stream { enum type { std_out, std_error }; };
struct level_color {
level_color( log_level::type l=log_level::all,
color::type c=color::console_default )
:level(l),color(c){}
log_level::type level;
console_appender::color::type color;
};
struct config {
config()
:format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
stream(console_appender::stream::std_error),flush(true){}
fc::string format;
console_appender::stream::type stream;
fc::vector<level_color> level_colors;
bool flush;
};
config cfg;
color::type lc[log_level::off+1];
console_appender( const value& args );
const char* get_color(color::type t ) {
switch( t ) {
case color::red: return CONSOLE_RED;
case color::green: return CONSOLE_GREEN;
case color::brown: return CONSOLE_BROWN;
case color::blue: return CONSOLE_BLUE;
case color::magenta: return CONSOLE_MAGENTA;
case color::cyan: return CONSOLE_CYAN;
case color::white: return CONSOLE_WHITE;
case color::console_default:
default:
return CONSOLE_DEFAULT;
}
}
const char* get_color( log_level::type l ) {
return get_color( lc[l] );
}
virtual void log( const log_message& m ) {
fc::string message = fc::substitute( m.format, m.args );
fc::value lmsg(m);
FILE* out = stream::std_error ? stderr : stdout;
fc::string fmt_str = fc::substitute( cfg.format, value(m).set( "message", message) );
fc::unique_lock<boost::mutex> lock(log_mutex());
#ifndef WIN32
if(isatty(fileno(out))) fprintf( out, "\r%s", get_color( m.level ) );
#endif
fprintf( out, "%s", fmt_str.c_str() );
#ifndef WIN32
if(isatty(fileno(out))) fprintf( out, "\r%s", CONSOLE_DEFAULT );
#endif
fprintf( out, "\n" );
if( cfg.flush ) fflush( out );
}
};
} // namespace fc
FC_REFLECT_ENUM( fc::console_appender::stream::type, (std_out)(std_error) )
FC_REFLECT_ENUM( fc::console_appender::color::type, (red)(green)(brown)(blue)(magenta)(cyan)(white)(console_default) )
FC_REFLECT( fc::console_appender::level_color, (level)(color) )
FC_REFLECT( fc::console_appender::config, (format)(stream)(level_colors)(flush) )
namespace fc {
console_appender::console_appender( const value& args ) {
cfg = fc::value_cast<config>(args);
for( int i = 0; i < log_level::off+1; ++i )
lc[i] = color::console_default;
for( auto itr = cfg.level_colors.begin(); itr != cfg.level_colors.end(); ++itr )
lc[itr->level] = itr->color;
}
static bool reg_console_appender = appender::register_appender<console_appender>( "console" );
static bool reg_file_appender = appender::register_appender<file_appender>( "file" );
} // namespace fc

56
src/console_appender.cpp Normal file
View file

@ -0,0 +1,56 @@
#include <fc/console_appender.hpp>
#include <boost/thread/mutex.hpp>
#include <fc/unique_lock.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#ifndef WIN32
#include <unistd.h>
#endif
namespace fc {
console_appender::console_appender( const value& args ) {
cfg = fc::value_cast<config>(args);
for( int i = 0; i < log_level::off+1; ++i )
lc[i] = color::console_default;
for( auto itr = cfg.level_colors.begin(); itr != cfg.level_colors.end(); ++itr )
lc[itr->level] = itr->color;
}
const char* get_console_color(console_appender::color::type t ) {
switch( t ) {
case console_appender::color::red: return CONSOLE_RED;
case console_appender::color::green: return CONSOLE_GREEN;
case console_appender::color::brown: return CONSOLE_BROWN;
case console_appender::color::blue: return CONSOLE_BLUE;
case console_appender::color::magenta: return CONSOLE_MAGENTA;
case console_appender::color::cyan: return CONSOLE_CYAN;
case console_appender::color::white: return CONSOLE_WHITE;
case console_appender::color::console_default:
default:
return CONSOLE_DEFAULT;
}
}
const char* console_appender::get_color( log_level::type l )const {
return get_console_color( lc[l] );
}
void console_appender::log( const log_message& m ) {
fc::string message = fc::substitute( m.format, m.args );
fc::value lmsg(m);
FILE* out = stream::std_error ? stderr : stdout;
fc::string fmt_str = fc::substitute( cfg.format, value(m).set( "message", message) );
fc::unique_lock<boost::mutex> lock(log_mutex());
#ifndef WIN32
if(isatty(fileno(out))) fprintf( out, "\r%s", get_color( m.level ) );
#endif
fprintf( out, "%s", fmt_str.c_str() );
#ifndef WIN32
if(isatty(fileno(out))) fprintf( out, "\r%s", CONSOLE_DEFAULT );
#endif
fprintf( out, "\n" );
if( cfg.flush ) fflush( out );
}
}

44
src/file_appender.cpp Normal file
View file

@ -0,0 +1,44 @@
#include <fc/file_appender.hpp>
#include <boost/thread/mutex.hpp>
#include <fc/scoped_lock.hpp>
#include <boost/thread/mutex.hpp>
#include <fc/value.hpp>
#include <fc/value_cast.hpp>
#include <fc/fstream.hpp>
namespace fc {
class file_appender::impl : public fc::retainable {
public:
config cfg;
ofstream out;
boost::mutex slock;
};
file_appender::config::config( const fc::path& p )
:format( "${when} ${thread} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
filename(p),flush(true),truncate(true){}
file_appender::file_appender( const value& args )
:my( new impl() )
{
try {
my->cfg = fc::value_cast<config>(args);
my->out.open( my->cfg.filename.string().c_str() );
} catch ( ... ) {
elog( "%s", fc::except_str().c_str() );
}
}
file_appender::~file_appender(){}
void file_appender::log( const log_message& m )
{
fc::string message = fc::substitute( m.format, m.args );
fc::value lmsg(m);
fc::string fmt_str = fc::substitute( my->cfg.format, value(m).set( "message", message) );
{
fc::scoped_lock<boost::mutex> lock(my->slock);
my->out << fmt_str << "\n";
}
if( my->cfg.flush ) my->out.flush();
}
}

View file

@ -8,6 +8,7 @@
namespace fc {
std::unordered_map<std::string,logger>& get_logger_map();
std::unordered_map<std::string,appender::ptr>& get_appender_map();
logger_config& logger_config::add_appender( const string& s ) { appenders.push_back(s); return *this; }
void configure_logging( const fc::path& lc )
{
@ -26,13 +27,15 @@ namespace fc {
for( size_t i = 0; i < cfg.loggers.size(); ++i ) {
auto lgr = logger::get( cfg.loggers[i].name );
// TODO: configure logger here...
// TODO: finish configure logger here...
if( cfg.loggers[i].parent ) {
lgr.set_parent( logger::get( *cfg.loggers[i].parent ) );
}
lgr.set_name(cfg.loggers[i].name);
lgr.set_log_level( *cfg.loggers[i].level );
for( auto a = cfg.loggers[i].appenders.begin();
a != cfg.loggers[i].appenders.end(); ++a ){
for( auto a = cfg.loggers[i].appenders.begin(); a != cfg.loggers[i].appenders.end(); ++a ){
auto ap = appender::get( *a );
if( ap ) { lgr.add_appender(ap); }
}

View file

@ -1,12 +1,25 @@
#include <fc/logger_config.hpp>
#include <fc/file_appender.hpp>
#include <fc/value_cast.hpp>
int main( int argc, char** argv ) {
auto lgr = fc::logger::get();
fc::configure_logging( fc::logging_config::default_config() );
auto dconfig = fc::logging_config::default_config();
dconfig.appenders.push_back( fc::appender_config("logfile", "file", fc::value(fc::file_appender::config("test.log")) ) );
dconfig.loggers.push_back( fc::logger_config("main").add_appender("stderr").add_appender("logfile") );
fc::configure_logging( dconfig );
fc_dlog( lgr, "Hello Debug" );
fc_ilog( lgr, "Hello Info" );
fc_wlog( lgr, "Hello Warn" );
fc_elog( lgr, "Hello Error" );
fc_flog( lgr, "Hello Fatal" );
auto main_lgr = fc::logger::get( "main" );
fc_dlog( main_lgr, "Hello Debug" );
fc_ilog( main_lgr, "Hello Info" );
fc_wlog( main_lgr, "Hello Warn" );
fc_elog( main_lgr, "Hello Error" );
fc_flog( main_lgr, "Hello Fatal" );
return 0;
}