Console: improve console logging facility

This commit is contained in:
Zheng, Lei
2019-06-21 10:13:46 +08:00
committed by wmayer
parent 5ca5f906d9
commit bfa68f2676
2 changed files with 79 additions and 77 deletions

View File

@@ -40,6 +40,7 @@
#include "Exception.h"
#include "PyObjectBase.h"
#include <QCoreApplication>
#include <frameobject.h>
using namespace Base;
@@ -251,18 +252,24 @@ void ConsoleSingleton::SetConnectionMode(ConnectionMode mode)
*/
void ConsoleSingleton::Message( const char *pMsg, ... )
{
char format[BufferSize];
const unsigned int format_len = BufferSize;
#define FC_CONSOLE_FMT(_type,_type2) \
char format[BufferSize];\
format[sizeof(format)-4] = '.';\
format[sizeof(format)-3] = '.';\
format[sizeof(format)-2] = '\n';\
format[sizeof(format)-1] = 0;\
const unsigned int format_len = sizeof(format)-4;\
va_list namelessVars;\
va_start(namelessVars, pMsg);\
vsnprintf(format, format_len, pMsg, namelessVars);\
format[sizeof(format)-5] = '.';\
va_end(namelessVars);\
if (connectionMode == Direct)\
Notify##_type(format);\
else\
QCoreApplication::postEvent(ConsoleOutput::getInstance(), new ConsoleEvent(MsgType_##_type2, format));
va_list namelessVars;
va_start(namelessVars, pMsg); // Get the "..." vars
vsnprintf(format, format_len, pMsg, namelessVars);
va_end(namelessVars);
if (connectionMode == Direct)
NotifyMessage(format);
else
QCoreApplication::postEvent(ConsoleOutput::getInstance(), new ConsoleEvent(MsgType_Txt, format));
FC_CONSOLE_FMT(Message,Txt);
}
/** Prints a Message
@@ -282,18 +289,7 @@ void ConsoleSingleton::Message( const char *pMsg, ... )
*/
void ConsoleSingleton::Warning( const char *pMsg, ... )
{
char format[BufferSize];
const unsigned int format_len = BufferSize;
va_list namelessVars;
va_start(namelessVars, pMsg); // Get the "..." vars
vsnprintf(format, format_len, pMsg, namelessVars);
va_end(namelessVars);
if (connectionMode == Direct)
NotifyWarning(format);
else
QCoreApplication::postEvent(ConsoleOutput::getInstance(), new ConsoleEvent(MsgType_Wrn, format));
FC_CONSOLE_FMT(Warning,Wrn);
}
/** Prints a Message
@@ -313,18 +309,7 @@ void ConsoleSingleton::Warning( const char *pMsg, ... )
*/
void ConsoleSingleton::Error( const char *pMsg, ... )
{
char format[BufferSize];
const unsigned int format_len = BufferSize;
va_list namelessVars;
va_start(namelessVars, pMsg); // Get the "..." vars
vsnprintf(format, format_len, pMsg, namelessVars);
va_end(namelessVars);
if (connectionMode == Direct)
NotifyError(format);
else
QCoreApplication::postEvent(ConsoleOutput::getInstance(), new ConsoleEvent(MsgType_Err, format));
FC_CONSOLE_FMT(Error,Err);
}
@@ -346,24 +331,12 @@ void ConsoleSingleton::Error( const char *pMsg, ... )
void ConsoleSingleton::Log( const char *pMsg, ... )
{
char format[BufferSize];
const unsigned int format_len = BufferSize;
if (_bVerbose)
if (!_bVerbose)
{
va_list namelessVars;
va_start(namelessVars, pMsg); // Get the "..." vars
vsnprintf(format, format_len, pMsg, namelessVars);
va_end(namelessVars);
if (connectionMode == Direct)
NotifyLog(format);
else
QCoreApplication::postEvent(ConsoleOutput::getInstance(), new ConsoleEvent(MsgType_Log, format));
FC_CONSOLE_FMT(Log,Log);
}
}
/** Delivers the time/date
* This method gives you a string with the actual time/date. You can
* use that for Log() calls to make timestamps.
@@ -464,7 +437,7 @@ int *ConsoleSingleton::GetLogLevel(const char *tag, bool create) {
void ConsoleSingleton::Refresh() {
if(_bCanRefresh)
QCoreApplication::sendPostedEvents();
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
void ConsoleSingleton::EnableRefresh(bool enable) {
@@ -552,7 +525,7 @@ PyObject *ConsoleSingleton::sPyMessage(PyObject * /*self*/, PyObject *args)
PY_TRY {
if (string)
Instance().Message("%s",string); // process message
Instance().NotifyMessage(string); // process message
} PY_CATCH;
Py_XDECREF(unicode);
@@ -598,7 +571,7 @@ PyObject *ConsoleSingleton::sPyWarning(PyObject * /*self*/, PyObject *args)
PY_TRY {
if (string)
Instance().Warning("%s",string); // process message
Instance().NotifyWarning(string); // process message
} PY_CATCH;
Py_XDECREF(unicode);
@@ -644,7 +617,7 @@ PyObject *ConsoleSingleton::sPyError(PyObject * /*self*/, PyObject *args)
PY_TRY {
if (string)
Instance().Error("%s",string); // process message
Instance().NotifyError(string); // process message
} PY_CATCH;
Py_XDECREF(unicode);
@@ -690,7 +663,7 @@ PyObject *ConsoleSingleton::sPyLog(PyObject * /*self*/, PyObject *args)
PY_TRY {
if (string)
Instance().Log("%s",string); // process message
Instance().NotifyLog(string); // process message
} PY_CATCH;
Py_XDECREF(unicode);
@@ -968,8 +941,23 @@ std::stringstream &LogLevel::prefix(std::stringstream &str, const char *src, int
str << d.count() << ' ';
}
if(print_tag) str << '<' << tag << "> ";
if(print_src) {
if(print_src==2) {
PyFrameObject* frame = PyEval_GetFrame();
if(frame) {
line = PyFrame_GetLineNumber(frame);
#if PY_MAJOR_VERSION >= 3
src = PyUnicode_AsUTF8(frame->f_code->co_filename);
#else
src = PyString_AsString(frame->f_code->co_filename);
#endif
}
}
if(print_src && src && src[0]) {
#ifdef FC_OS_WIN32
const char *_f = std::strrchr(src, '\\');
#else
const char *_f = std::strrchr(src, '/');
#endif
str << (_f?_f+1:src)<<"("<<line<<"): ";
}
return str;

View File

@@ -123,7 +123,7 @@
* shown blew along with their default values.
*
* \code{.c}
* FC_LOG_LEVEL_INIT(tag, print_tag=true, print_src=false,
* FC_LOG_LEVEL_INIT(tag, print_tag=true, print_src=0,
* print_time=false, add_eol=true, refresh=false)
* \endcode
*
@@ -133,7 +133,11 @@
*
* \code{.c}
* FC_LOG_INSTANCE.refresh = true; // print time for each log, default false.
* FC_LOG_INSTANCE.print_src = true; // print file and line number, default false.
*
* // print file and line number, default 0, if set to 2 then print python
* // source from current call frame.
* FC_LOG_INSTANCE.print_src = 1;
*
* FC_LOG_INSTANCE.print_tag = false; // do not print tag, default true
* FC_LOG_INSTANCE.add_eol = false; // do not add eol
* FC_LOG_INSTANCE.refresh = true; // refresh GUI after each log
@@ -349,24 +353,34 @@
#define FC_LOG_LEVEL_INIT(_tag,...) \
_FC_LOG_LEVEL_INIT(FC_LOG_INSTANCE, _tag, ## __VA_ARGS__)
#define _FC_PRINT(_instance,_l,_func,_msg) do{\
#define __FC_PRINT(_instance,_l,_func,_msg,_file,_line) do{\
if(_instance.isEnabled(_l)) {\
std::stringstream str;\
_instance.prefix(str,__FILE__,__LINE__) << _msg;\
std::stringstream _str;\
_instance.prefix(_str,_file,_line) << _msg;\
if(_instance.add_eol) \
str<<std::endl;\
Base::Console()._func("%s",str.str().c_str());\
_str<<std::endl;\
Base::Console()._func(_str.str().c_str());\
if(_instance.refresh) Base::Console().Refresh();\
}\
}while(0)
#define FC_MSG(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_MSG,Message,_msg)
#define FC_WARN(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_WARN,Warning,_msg)
#define FC_ERR(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_ERR,Error,_msg)
#define FC_LOG(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_LOG,Log,_msg)
#define FC_TRACE(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_TRACE,Log,_msg)
#define _FC_PRINT(_instance,_l,_func,_msg) __FC_PRINT(_instance,_l,_func,_msg,__FILE__,__LINE__)
#define FC_MSG(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_MSG,NotifyMessage,_msg)
#define FC_WARN(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_WARN,NotifyWarning,_msg)
#define FC_ERR(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_ERR,NotifyError,_msg)
#define FC_LOG(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_LOG,NotifyLog,_msg)
#define FC_TRACE(_msg) _FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_TRACE,NotifyLog,_msg)
#define _FC_MSG(_file,_line,_msg) __FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_MSG,NotifyMessage,_msg,_file,_line)
#define _FC_WARN(_file,_line,_msg) __FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_WARN,NotifyWarning,_msg,_file,_line)
#define _FC_ERR(_file,_line,_msg) __FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_ERR,NotifyError,_msg,_file,_line)
#define _FC_LOG(_file,_line,_msg) __FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_LOG,NotifyLog,_msg,_file,_line)
#define _FC_TRACE(_file,_line,_msg) __FC_PRINT(FC_LOG_INSTANCE,FC_LOGLEVEL_TRACE,NotifyLog,_msg,_file,_line)
#define FC_XYZ(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')'
#define FC_XY(_pt) '('<<(_pt).x<<", " << (_pt).y<<')'
#define FC_xy(_pt) '('<<(_pt).x<<", " << (_pt).y<<')'
#define FC_xyz(_pt) '('<<(_pt).x<<", " << (_pt).y<<", " << (_pt).z<<')'
#ifndef FC_LOG_NO_TIMING
# define FC_TIME_CLOCK high_resolution_clock
@@ -506,7 +520,13 @@ public:
/// Prints a log Message
virtual void Log ( const char * pMsg, ... ) ;
/// Delivers a time/date string
// observer processing
void NotifyMessage(const char *sMsg);
void NotifyWarning(const char *sMsg);
void NotifyError (const char *sMsg);
void NotifyLog (const char *sMsg);
/// Delivers a time/date string
const char* Time(void);
/// Attaches an Observer to FCConsole
void AttachObserver(ConsoleObserver *pcObserver);
@@ -582,12 +602,6 @@ private:
static void Destruct(void);
static ConsoleSingleton *_pcSingleton;
// observer processing
void NotifyMessage(const char *sMsg);
void NotifyWarning(const char *sMsg);
void NotifyError (const char *sMsg);
void NotifyLog (const char *sMsg);
// observer list
std::set<ConsoleObserver * > _aclObservers;
@@ -623,12 +637,12 @@ public:
std::string tag;
int &lvl;
bool print_tag;
bool print_src;
int print_src;
bool print_time;
bool add_eol;
bool refresh;
LogLevel(const char *tag, bool print_tag=true, bool print_src=false,
LogLevel(const char *tag, bool print_tag=true, int print_src=0,
bool print_time=false, bool add_eol=true, bool refresh=false)
:tag(tag),lvl(*Console().GetLogLevel(tag))
,print_tag(print_tag),print_src(print_src),print_time(print_time)