BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
console_appender.cpp
Go to the documentation of this file.
2 #include <fc/log/log_message.hpp>
4 #include <fc/variant.hpp>
5 #include <fc/reflect/variant.hpp>
6 #ifndef WIN32
7 #include <unistd.h>
8 #endif
9 #include <boost/thread/mutex.hpp>
10 #define COLOR_CONSOLE 1
11 #include "console_defines.h"
12 #include <fc/io/stdio.hpp>
14 #include <iomanip>
15 #include <sstream>
16 #include <mutex>
17 
18 
19 namespace fc {
20 
22  public:
25 #ifdef WIN32
26  HANDLE console_handle;
27 #endif
28  };
29 
31  :my(new impl)
32  {
34  }
35 
37  :my(new impl)
38  {
39  configure( cfg );
40  }
42  :my(new impl){}
43 
44 
45  void console_appender::configure( const config& console_appender_config )
46  { try {
47 #ifdef WIN32
48  my->console_handle = INVALID_HANDLE_VALUE;
49 #endif
50  my->cfg = console_appender_config;
51 #ifdef WIN32
52  if (my->cfg.stream = stream::std_error)
53  my->console_handle = GetStdHandle(STD_ERROR_HANDLE);
54  else if (my->cfg.stream = stream::std_out)
55  my->console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
56 #endif
57 
58  for( int i = 0; i < log_level::off+1; ++i )
59  my->lc[i] = color::console_default;
60  for( auto itr = my->cfg.level_colors.begin(); itr != my->cfg.level_colors.end(); ++itr )
61  my->lc[itr->level] = itr->color;
62  } FC_CAPTURE_AND_RETHROW( (console_appender_config) ) }
63 
65 
66  #ifdef WIN32
67  static WORD
68  #else
69  static const char*
70  #endif
71  get_console_color(console_appender::color::type t ) {
72  switch( t ) {
73  case console_appender::color::red: return CONSOLE_RED;
74  case console_appender::color::green: return CONSOLE_GREEN;
75  case console_appender::color::brown: return CONSOLE_BROWN;
76  case console_appender::color::blue: return CONSOLE_BLUE;
77  case console_appender::color::magenta: return CONSOLE_MAGENTA;
78  case console_appender::color::cyan: return CONSOLE_CYAN;
79  case console_appender::color::white: return CONSOLE_WHITE;
81  default:
82  return CONSOLE_DEFAULT;
83  }
84  }
85 
86  boost::mutex& log_mutex() {
87  static boost::mutex m; return m;
88  }
89 
91 
92  FILE* out = stream::std_error ? stderr : stdout;
93 
94  std::stringstream file_line;
95  file_line << m.get_context().get_file() <<":"<<m.get_context().get_line_number() <<" ";
96 
98  std::stringstream line;
99  line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms ";
100  line << std::setw( 10 ) << std::left << m.get_context().get_thread_name().substr(0,9).c_str() <<" "<<std::setw(30)<< std::left <<file_line.str();
101 
102  auto me = m.get_context().get_method();
103  // strip all leading scopes...
104  if( me.size() )
105  {
106  uint32_t p = 0;
107  for( uint32_t i = 0;i < me.size(); ++i )
108  {
109  if( me[i] == ':' ) p = i;
110  }
111 
112  if( me[p] == ':' ) ++p;
113  line << std::setw( 20 ) << std::left << m.get_context().get_method().substr(p,20).c_str() <<" ";
114  }
115  line << "] ";
116  std::string message = fc::format_string( m.get_format(), m.get_data(), my->cfg.max_object_depth );
117  line << message;
118 
120 
121  print( line.str(), my->lc[m.get_context().get_log_level()] );
122 
123  fprintf( out, "\n" );
124 
125  if( my->cfg.flush ) fflush( out );
126  }
127 
128  void console_appender::print( const std::string& text, color::type text_color )
129  {
130  FILE* out = stream::std_error ? stderr : stdout;
131 
132  #ifdef WIN32
133  if (my->console_handle != INVALID_HANDLE_VALUE)
134  SetConsoleTextAttribute(my->console_handle, get_console_color(text_color));
135  #else
136  if(isatty(fileno(out))) fprintf( out, "\r%s", get_console_color( text_color ) );
137  #endif
138 
139  if( text.size() )
140  fprintf( out, "%s", text.c_str() );
141 
142  #ifdef WIN32
143  if (my->console_handle != INVALID_HANDLE_VALUE)
144  SetConsoleTextAttribute(my->console_handle, CONSOLE_DEFAULT);
145  #else
146  if(isatty(fileno(out))) fprintf( out, "\r%s", CONSOLE_DEFAULT );
147  #endif
148 
149  if( my->cfg.flush ) fflush( out );
150  }
151 
152 }
std::string get_file() const
std::string format_string(const std::string &, const variant_object &, uint32_t max_object_depth=200)
T as(uint32_t max_depth) const
Definition: variant.hpp:336
std::string get_thread_name() const
uint64_t get_line_number() const
Defines types and helper macros necessary for generating log messages.
void configure(const config &cfg)
virtual void log(const log_message &m)
color::type lc[log_level::off+1]
#define FC_MAX_LOG_OBJECT_DEPTH
Definition: config.hpp:8
log_level get_log_level() const
std::string get_format() const
int64_t count() const
Definition: time.hpp:28
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
void print(const std::string &text_to_print, color::type text_color=color::console_default)
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
log_context get_context() const
Defines exception&#39;s used by fc.
time_point get_timestamp() const
const microseconds & time_since_epoch() const
Definition: time.hpp:54
boost::mutex & log_mutex()
aggregates a message along with the context and associated meta-information.
Definition: api.hpp:15
variant_object get_data() const
std::string get_method() const