Midge  v3.9.2
Data Processing Framework
message_logger.cc
Go to the documentation of this file.
1 #include <iomanip>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <execinfo.h>
5 #include <iostream>
6 #include "message_logger.hh"
7 
8 using std::set;
9 using std::vector;
10 using std::map;
11 using std::ostream;
12 using std::pair;
13 using std::string;
14 using std::stringstream;
15 using std::setprecision;
16 using std::fixed;
17 
18 namespace midge
19 {
20 
21  std::mutex message::f_outer;
22  std::mutex message::f_inner;
23  set< std::thread::id > message::f_threads = set< std::thread::id >();
24 
25  message::message( const string& aKey, const string& aDescription, const string& aPrefix, const string& aSuffix ) :
26  f_key( aKey ),
27  f_system_description( aDescription ),
28  f_system_prefix( aPrefix ),
29  f_system_suffix( aSuffix ),
30 
31  f_error_color_prefix( "\33[31;1m" ),
32  f_error_color_suffix( "\33[0m" ),
33  f_error_description( "error" ),
34 
35  f_warning_color_prefix( "\33[33;1m" ),
36  f_warning_color_suffix( "\33[0m" ),
37  f_warning_description( "warning" ),
38 
39  f_normal_color_prefix( "\33[32;1m" ),
40  f_normal_color_suffix( "\33[0m" ),
41  f_normal_description( "normal" ),
42 
43  f_debug_color_prefix( "\33[36;1m" ),
44  f_debug_color_suffix( "\33[0m" ),
45  f_debug_description( "debug" ),
46 
47  f_default_color_prefix( "\33[37;1m" ),
48  f_default_color_suffix( "\33[0m" ),
49  f_default_description( "unknown" ),
50 
51  f_severity( s_normal ),
52 
53  f_color_prefix( &message::f_normal_color_prefix ),
54  f_description( &message::f_normal_description ),
55  f_color_suffix( &message::f_normal_color_suffix ),
56 
57  f_message_line(),
58  f_message_lines(),
59 
60  f_terminal_severity( messages::get_instance()->get_terminal_severity() ),
61  f_terminal_stream( messages::get_instance()->get_terminal_stream() ),
62  f_log_severity( messages::get_instance()->get_log_severity() ),
63  f_log_stream( messages::get_instance()->get_log_stream() )
64  {
65  f_message_line.setf( messages::get_instance()->get_format(), std::ios::floatfield );
66  f_message_line.precision( messages::get_instance()->GetPrecision() );
67  messages::get_instance()->add( this );
68  }
70  {
71  messages::get_instance()->remove( this );
72  }
73 
74  const string& message::get_key() const
75  {
76  return f_key;
77  }
78  void message::set_key( const string& aKey )
79  {
80  f_key = aKey;
81  return;
82  }
83 
84  void message::set_severity( const message_severity& aSeverity )
85  {
86  f_severity = aSeverity;
87 
88  switch( f_severity )
89  {
90  case s_error :
94  break;
95 
96  case s_warning :
100  break;
101 
102  case s_normal :
106  break;
107 
108  case s_debug :
112  break;
113 
114  default :
118  break;
119  }
120 
121  return;
122  }
124  {
125  if( (f_severity <= f_terminal_severity) && (f_terminal_stream != NULL) && (f_terminal_stream->good() == true) )
126  {
127  for( vector< string >::iterator t_it = f_message_lines.begin(); t_it != f_message_lines.end(); t_it++ )
128  {
129  (*f_terminal_stream) << this->*f_color_prefix << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] " << (*t_it) << f_system_suffix << this->*f_color_suffix << "\n";
130  }
131  (*f_terminal_stream).flush();
132  }
133 
134  if( (f_severity <= f_log_severity) && (f_log_stream != NULL) && (f_log_stream->good() == true) )
135  {
136  for( vector< string >::iterator t_it = f_message_lines.begin(); t_it != f_message_lines.end(); t_it++ )
137  {
138  (*f_log_stream) << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] " << *t_it << f_system_suffix << "\n";
139  }
140  (*f_log_stream).flush();
141  }
142 
143  while( !f_message_lines.empty() )
144  {
145  f_message_lines.pop_back();
146  }
147 
148  if( f_severity == s_error )
149  {
150  shutdown();
151  }
152 
153  return;
154  }
155 
157  {
158  const size_t t_max_frames = 512;
159  void* t_frame_array[ t_max_frames ];
160  const size_t t_frame_count = backtrace( t_frame_array, t_max_frames );
161  char** t_frame_symbols = backtrace_symbols( t_frame_array, t_frame_count );
162 
163  if( (f_severity <= f_terminal_severity) && (f_terminal_stream != NULL) && (f_terminal_stream->good() == true) )
164  {
165  (*f_terminal_stream) << this->*f_color_prefix << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] shutting down..." << f_system_suffix << this->*f_color_suffix << '\n';
166  (*f_terminal_stream) << this->*f_color_prefix << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] stack trace:" << f_system_suffix << this->*f_color_suffix << '\n';
167  for( size_t Index = 0; Index < t_frame_count; Index++ )
168  {
169  (*f_terminal_stream) << this->*f_color_prefix << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] " << t_frame_symbols[ Index ] << f_system_suffix << this->*f_color_suffix << '\n';
170  }
171  (*f_terminal_stream).flush();
172  }
173 
174  if( (f_severity <= f_log_severity) && (f_log_stream != NULL) && (f_log_stream->good() == true) )
175  {
176  (*f_log_stream) << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] shutting down..." << f_system_suffix << '\n';
177  (*f_log_stream) << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] stack trace:" << f_system_suffix << '\n';
178  for( size_t t_index = 0; t_index < t_frame_count; t_index++ )
179  {
180  (*f_log_stream) << f_system_prefix << "[" << f_system_description << " " << this->*f_description << " message] " << t_frame_symbols[ t_index ] << f_system_suffix << '\n';
181  }
182  (*f_log_stream).flush();
183  }
184 
185  free( t_frame_symbols );
186  exit( -1 );
187 
188  return;
189  }
190 
191  void message::set_format( const message_format& aFormat )
192  {
193  f_message_line.setf( aFormat, std::ios::floatfield );
194  return;
195  }
196  void message::set_precision( const message_precision& aPrecision )
197  {
198  f_message_line.precision( aPrecision );
199  return;
200  }
202  {
203  f_terminal_severity = aVerbosity;
204  return;
205  }
206  void message::set_terminal_stream( ostream* aTerminalStream )
207  {
208  f_terminal_stream = aTerminalStream;
209  return;
210  }
211  void message::set_log_severity( const message_severity& aVerbosity )
212  {
213  f_log_severity = aVerbosity;
214  return;
215  }
216  void message::set_log_stream( ostream* aLogStream )
217  {
218  f_log_stream = aLogStream;
219  return;
220  }
221 
223  {
224  bool_t t_flag;
225  f_outer.lock();
226  if( f_threads.find( std::this_thread::get_id() ) == f_threads.end() )
227  {
228  f_threads.insert( std::this_thread::get_id() );
229  t_flag = true;
230  }
231  else
232  {
233  t_flag = false;
234  }
235  f_outer.unlock();
236 
237  if( t_flag == true )
238  {
239  f_inner.lock();
240  }
241 
242  return;
243  }
245  {
246  bool_t t_flag;
247  f_outer.lock();
248  if( f_threads.find( std::this_thread::get_id() ) == f_threads.end() )
249  {
250  t_flag = false;
251  }
252  else
253  {
254  f_threads.erase( std::this_thread::get_id() );
255  t_flag = true;
256  }
257  f_outer.unlock();
258 
259  if( t_flag == true )
260  {
261  f_inner.unlock();
262  }
263 
264  return;
265  }
266 
267 }
268 
269 namespace midge
270 {
271 
273  f_map(),
274  f_format( std::cout.flags() ),
275  f_precision( std::cout.precision() ),
276 #ifdef MIDGE_ENABLE_DEBUG_MESSAGES
278 #else
280 #endif
281  f_terminal_stream( &std::cout ),
282 #ifdef MIDGE_ENABLE_DEBUG_MESSAGES
284 #else
286 #endif
287  f_log_stream( NULL )
288  {
289  }
291  {
292  }
293 
294  void messages::add( message* aMessage )
295  {
296  it_t tIter = f_map.find( aMessage->get_key() );
297  if( tIter == f_map.end() )
298  {
299  f_map.insert( entry_t( aMessage->get_key(), aMessage ) );
300  }
301  return;
302  }
303  message* messages::get( const string& aKey )
304  {
305  it_t tIter = f_map.find( aKey );
306  if( tIter != f_map.end() )
307  {
308  return tIter->second;
309  }
310  return NULL;
311  }
312  void messages::remove( message* aMessage )
313  {
314  it_t tIter = f_map.find( aMessage->get_key() );
315  if( tIter != f_map.end() )
316  {
317  f_map.erase( tIter );
318  }
319  return;
320  }
321 
322  void messages::set_format( const message_format& aFormat )
323  {
324  f_format = aFormat;
325  it_t tIter;
326  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
327  {
328  tIter->second->set_format( f_format );
329  }
330  return;
331  }
333  {
334  return f_format;
335  }
336 
337  void messages::set_precision( const message_precision& aPrecision )
338  {
339  f_precision = aPrecision;
340  it_t tIter;
341  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
342  {
343  tIter->second->set_precision( f_precision );
344  }
345  return;
346  }
348  {
349  return f_precision;
350  }
351 
353  {
354  f_terminal_severity = aVerbosity;
355  it_t tIter;
356  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
357  {
358  tIter->second->set_terminal_severity( f_terminal_severity );
359  }
360  return;
361  }
363  {
364  return f_terminal_severity;
365  }
366 
367  void messages::set_terminal_stream( ostream* aTerminalStream )
368  {
369  f_terminal_stream = aTerminalStream;
370  it_t tIter;
371  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
372  {
373  tIter->second->set_terminal_stream( f_terminal_stream );
374  }
375  return;
376  }
378  {
379  return f_terminal_stream;
380  }
381 
383  {
384  f_log_severity = aVerbosity;
385  it_t tIter;
386  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
387  {
388  tIter->second->set_log_severity( f_log_severity );
389  }
390  return;
391  }
393  {
394  return f_log_severity;
395  }
396 
397  void messages::set_log_stream( ostream* aLogStream )
398  {
399  f_log_stream = aLogStream;
400  it_t tIter;
401  for( tIter = f_map.begin(); tIter != f_map.end(); tIter++ )
402  {
403  tIter->second->set_log_stream( f_log_stream );
404  }
405  return;
406  }
408  {
409  return f_log_stream;
410  }
411 
412 }
413 
414 message_define( msg, midge, midge )
void set_terminal_stream(std::ostream *aTerminalStream)
std::string f_key
void set_terminal_severity(const message_severity &aVerbosity)
message_severity f_log_severity
const message_severity & get_log_severity()
void set_precision(const message_precision &aPrecision)
void set_precision(const message_precision &aPrecision)
Definition: _buffer.hh:11
std::string message::* f_color_suffix
std::string f_system_suffix
std::string f_system_description
std::ostream * f_terminal_stream
void add(message *aMessage)
virtual ~message()
std::vector< std::string > f_message_lines
std::string f_error_description
void set_format(const message_format &aFormat)
void set_severity(const message_severity &aSeverity)
STL namespace.
static std::mutex f_inner
static const message_severity s_debug
std::string f_normal_color_suffix
map_t::iterator it_t
message_severity f_terminal_severity
std::streamsize message_precision
std::string f_warning_color_suffix
static const message_severity s_error
void set_terminal_severity(const message_severity &aVerbosity)
std::string f_warning_color_prefix
map_t::value_type entry_t
std::string f_debug_color_prefix
void set_format(const message_format &aFormat)
std::stringstream f_message_line
message_severity f_log_severity
message * get(const std::string &aKey)
std::ostream * f_log_stream
void set_log_severity(const message_severity &aVerbosity)
std::string message::* f_description
static void release()
void set_terminal_stream(std::ostream *aTerminalStream)
std::ios_base::fmtflags message_format
void set_log_stream(std::ostream *aLogStream)
message_format f_format
bool bool_t
Definition: types.hh:12
static const message_severity s_normal
static const message_severity s_warning
std::string f_system_prefix
std::string f_normal_color_prefix
std::string f_normal_description
static std::set< std::thread::id > f_threads
message_define(testmsg, test, test) using namespace midge
std::string message::* f_color_prefix
message_severity f_severity
std::string f_error_color_prefix
std::ostream * get_log_stream()
message_severity f_terminal_severity
void set_log_severity(const message_severity &aVerbosity)
int message_severity
const message_precision & GetPrecision()
void remove(message *aMessage)
std::string f_error_color_suffix
std::ostream * f_terminal_stream
const std::string & get_key() const
std::ostream * f_log_stream
std::string f_debug_description
const message_format & get_format()
message_precision f_precision
std::string f_warning_description
std::ostream * get_terminal_stream()
static std::mutex f_outer
static void acquire()
void set_log_stream(std::ostream *aLogStream)
const message_severity & get_terminal_severity()
std::string f_debug_color_suffix
void set_key(const std::string &aKey)