97
97
#define LOG_TEE_TARGET stderr
98
98
#endif
99
99
100
- // NOTE: currently disabled as it produces too many log files
100
+ // Utility for synchronizing log configuration state
101
+ // since std::optional was introduced only in c++17
102
+ enum LogTriState
103
+ {
104
+ LogTriStateSame,
105
+ LogTriStateFalse,
106
+ LogTriStateTrue
107
+ };
108
+
101
109
// Utility to obtain "pid" like unique process id and use it when creating log files.
102
- // inline std::string log_get_pid()
103
- // {
104
- // static std::string pid;
105
- // if (pid.empty())
106
- // {
107
- // // std::this_thread::get_id() is the most portable way of obtaining a "process id"
108
- // // it's not the same as "pid" but is unique enough to solve multiple instances
109
- // // trying to write to the same log.
110
- // std::stringstream ss;
111
- // ss << std::this_thread::get_id();
112
- // pid = ss.str();
113
- // }
114
- //
115
- // return pid;
116
- // }
110
+ inline std::string log_get_pid ()
111
+ {
112
+ static std::string pid;
113
+ if (pid.empty ())
114
+ {
115
+ // std::this_thread::get_id() is the most portable way of obtaining a "process id"
116
+ // it's not the same as "pid" but is unique enough to solve multiple instances
117
+ // trying to write to the same log.
118
+ std::stringstream ss;
119
+ ss << std::this_thread::get_id ();
120
+ pid = ss.str ();
121
+ }
122
+
123
+ return pid;
124
+ }
117
125
118
126
// Utility function for generating log file names with unique id based on thread id.
119
127
// invocation with log_filename_generator( "llama", "log" ) creates a string "llama.<number>.log"
120
128
// where the number is a runtime id of the current thread.
121
129
122
- #define log_filename_generator (log_file_basename, log_file_extension ) log_filename_generator_impl(log_file_basename, log_file_extension)
130
+ #define log_filename_generator (log_file_basename, log_file_extension ) log_filename_generator_impl(LogTriStateSame, log_file_basename, log_file_extension)
123
131
124
132
// INTERNAL, DO NOT USE
125
- inline std::string log_filename_generator_impl (const std::string & log_file_basename, const std::string & log_file_extension)
133
+ inline std::string log_filename_generator_impl (LogTriState multilog, const std::string & log_file_basename, const std::string & log_file_extension)
126
134
{
135
+ static bool _multilog = false ;
136
+
137
+ if (multilog != LogTriStateSame)
138
+ {
139
+ _multilog = multilog == LogTriStateTrue;
140
+ }
141
+
127
142
std::stringstream buf;
128
143
129
144
buf << log_file_basename;
130
- // buf << ".";
131
- // buf << log_get_pid();
145
+ if (_multilog)
146
+ {
147
+ buf << " ." ;
148
+ buf << log_get_pid ();
149
+ }
132
150
buf << " ." ;
133
151
buf << log_file_extension;
134
152
@@ -213,15 +231,6 @@ inline std::string log_filename_generator_impl(const std::string & log_file_base
213
231
#define LOG_TEE_FLF_VAL ," "
214
232
#endif
215
233
216
- // Utility for synchronizing log configuration state
217
- // since std::optional was introduced only in c++17
218
- enum LogTriState
219
- {
220
- LogTriStateSame,
221
- LogTriStateFalse,
222
- LogTriStateTrue
223
- };
224
-
225
234
// INTERNAL, DO NOT USE
226
235
// USE LOG() INSTEAD
227
236
//
@@ -315,16 +324,23 @@ enum LogTriState
315
324
#endif
316
325
317
326
// INTERNAL, DO NOT USE
318
- inline FILE *log_handler1_impl (bool change = false , LogTriState disable = LogTriStateSame, const std::string & filename = LOG_DEFAULT_FILE_NAME, FILE *target = nullptr )
327
+ inline FILE *log_handler1_impl (bool change = false , LogTriState append = LogTriStateSame, LogTriState disable = LogTriStateSame, const std::string & filename = LOG_DEFAULT_FILE_NAME, FILE *target = nullptr )
319
328
{
320
- static bool _initialized{false };
321
- static bool _disabled{(filename.empty () && target == nullptr )};
329
+ static bool _initialized = false ;
330
+ static bool _append = false ;
331
+ static bool _disabled = filename.empty () && target == nullptr ;
322
332
static std::string log_current_filename{filename};
323
333
static FILE *log_current_target{target};
324
334
static FILE *logfile = nullptr ;
325
335
326
336
if (change)
327
337
{
338
+ if (append != LogTriStateSame)
339
+ {
340
+ _append = append == LogTriStateTrue;
341
+ return logfile;
342
+ }
343
+
328
344
if (disable == LogTriStateTrue)
329
345
{
330
346
// Disable primary target
@@ -377,7 +393,7 @@ inline FILE *log_handler1_impl(bool change = false, LogTriState disable = LogTri
377
393
}
378
394
}
379
395
380
- logfile = fopen (filename.c_str (), " w" );
396
+ logfile = fopen (filename.c_str (), _append ? " a " : " w" );
381
397
}
382
398
383
399
if (!logfile)
@@ -398,9 +414,9 @@ inline FILE *log_handler1_impl(bool change = false, LogTriState disable = LogTri
398
414
}
399
415
400
416
// INTERNAL, DO NOT USE
401
- inline FILE *log_handler2_impl (bool change = false , LogTriState disable = LogTriStateSame, FILE *target = nullptr , const std::string & filename = LOG_DEFAULT_FILE_NAME)
417
+ inline FILE *log_handler2_impl (bool change = false , LogTriState append = LogTriStateSame, LogTriState disable = LogTriStateSame, FILE *target = nullptr , const std::string & filename = LOG_DEFAULT_FILE_NAME)
402
418
{
403
- return log_handler1_impl (change, disable, filename, target);
419
+ return log_handler1_impl (change, append, disable, filename, target);
404
420
}
405
421
406
422
// Disables logs entirely at runtime.
@@ -411,7 +427,7 @@ inline FILE *log_handler2_impl(bool change = false, LogTriState disable = LogTri
411
427
// INTERNAL, DO NOT USE
412
428
inline FILE *log_disable_impl ()
413
429
{
414
- return log_handler1_impl (true , LogTriStateTrue);
430
+ return log_handler1_impl (true , LogTriStateSame, LogTriStateTrue);
415
431
}
416
432
417
433
// Enables logs at runtime.
@@ -420,19 +436,31 @@ inline FILE *log_disable_impl()
420
436
// INTERNAL, DO NOT USE
421
437
inline FILE *log_enable_impl ()
422
438
{
423
- return log_handler1_impl (true , LogTriStateFalse);
439
+ return log_handler1_impl (true , LogTriStateSame, LogTriStateFalse);
424
440
}
425
441
426
442
// Sets target fir logs, either by a file name or FILE* pointer (stdout, stderr, or any valid FILE*)
427
443
#define log_set_target (target ) log_set_target_impl(target)
428
444
429
445
// INTERNAL, DO NOT USE
430
- inline FILE *log_set_target_impl (const std::string & filename) { return log_handler1_impl (true , LogTriStateSame, filename); }
431
- inline FILE *log_set_target_impl (FILE *target) { return log_handler2_impl (true , LogTriStateSame, target); }
446
+ inline FILE *log_set_target_impl (const std::string & filename) { return log_handler1_impl (true , LogTriStateSame, LogTriStateSame, filename); }
447
+ inline FILE *log_set_target_impl (FILE *target) { return log_handler2_impl (true , LogTriStateSame, LogTriStateSame, target); }
432
448
433
449
// INTERNAL, DO NOT USE
434
450
inline FILE *log_handler () { return log_handler1_impl (); }
435
451
452
+ // Enable or disable creating separate log files for each run.
453
+ // can ONLY be invoked BEFORE first log use.
454
+ #define log_multilog (enable ) log_filename_generator_impl((enable) ? LogTriStateTrue : LogTriStateFalse, " " , " " )
455
+ // Enable or disable append mode for log file.
456
+ // can ONLY be invoked BEFORE first log use.
457
+ #define log_append (enable ) log_append_impl(enable)
458
+ // INTERNAL, DO NOT USE
459
+ inline FILE *log_append_impl (bool enable)
460
+ {
461
+ return log_handler1_impl (true , enable ? LogTriStateTrue : LogTriStateFalse, LogTriStateSame);
462
+ }
463
+
436
464
inline void log_test ()
437
465
{
438
466
log_disable ();
@@ -494,6 +522,18 @@ inline bool log_param_single_parse(const std::string & param)
494
522
return true ;
495
523
}
496
524
525
+ if (param == " --log-new" )
526
+ {
527
+ log_multilog (true );
528
+ return true ;
529
+ }
530
+
531
+ if (param == " --log-append" )
532
+ {
533
+ log_append (true );
534
+ return true ;
535
+ }
536
+
497
537
return false ;
498
538
}
499
539
@@ -523,7 +563,9 @@ inline void log_print_usage()
523
563
printf (" --log-disable Disable trace logs\n " );
524
564
printf (" --log-enable Enable trace logs\n " );
525
565
printf (" --log-file Specify a log filename (without extension)\n " );
526
- printf (" Log file will be tagged with unique ID and written as \" <name>.<ID>.log\"\n " ); /* */
566
+ printf (" --log-new Create a separate new log file on start. "
567
+ " Each log file will have unique name: \" <name>.<ID>.log\"\n " );
568
+ printf (" --log-append Don't truncate the old log file.\n " );
527
569
}
528
570
529
571
#define log_dump_cmdline (argc, argv ) log_dump_cmdline_impl(argc, argv)
0 commit comments