Changes to enable color debugging, based on the patch sent by maciejka.

Advanced debugging options are retained in NDEBUG build mode.


git-svn-id: http://yate.null.ro/svn/yate/trunk@798 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2006-05-19 15:52:05 +00:00
parent 2639e1e3e3
commit 5717e14f59
5 changed files with 112 additions and 14 deletions

View File

@ -832,7 +832,6 @@ static void usage(bool client, FILE* f)
" -c pathname Path to conf files directory (" CFG_PATH ")\n"
" -m pathname Path to modules directory (" MOD_PATH ")\n"
" -w directory Change working directory\n"
#ifndef NDEBUG
" -D[options] Special debugging options\n"
" a Abort if bugs are encountered\n"
" m Attempt to debug mutex deadlocks\n"
@ -840,8 +839,8 @@ static void usage(bool client, FILE* f)
" i Reinitialize after 1st initialization\n"
" x Exit immediately after initialization\n"
" w Delay creation of 1st worker thread\n"
" o Colorize output using ANSI codes\n"
" t Timestamp debugging messages\n"
#endif
,client ? "" :
#ifdef _WINDOWS
" --service Run as Windows service\n"
@ -884,6 +883,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
#endif
bool client = (mode == Client);
bool tstamp = false;
bool colorize = false;
const char* pidfile = 0;
const char* workdir = 0;
int debug_level = debugLevel();
@ -1003,7 +1003,6 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
pc = 0;
workdir = argv[++i];
break;
#ifndef NDEBUG
case 'D':
while (*++pc) {
switch (*pc) {
@ -1025,6 +1024,9 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
case 'w':
s_makeworker = false;
break;
case 'o':
colorize = true;
break;
case 't':
tstamp = true;
break;
@ -1035,7 +1037,6 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
}
pc = 0;
break;
#endif
case 'V':
version();
return 0;
@ -1123,6 +1124,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
::fprintf(stderr,"Options -d and -s not supported in client mode\n");
return EINVAL;
}
Debugger::enableOutput(true,colorize);
if (daemonic) {
Debugger::enableOutput(false);
// Make sure X client modules fail initialization in daemon mode

View File

@ -56,11 +56,57 @@ static bool s_debugging = true;
static bool s_abort = false;
static u_int64_t s_timestamp = 0;
static const char* const s_colors[11] = {
"\033[5;41;1;33m\033[K",// DebugFail - blinking yellow on red
"\033[41;1;33m\033[K", // Unnamed - yellow on red
"\033[41;1;37m\033[K", // DebugGoOn - white on red
"\033[41;37m\033[K", // Unnamed - gray on red
"\033[41;37m\033[K", // Unnamed - gray on red
"\033[40;1;31m\033[K", // DebugWarn - light red on black
"\033[40;1;33m\033[K", // DebugMild - yellow on black
"\033[40;1;37m\033[K", // DebugCall - white on black
"\033[40;1;32m\033[K", // DebugNote - light green on black
"\033[40;1;36m\033[K", // DebugInfo - light cyan on black
"\033[40;36m\033[K" // DebugAll - cyan on black
};
static const char* const s_levels[11] = {
"FAIL",
"FAIL",
"GOON",
"GOON",
"GOON",
"WARN",
"MILD",
"CALL",
"NOTE",
"INFO",
"ALL",
};
static const char* dbg_level(int level)
{
if (level < DebugMin)
level = DebugMin;
if (level > DebugMax)
level = DebugMax;
return s_levels[level];
}
static void dbg_stderr_func(const char* buf, int level)
{
::write(2,buf,::strlen(buf));
}
static void dbg_colorize_func(const char* buf, int level)
{
const char* col = debugColor(level);
::write(2,col,::strlen(col));
::write(2,buf,::strlen(buf));
col = debugColor(-2);
::write(2,col,::strlen(col));
}
static void (*s_output)(const char*,int) = dbg_stderr_func;
static void (*s_intout)(const char*,int) = 0;
@ -138,7 +184,7 @@ void Debug(int level, const char* format, ...)
if (!format)
format = "";
char buf[32];
::sprintf(buf,"<%d> ",level);
::sprintf(buf,"<%s> ",dbg_level(level));
va_list va;
va_start(va,format);
ind_mux.lock();
@ -158,7 +204,7 @@ void Debug(const char* facility, int level, const char* format, ...)
if (!format)
format = "";
char buf[64];
::snprintf(buf,sizeof(buf),"<%s:%d> ",facility,level);
::snprintf(buf,sizeof(buf),"<%s:%s> ",facility,dbg_level(level));
va_list va;
va_start(va,format);
ind_mux.lock();
@ -187,9 +233,9 @@ void Debug(const DebugEnabler* local, int level, const char* format, ...)
format = "";
char buf[64];
if (facility)
::snprintf(buf,sizeof(buf),"<%s:%d> ",facility,level);
::snprintf(buf,sizeof(buf),"<%s:%s> ",facility,dbg_level(level));
else
::sprintf(buf,"<%d> ",level);
::sprintf(buf,"<%s> ",dbg_level(level));
va_list va;
va_start(va,format);
ind_mux.lock();
@ -232,6 +278,15 @@ bool debugAt(int level)
return (s_debugging && (level <= s_debug));
}
const char* debugColor(int level)
{
if (level == -2)
return "\033[0m\033[K"; // reset to defaults
if ((level < DebugMin) || (level > DebugMax))
return "\033[0;40;37m\033[K"; // light gray on black
return s_colors[level];
}
void setDebugTimestamp()
{
s_timestamp = (Time::now() / 1000000) * 1000000;
@ -339,9 +394,11 @@ void Debugger::setIntOut(void (*outFunc)(const char*,int))
out_mux.unlock();
}
void Debugger::enableOutput(bool enable)
void Debugger::enableOutput(bool enable, bool colorize)
{
s_debugging = enable;
if (colorize)
setOutput(dbg_colorize_func);
}

