SimpleDiagnostics.cpp
Go to the documentation of this file.
1 #include "SimpleDiagnostics.hpp"
2 
3 #include "../Defs.hpp"
4 
5 #include <iostream>
6 
7 namespace iv
8 {
9 
11  InputNode( inst ),
12  ConfigStream( inst, "simple_diagnostics" ),
13  Ostream_TextDebugView( &this->cm, &iv::TextOutput ),
14  SimpleLogger( inst ),
15  cm( inst, this, "SimpleDiagnostics" ),
16  reading( false ),
17  frame_enabled( (unsigned)-1 )
18 {
19  this->cm.inherits( this->InputNode::cm, this->ConfigStream::cm, this->SimpleLogger::cm );
20 
21  //
22  if( !this->stream_exists() )
23  {
24  this->stream_write(
25  []( std::ostream & out )
26  {
27 
28 out << R"STRING([SimpleLogger]
29 
30 # examples
31 #* Performance
32 #system my_system Performance
33 #instance my_instance Performance
34 #client * Performance
35 #client Slot:* Performance
36 
37 # warnings
38 client * Warning (Critical) (SrcInfo)
39 system * Warning (Critical) (SrcInfo)
40 )STRING" << std::endl;
41 
42  }
43  );
44  }
45 
46  //
47  this->config_stream_changed();
48  this->print_welcome();
49 }
50 
52 {
53  for( auto & [ type, system ] : this->instance()->getSystemContainer()->debug_GetSystems() )
54  if( system->log_enabled( ::iv::Defs::Log::StartupDump ) )
55  this->print_system( system );
56 }
57 
58 SimpleLogger::Flags SimpleDiagnostics::LineLogFlags( LogLine const & line, bool frame_enabled, LogId id )
59 {
60  if( !line.frame || frame_enabled )
61  if( !line.log_id.has_value() || line.log_id.value() == id )
62  return line.flags;
64 }
65 
66 SimpleLogger::Flags SimpleDiagnostics::LogFlagsCombine( SimpleLogger::Flags a, SimpleLogger::Flags b )
67 {
68  return SimpleLogger::Flags( int( a ) | int( b ) );
69 }
70 
71 SimpleLogger::Flags SimpleDiagnostics::ClientLogFlags( ClientMarker const * marker, LogId id )
72 {
73  // self check
74  if( this->reading && id == ::iv::Defs::Log::Warning )
76 
77  //
78  unsigned frame_id = this->instance()->frame_id();
80 
81  // general log
82  for( SimpleLogger_GeneralLog const & log : this->generalLog )
83  {
84  flags = this->LogFlagsCombine( flags, this->LineLogFlags( log.line, this->frame_enabled == frame_id, id ) );
85  }
86 
87  // instance check
88  for( SimpleLogger_InstanceLog const & log : this->instanceLog )
89  {
90  if( !log.instance_name.has_value() || log.instance_name.value() == marker->instance()->instance_name() )
91  flags = this->LogFlagsCombine( flags, this->LineLogFlags( log.line, this->frame_enabled == frame_id, id ) );
92  }
93 
94  // client check
95  for( SimpleLogger_ClientLog const & log : this->clientLog )
96  {
97  SimpleLogger::Flags client_flags = this->LineLogFlags( log.line, this->frame_enabled == frame_id, id );
98  if( client_flags == SimpleLogger::Flags::Disabled )
99  continue;
100 
101  if( !log.client_name.has_value() )
102  {
103  flags = this->LogFlagsCombine( flags, client_flags );
104  }
105  else
106  {
107  // check marker and all its inheritance children
108  ClientMarker const * m = marker;
109  while( m )
110  {
111  if( m->name() == log.client_name.value() )
112  if( !log.client_id.has_value() || log.client_id.value() == m->marker_id() )
113  {
114  flags = this->LogFlagsCombine( flags, client_flags );
115  break;
116  }
117  m = m->inheritance_child();
118  }
119  }
120  }
121 
122  return flags;
123 }
124 
125 SimpleLogger::Flags SimpleDiagnostics::SystemLogFlags( System const * system, LogId id )
126 {
127  // self check
128  if( this->reading && id == ::iv::Defs::Log::Warning )
130 
131  //
132  unsigned frame_id = this->instance()->frame_id();
134 
135  // general log
136  for( SimpleLogger_GeneralLog const & log : this->generalLog )
137  {
138  flags = this->LogFlagsCombine( flags, this->LineLogFlags( log.line, this->frame_enabled == frame_id, id ) );
139  }
140 
141  // system log
142  for( SimpleLogger_SystemLog const & log : this->systemLog )
143  {
144  if( !log.system_name.has_value() || log.system_name == system->debug_name() )
145  flags = this->LogFlagsCombine( flags, this->LineLogFlags( log.line, this->frame_enabled == frame_id, id ) );
146  }
147 
148  return flags;
149 }
150 
151 void SimpleDiagnostics::AcceptLogLine( Lex & lex, LogLine & line )
152 {
153  // log id
154  if( lex.IsNext( Lex::Name ) )
155  line.log_id = LogId( lex.AcceptName().c_str(), &this->cm );
156  else
157  lex.AcceptOperator( "*" );
158 
159  // modifiers
160  while( lex.IsNextOperator( "(" ) )
161  {
162  lex.AcceptOperator( "(" );
163  std::string flag_str = lex.AcceptName();
164  lex.AcceptOperator( ")" );
165 
166  if( flag_str == "Frame" )
167  {
168  line.frame = true;
169  }
170  else
171  {
172  auto flag = iv::StringIO_Read< SimpleLogger::Flags >( flag_str.c_str(), &this->cm );
173  if( flag != SimpleLogger::Flags::Disabled )
174  line.flags = SimpleLogger::Flags( int( line.flags ) | int( flag ) );
175  else
176  lex.LogicFail( "Invalid flag keyword." );
177  }
178  }
179 }
180 
182 {
183  this->reading = true;
184 
185  this->instanceLog.clear();
186  this->clientLog.clear();
187  this->systemLog.clear();
188 
189  this->stream_read(
190  [&]( std::istream & in )
191  {
192  Lex lex( this->instance() );
193  lex.DisableNewlineSkipping();
194  lex.DefineOperator( "[" );
195  lex.DefineOperator( "]" );
196  lex.DefineKeyword( "log" );
197  lex.DefineKeyword( "unpack" );
198  lex.DefineOperator( "*" );
199  lex.DefineOperator( ":" );
200  lex.DefineOperator( "(" );
201  lex.DefineOperator( ")" );
202 
203  lex.Init( in );
204 
205  Lex_LogTrace _mod( lex );
206 
207  constexpr int Mode_None = 0;
208  constexpr int Mode_SimpleLogger = 1;
209 
210  int mode = Mode_None;
211 
212  while( !lex.IsNext( Lex::Eof ) )
213  {
214  if( lex.IsNext( Lex::Token::Newline ) )
215  {
216  lex.Accept( Lex::Token::Newline );
217  }
218  else if( lex.IsNextOperator( "[" ) )
219  {
220  lex.AcceptOperator( "[" );
221  std::string name = lex.AcceptName();
222  lex.AcceptOperator( "]" );
223 
224  if( lex.Failed() )
225  mode = Mode_None;
226  else if( name == "SimpleLogger" )
227  mode = Mode_SimpleLogger;
228  else
229  lex.LogicFail( "Unknown section identifier." );
230 
231  // newline
232  lex.Recover( Lex::Newline );
233  lex.Accept( Lex::Token::Newline );
234  }
235  else if( mode == Mode_SimpleLogger )
236  {
237  if( lex.IsNextOperator( "*" ) )
238  {
239  lex.AcceptOperator( "*" );
240 
241  SimpleLogger_GeneralLog log;
242 
243  // log id and modifiers
244  this->AcceptLogLine( lex, log.line );
245 
246  //
247  if( !lex.Failed() )
248  this->generalLog.push_back( log );
249 
250  // newline
251  lex.Recover( Lex::Newline );
252  lex.Accept( Lex::Token::Newline );
253  }
254  else
255  {
256  std::string name = lex.AcceptName();
257  if( name == "instance" )
258  {
259  SimpleLogger_InstanceLog log;
260 
261  // instance name
262  if( lex.IsNextOperator( "*" ) )
263  lex.AcceptOperator( "*" );
264  else
265  log.instance_name = lex.AcceptName();
266 
267  // log id and modifiers
268  this->AcceptLogLine( lex, log.line );
269 
270  //
271  if( !lex.Failed() )
272  this->instanceLog.push_back( log );
273 
274  // newline
275  lex.Recover( Lex::Newline );
276  lex.Accept( Lex::Token::Newline );
277  }
278  else if( name == "client" )
279  {
280  SimpleLogger_ClientLog log;
281 
282  // client name
283  if( lex.IsNextOperator( "*" ) )
284  lex.AcceptOperator( "*" );
285  else
286  log.client_name = lex.AcceptName();
287 
288  if( log.client_name.has_value() && lex.IsNextOperator( ":" ) )
289  {
290  // separator
291  lex.AcceptOperator( ":" );
292 
293  // client id
294  if( lex.IsNextKeyword( "*" ) )
295  lex.AcceptKeyword( "*" );
296  else
297  log.client_id = lex.AcceptInteger();
298  }
299 
300  // log id and modifiers
301  this->AcceptLogLine( lex, log.line );
302 
303  //
304  if( !lex.Failed() )
305  this->clientLog.push_back( log );
306 
307  // newline
308  lex.Recover( Lex::Newline );
309  lex.Accept( Lex::Token::Newline );
310  }
311  else if( name == "system" )
312  {
313  SimpleLogger_SystemLog log;
314 
315  // system name
316  if( lex.IsNextOperator( "*" ) )
317  lex.AcceptOperator( "*" );
318  else
319  log.system_name = lex.AcceptName();
320 
321  // log id and modifiers
322  this->AcceptLogLine( lex, log.line );
323 
324  //
325  if( !lex.Failed() )
326  this->systemLog.push_back( log );
327 
328  // newline
329  lex.Recover( Lex::Newline );
330  lex.Accept( Lex::Token::Newline );
331  }
332  else
333  {
334  lex.AcceptFail();
335  }
336  }
337  }
338  else
339  {
340  lex.AcceptFail();
341  }
342  }
343  }
344  );
345 
346  this->reading = false;
347 }
348 
350 {
351  if( key.first != Input::Key::Character )
352  {
353  this->cm.log( SRC_INFO, Defs::Log::Input, "Refuse input, not a Character input." );
354  return true;
355  }
356 
357  InputQuery iq( this->instance() );
358  unsigned character = iq.input_character();
359 
360  if( this->action( character ) )
361  {
362  this->cm.log( SRC_INFO, Defs::Log::Input, "Accept input, but let it fall through." );
363  }
364  else
365  {
366  this->cm.log( SRC_INFO, Defs::Log::Input, "Refuse input, no action is attached to this character." );
367  }
368 
369  return true;
370 }
371 
372 void SimpleDiagnostics::print_system( System * sys )
373 {
374  if( sys )
375  {
376  this->out() << sys->debug_name() << ":" << std::endl;
377  this->prefix_push( " " );
378  sys->status( this );
379  this->out() << std::endl;
380  this->prefix_pop();
381  }
382 }
383 
384 void SimpleDiagnostics::print_welcome()
385 {
386  this->out() << "========= SimpleDiagnostics =========" << std::endl;
387  this->out() << " p - Print all systems." << std::endl;
388  this->out() << " e - Print ElementSystem." << std::endl;
389  this->out() << " i - Print InstanceSystem." << std::endl;
390  this->out() << " n - Print AnimSystem." << std::endl;
391  this->out() << " f - Frame log." << std::endl;
392  this->out() << "" << std::endl;
393 
394  this->out() << " LogId:" << std::endl;
395  for( size_t i = 1; i < LogId::ids_count(); i++ )
396  {
397  LogId id( i );
398  this->out() << " " << id.runtime_value() << " - " << id.persistent_value() << std::endl;
399  }
400  this->out() << "" << std::endl;
401 }
402 
403 bool SimpleDiagnostics::action( unsigned key )
404 {
405  if( key == 'p' )
406  {
407  this->print_systems();
408  }
409  else if( key == 'e' )
410  {
411  auto es = this->instance()->getSystem< ElementSystem >();
412  if( es )
413  {
414  this->print_system( es );
415  }
416  }
417  else if( key == 'i' )
418  {
419  this->print_system( this->instance()->getSystem< InstanceSystem >() );
420  }
421  else if( key == 'n' )
422  {
423  this->print_system( this->instance()->getSystem< AnimSystem >() );
424  }
425  else if( key == 'b' )
426  {
427  this->print_system( this->instance()->getSystem< InputBindingSystem >() );
428  }
429  else if( key == 'f' )
430  {
431  this->frame_enabled = this->instance()->frame_id() + 1;
432  }
433  else
434  {
435  return true;
436  }
437 
438  return false;
439 }
440 
442 {
443  this->instance()->getSystemContainer()->debug_print( this );
444 }
445 
446 }