Warning, /eic-opticks/sysrap/SLOG_review.rst is written in an unsupported language. File is not indexed.
0001 SLOG review
0002 ==============
0003
0004 Overview
0005 ----------
0006
0007 SLOG provides a thin convenience/configuration layer above the
0008 underlying plog logging framework. In particular it
0009 makes it simple to setup a chained multi-logger system with a
0010 main logger and loggers for each library with individually
0011 controlled logging levels via command line arguments,
0012 which all log to the same console and logfile.
0013
0014 ::
0015
0016 OKTest --warn \ # global loglevel
0017 --npy verbose \ # per-library loglevel
0018 --sysrap warning
0019
0020
0021 Getting rid of the dangerous re-define of trace
0022 -------------------------------------------------
0023
0024 Observe a problem with xercesc headers : so bite the bullet
0025 and get rid of the dangerous define and switch all
0026 use of LOG(trace) into LOG(verbose)
0027
0028 ::
0029
0030 epsilon:sysrap blyth$ hg diff SLOG.hh
0031 diff -r 3e7743e5bc48 sysrap/SLOG.hh
0032 --- a/sysrap/SLOG.hh Thu Aug 16 00:01:19 2018 +0800
0033 +++ b/sysrap/SLOG.hh Thu Aug 16 12:57:29 2018 +0800
0034 @@ -15,7 +15,7 @@
0035 using plog::verbose ;
0036
0037 // hmm dangerous but what alternative
0038 -#define trace plog::verbose
0039 +//#define trace plog::verbose
0040
0041 #include "SYSRAP_API_EXPORT.hh"
0042
0043 epsilon:sysrap blyth$
0044
0045
0046
0047 plog
0048 ------
0049
0050 * https://github.com/SergiusTheBest/plog
0051
0052 chained loggers
0053 ~~~~~~~~~~~~~~~~~~
0054
0055 * https://github.com/SergiusTheBest/plog#chained-loggers
0056 * https://github.com/SergiusTheBest/plog/blob/master/samples/Chained/ChainedApp/Main.cpp
0057 * https://github.com/SergiusTheBest/plog/blob/master/samples/Chained/ChainedLib/Main.cpp
0058
0059 A Logger can work as an Appender for another Logger. So you can chain several
0060 loggers together. This is useful for streaming log messages from a shared
0061 library to the main application binary.
0062
0063
0064 ::
0065
0066 // main app
0067
0068 // Functions imported form the shared library.
0069 extern "C" void initialize(plog::Severity severity, plog::IAppender* appender);
0070 extern "C" void foo();
0071
0072 int main()
0073 {
0074 plog::init(plog::debug, "ChainedApp.txt"); // Initialize the main logger.
0075
0076 LOGD << "Hello from app!"; // Write a log message.
0077
0078 initialize(plog::debug, plog::get()); // Initialize the logger in the shared library. Note that it has its own severity.
0079 foo(); // Call a function from the shared library that produces a log message.
0080
0081 return 0;
0082 }
0083
0084 ::
0085
0086 // shared library
0087
0088 // Function that initializes the logger in the shared library.
0089 extern "C" void EXPORT initialize(plog::Severity severity, plog::IAppender* appender)
0090 {
0091 plog::init(severity, appender); // Initialize the shared library logger.
0092 }
0093
0094 // Function that produces a log message.
0095 extern "C" void EXPORT foo()
0096 {
0097 LOGI << "Hello from shared lib!";
0098 }
0099
0100
0101 Typical Opticks executable main
0102 ----------------------------------
0103 ::
0104
0105
0106 01 // op --opticks
0107 2
0108 3 #include <iostream>
0109 4
0110 5 #include "BFile.hh"
0111 6 #include "SLOG.hh"
0112 7
0113 8 #include "SYSRAP_LOG.hh"
0114 9 #include "BRAP_LOG.hh"
0115 10 #include "NPY_LOG.hh"
0116 11 #include "OKCORE_LOG.hh"
0117 12
0118 13 #include "Opticks.hh"
0119 14
0120 ..
0121 74 int main(int argc, char** argv)
0122 75 {
0123 76 SLOG_(argc,argv);
0124 77 LOG(info) << argv[0] ;
0125 78
0126 79
0127 80 SYSRAP_LOG__ ;
0128 81 BRAP_LOG__ ;
0129 82 NPY_LOG__ ;
0130 83 OKCORE_LOG__ ;
0131 84
0132 85
0133 86 Opticks ok(argc, argv);
0134 87
0135
0136
0137 SLOG.hh
0138 ~~~~~~~~~~
0139
0140 ::
0141
0142 005 #include <cstddef>
0143 6 #include <plog/Log.h>
0144 7
0145 8 // translate from boost log levels to plog
0146 9 using plog::fatal ;
0147 10 using plog::error ;
0148 11 using plog::warning ;
0149 12 using plog::info ;
0150 13 using plog::debug ;
0151 14 using plog::verbose ;
0152 15
0153 16 // hmm dangerous but what alternative
0154 17 #define trace plog::verbose
0155 18
0156 19 #include "SYSRAP_API_EXPORT.hh"
0157 ...
0158 105 struct SLOG ;
0159 106
0160 107 struct SYSRAP_API SLOG
0161 108 {
0162 109 int argc ;
0163 110 char** argv ;
0164 111 int level ;
0165 112 const char* logpath ;
0166 113 int logmax ;
0167 114
0168 115 SLOG(int argc, char** argv, const char* fallback="VERBOSE", const char* prefix=NULL );
0169 116
0170 117 const char* name();
0171 118 int parse( const char* fallback);
0172 119 int parse( plog::Severity _fallback);
0173 120 int prefixlevel_parse( const char* fallback, const char* prefix);
0174 121 int prefixlevel_parse( plog::Severity _fallback, const char* prefix);
0175 122
0176 123 static int _parse(int argc, char** argv, const char* fallback);
0177 124 static int _prefixlevel_parse(int argc, char** argv, const char* fallback, const char* prefix);
0178 125 static void _dump(const char* msg, int argc, char** argv);
0179 126 static const char* _name(plog::Severity severity);
0180 127 static const char* _name(int level);
0181 128 static const char* _logpath_parse(int argc, char** argv);
0182 129
0183 130 static SLOG* instance ;
0184 ... ^^^^^^^^^^^^^^^^^^^^^^^^^^ static singleton instance : possibly source of stomp problems with recent gcc ?
0185
0186 131 };
0187 132
0188 133
0189 134 #include "SLOG_INIT.hh"
0190 135
0191
0192
0193 SLOG_INIT.hh
0194 ~~~~~~~~~~~~~~
0195
0196 ::
0197
0198 01 #include <plog/Log.h>
0199 2 #include <plog/Appenders/ColorConsoleAppender.h>
0200 3 #include <plog/Appenders/ConsoleAppender.h>
0201 4 #include <plog/Formatters/FuncMessageFormatter.h>
0202 5
0203 6 #include "PlainFormatter.hh"
0204 7
0205 8 /*
0206 9
0207 10 SLOG_INIT macros are used in two situations:
0208 11
0209 12 * an executable main as a result of SLOG_ or PLOT_COLOR applied
0210 13 to the arguments
0211 14
0212 15 * package logger
0213 16
0214 17
0215 18 */
0216 19
0217 20
0218 21
0219 22 #define SLOG_INIT(level, app1, app2 ) \
0220 23 { \
0221 24 plog::IAppender* appender1 = app1 ? static_cast<plog::IAppender*>(app1) : NULL ; \
0222 25 plog::IAppender* appender2 = app2 ? static_cast<plog::IAppender*>(app2) : NULL ; \
0223 26 plog::Severity severity = static_cast<plog::Severity>(level) ; \
0224 27 plog::init( severity , appender1 ); \
0225 28 if(appender2) \
0226 29 plog::get()->addAppender(appender2) ; \
0227 30 } \
0228 31
0229 32
0230 33 #define SLOG_COLOR(argc, argv) \
0231 34 { \
0232 35 SLOG _plog(argc, argv); \
0233 36 static plog::RollingFileAppender<plog::FuncMessageFormatter> fileAppender( _plog.logpath, _plog.logmax); \
0234 37 static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender; \
0235 38 SLOG_INIT( _plog.level, &consoleAppender, &fileAppender ); \
0236 39 } \
0237 40
0238 41 #define SLOG_(argc, argv) \
0239 42 { \
0240 43 SLOG _plog(argc, argv); \
0241 44 static plog::RollingFileAppender<plog::FuncMessageFormatter> fileAppender( _plog.logpath, _plog.logmax); \
0242 45 static plog::ConsoleAppender<plog::TxtFormatter> consoleAppender; \
0243 46 SLOG_INIT( _plog.level, &consoleAppender, &fileAppender ); \
0244 47 } \
0245 48
0246 ...
0247
0248
0249 What SLOG_(argc, argv) does
0250 ------------------------------
0251
0252 ::
0253
0254 74 int main(int argc, char** argv)
0255 75 {
0256 76 SLOG_(argc,argv);
0257 77 LOG(info) << argv[0] ;
0258 78
0259
0260 Instanciates SLOG struct into main which parses command line arguments into:
0261
0262 * global logmax
0263 * global logpath
0264 * holds onto arguments within SLOG::instance, for use from the package loggers
0265
0266 Invokes SLOG_INIT macro which instanciates the main plog logger and hooks up
0267 file and console appenders.
0268
0269
0270 What SYSRAP_LOG__ and other pkg macros do
0271 ---------------------------------------------
0272
0273 ::
0274
0275 5 #define SYSRAP_LOG__ { SYSRAP_LOG::Initialize(SLOG::instance->prefixlevel_parse( info, "SYSRAP"), plog::get(), NULL ); }
0276
0277 ## notice that the main logger plog::get() is being passed to the lib logger as an appender
0278
0279
0280 * uses the command line arguments persisted in SLOG::instance to define the per-package logging level
0281 and passes this level to the package libs where SLOG_INIT is invoked to instanciate the
0282 per-library loggers.
0283
0284 * also chains together the main and library loggers ; this means than the lib
0285 logger acts as an appender for the main logger
0286
0287
0288 Package Loggers
0289 -------------------
0290
0291 SYSRAP_LOG.hh SYSRAP_LOG.cc
0292 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0293
0294 ::
0295
0296 01
0297 2 #pragma once
0298 3 #include "SYSRAP_API_EXPORT.hh"
0299 4
0300 5 #define SYSRAP_LOG__ { SYSRAP_LOG::Initialize(SLOG::instance->prefixlevel_parse( info, "SYSRAP"), plog::get(), NULL ); }
0301 6
0302 7 #define SYSRAP_LOG_ { SYSRAP_LOG::Initialize(plog::get()->getMaxSeverity(), plog::get(), NULL ); }
0303 8 class SYSRAP_API SYSRAP_LOG {
0304 9 public:
0305 10 static void Initialize(int level, void* app1, void* app2 );
0306 11 static void Check(const char* msg);
0307 12 };
0308 13
0309
0310 01
0311 2 #include <plog/Log.h>
0312 3
0313 4 #include "SYSRAP_LOG.hh"
0314 5 #include "SLOG_INIT.hh"
0315 6 #include "SLOG.hh"
0316 7
0317 8 void SYSRAP_LOG::Initialize(int level, void* app1, void* app2 )
0318 9 {
0319 10 SLOG_INIT(level, app1, app2);
0320 11 }
0321 12 void SYSRAP_LOG::Check(const char* msg)
0322 13 {
0323 14 SLOG_CHECK(msg);
0324 15 }
0325 16
0326
0327
0328 NPY_LOG.hh NPY_LOG.cc
0329 ~~~~~~~~~~~~~~~~~~~~~~~~~~
0330
0331 ::
0332
0333
0334 01
0335 2 #pragma once
0336 3 #include "NPY_API_EXPORT.hh"
0337 4
0338 5 #define NPY_LOG__ { NPY_LOG::Initialize(SLOG::instance->prefixlevel_parse( info, "NPY"), plog::get(), NULL ); }
0339 6
0340 7 #define NPY_LOG_ { NPY_LOG::Initialize(plog::get()->getMaxSeverity(), plog::get(), NULL ); }
0341 8 class NPY_API NPY_LOG {
0342 9 public:
0343 10 static void Initialize(int level, void* app1, void* app2 );
0344 11 static void Check(const char* msg);
0345 12 };
0346 13
0347
0348 01
0349 2 #include <plog/Log.h>
0350 3
0351 4 #include "NPY_LOG.hh"
0352 5 #include "SLOG_INIT.hh"
0353 6 #include "SLOG.hh"
0354 7
0355 8 void NPY_LOG::Initialize(int level, void* app1, void* app2 )
0356 9 {
0357 10 SLOG_INIT(level, app1, app2);
0358 11 }
0359 12 void NPY_LOG::Check(const char* msg)
0360 13 {
0361 14 SLOG_CHECK(msg);
0362 15 }
0363
0364
0365
0366
0367
0368 Same pattern followed by all package loggers ...
0369 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0370
0371
0372 ::
0373
0374 simon:opticks blyth$ find . -name '*_LOG.cc'
0375 ./assimprap/ASIRAP_LOG.cc
0376 ./boostrap/BRAP_LOG.cc
0377 ./cfg4/CFG4_LOG.cc
0378 ./cudarap/CUDARAP_LOG.cc
0379 ./ggeo/GGEO_LOG.cc
0380 ./oglrap/OGLRAP_LOG.cc
0381 ./ok/OK_LOG.cc
0382 ./okg4/OKG4_LOG.cc
0383 ./okop/OKOP_LOG.cc
0384 ./openmeshrap/MESHRAP_LOG.cc
0385 ./optickscore/OKCORE_LOG.cc
0386 ./opticksgeo/OKGEO_LOG.cc
0387 ./opticksgl/OKGL_LOG.cc
0388 ./opticksnpy/NPY_LOG.cc
0389 ./optixrap/OXRAP_LOG.cc
0390 ./sysrap/SYSRAP_LOG.cc
0391 ./thrustrap/THRAP_LOG.cc
0392 simon:opticks blyth$
0393
0394 Using the preprocessor macros allows the same logging setup code to
0395 be planted in every library.
0396
0397
0398
0399 Issue : log level not controlled in standalone script build cfg4/tests/CGDMLKludgeTest.sh
0400 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0401
0402 ::
0403
0404 epsilon:cfg4 blyth$ grep CFG4_LOG *.*
0405 CFG4_LOG.cc:#include "CFG4_LOG.hh"
0406 CFG4_LOG.cc:void CFG4_LOG::Initialize(int level, void* app1, void* app2 )
0407 CFG4_LOG.cc:void CFG4_LOG::Check(const char* msg)
0408 CFG4_LOG.hh:#define CFG4_LOG__ { CFG4_LOG::Initialize(SLOG::instance->prefixlevel_parse( info, "CFG4"), plog::get(), NULL ); }
0409 CFG4_LOG.hh:#define CFG4_LOG_ { CFG4_LOG::Initialize(plog::get()->getMaxSeverity(), plog::get(), NULL ); }
0410 CFG4_LOG.hh:class CFG4_API CFG4_LOG {
0411 CMakeLists.txt: CFG4_LOG.cc
0412 CMakeLists.txt: CFG4_LOG.hh
0413 epsilon:cfg4 blyth$
0414
0415
0416 The main does this, CGDMLKludgeTest.cc::
0417
0418 08 #include "OPTICKS_LOG.hh"
0419 9 #include "CGDMLKludge.hh"
0420 10
0421 11 int main(int argc, char** argv)
0422 12 {
0423 13 OPTICKS_LOG(argc, argv);
0424 14
0425
0426
0427 What OPTICKS_LOG does depends on the preprocessor macros such as *-DOPTICKS_CFG4*::
0428
0429 #define OPTICKS_LOG(argc, argv) { SLOG_COLOR(argc, argv); OPTICKS_LOG_::Initialize(SLOG::instance, plog::get(), NULL ); }
0430
0431
0432
0433 OPTICKS_LOG.hh::
0434
0435 108 class SYSRAP_API OPTICKS_LOG_ {
0436 109 public:
0437 110 // initialize all linked loggers and hookup the main logger
0438 111 static void Initialize(SLOG* instance, void* app1, void* /*app2*/ )
0439 112 {
0440 113 int max_level = instance->parse("info") ;
0441 114 // note : can decrease verbosity from the max_level in the subproj, but not increase
0442 115
0443 116 #ifdef OPTICKS_SYSRAP
0444 117 SYSRAP_LOG::Initialize(instance->prefixlevel_parse( max_level, "SYSRAP"), app1, NULL );
0445 118 #endif
0446 119 #ifdef OPTICKS_BRAP
0447 120 BRAP_LOG::Initialize(instance->prefixlevel_parse( max_level, "BRAP"), app1, NULL );
0448 121 #endif
0449 ...
0450 164 #ifdef OPTICKS_X4
0451 165 X4_LOG::Initialize(instance->prefixlevel_parse( max_level, "X4"), app1, NULL );
0452 166 #endif
0453 167 #ifdef OPTICKS_CFG4
0454 168 CFG4_LOG::Initialize(instance->prefixlevel_parse( max_level, "CFG4"), app1, NULL );
0455 169 #endif
0456
0457
0458
0459
0460