View File

@ -40,6 +40,7 @@ static const char s_helpmsg[] =
" status [module]\n"
" machine [on|off]\n"
" output [on|off]\n"
" color [on|off]\n"
" auth password\n"
"Authenticated commands:\n"
" debug [level|on|off]\n"
@ -88,9 +89,11 @@ private:
bool m_auth;
bool m_debug;
bool m_output;
bool m_colorize;
bool m_machine;
Socket* m_socket;
String m_address;
String m_lastcmd;
};
class RManager : public Plugin
@ -162,7 +165,7 @@ Connection *Connection::checkCreate(Socket* sock, const char* addr)
Connection::Connection(Socket* sock, const char* addr)
: Thread("RManager Connection"),
m_auth(false), m_debug(false), m_output(s_output), m_machine(false),
m_auth(false), m_debug(false), m_output(s_output), m_colorize(false), m_machine(false),
m_socket(sock), m_address(addr)
{
s_mutex.lock();
@ -264,8 +267,15 @@ bool Connection::processLine(const char *line)
DDebug("RManager",DebugInfo,"processLine = %s",line);
String str(line);
str.trimBlanks();
if (str.null())
return false;
// backslash or ANSI up arrow to repeat last command - very handy
if ((str == "\\") || (str == "\033[A") || (str == "\033[1A") || (str == "\033A")) {
if (m_lastcmd.null())
return false;
str = m_lastcmd;
}
else
m_lastcmd = str;
if (str.startSkip("status"))
{
@ -298,6 +308,14 @@ bool Connection::processLine(const char *line)
writeStr(str);
return false;
}
else if (str.startSkip("color"))
{
str >> m_colorize;
str = "Colorized output: ";
str += (m_colorize ? "yes\n" : "no\n");
writeStr(str);
return false;
}
else if (str.startSkip("quit"))
{
writeStr(m_machine ? "%%=quit\n" : "Goodbye!\n");
@ -482,8 +500,16 @@ void Connection::writeDebug(const char *str, int level)
{
if (null(str))
return;
if (m_debug || (m_output && (level < 0)))
if (m_debug || (m_output && (level < 0))) {
const char* col = m_colorize ? debugColor(level) : 0;
if (col)
writeStr(col,::strlen(col));
writeStr(str,::strlen(str));
if (col)
col = debugColor(-2);
if (col)
writeStr(col,::strlen(col));
}
}
void Connection::writeStr(const char *str, int len)

3
yate.8
View File

@ -85,6 +85,9 @@ Exit immediately after initialization
.B \-Dw
Delay for one second the creation of the first worker thread
.TP
.B \-Do
Colorize the output using ANSI control character sequences
.TP
.B \-Dt
Add start time relative timestamps to debugging messages
.SH COMMANDS

View File

@ -240,6 +240,14 @@ YATE_API int debugLevel(int level);
*/
YATE_API bool debugAt(int level);
/**
* Get an ANSI string to colorize debugging output
* @param level The debug level who's color is requested.
* Negative or out of range will reset to the default color
* @return ANSI string that sets color corresponding to level
*/
YATE_API const char* debugColor(int level);
/**
* Holds a local debugging level that can be modified separately from the
* global debugging
@ -514,8 +522,10 @@ public:
/**
* Enable or disable the debug output
* @param enable Set to true to globally enable output
* @param colorize Enable ANSI colorization of output
*/
static void enableOutput(bool enable = true);
static void enableOutput(bool enable = true, bool colorize = false);
private:
const char* m_name;