NS_LOG parsing changes to address bug 91
This commit is contained in:
276
src/core/log.cc
276
src/core/log.cc
@@ -18,6 +18,8 @@
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
// What about print-list!!!!!!???????
|
||||
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
|
||||
#include <list>
|
||||
@@ -44,69 +46,33 @@ ComponentList *GetComponentList (void)
|
||||
return &components;
|
||||
}
|
||||
|
||||
void
|
||||
LogComponentEnableEnvVar (void)
|
||||
LogComponent::LogComponent (char const * name)
|
||||
: m_levels (0), m_name (name)
|
||||
{
|
||||
static bool isFirstLog = true;
|
||||
#if 0
|
||||
//
|
||||
// Interesting static constructor bug:
|
||||
//
|
||||
// The RandomDirection2dMobilityModel declares a RandomVariableDefaultValue
|
||||
// g_speedVariable. This variable is initialized in the
|
||||
// static_initialization_and_destruction_0 function as expected. This causes
|
||||
// RandomVariableDefaultValue::Parse () to be called which calls NS_LOG_X
|
||||
// functions. The macro calls LogComponent::IsEnabled () which calls
|
||||
// LogComponentEnableEnvVar (). The following variable called isFirstLog
|
||||
// is set after the first call to prevent the environment variable from
|
||||
// actually being parsed on every log call.
|
||||
//
|
||||
// When the RandomDirection2dMobilityModel static constructor is run, other
|
||||
// log components may not have had their static constructors run yet. It is
|
||||
// in those other static constructors that their log components are added to
|
||||
// the list of log components.
|
||||
//
|
||||
// The end result is that if any code calls an NS_LOG_X function during its
|
||||
// static constructor, the environment variable check is "locked out" for
|
||||
// any log component declarations (in different compilation units) that have
|
||||
// not yet been executed.
|
||||
//
|
||||
// So, the choice seems to be to either 1) parse the environment variables
|
||||
// at every log call; or 2) make LogComponentEnableEnvVar explicitly called
|
||||
// after all other static constructors are called. This means in main ().
|
||||
// The former choice seems the only reasonable way out if we care remotely
|
||||
// about performance in logging.
|
||||
//
|
||||
// I made LogComponentEnableEnvVar a public API that you need to call in
|
||||
// main () if you want to use environment variables to drive the log output.
|
||||
//
|
||||
if (!isFirstLog)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif // 0
|
||||
EnvVarCheck (name);
|
||||
|
||||
ComponentList *components = GetComponentList ();
|
||||
for (ComponentListI i = components->begin ();
|
||||
i != components->end ();
|
||||
i++)
|
||||
{
|
||||
NS_ASSERT (i->first != name);
|
||||
}
|
||||
components->push_back (std::make_pair (name, this));
|
||||
}
|
||||
|
||||
void
|
||||
LogComponent::EnvVarCheck (char const * name)
|
||||
{
|
||||
#ifdef HAVE_GETENV
|
||||
char *envVar = getenv("NS_LOG");
|
||||
if (envVar == 0)
|
||||
{
|
||||
isFirstLog = false;
|
||||
return;
|
||||
}
|
||||
std::string env = envVar;
|
||||
if (env == "print-list")
|
||||
{
|
||||
LogComponentPrintList ();
|
||||
isFirstLog = false;
|
||||
return;
|
||||
}
|
||||
if (env == "*")
|
||||
{
|
||||
LogComponentEnableAll (LOG_DEBUG);
|
||||
isFirstLog = false;
|
||||
return;
|
||||
}
|
||||
bool allFound = true;
|
||||
std::string myName = name;
|
||||
|
||||
std::string::size_type cur = 0;
|
||||
std::string::size_type next = 0;
|
||||
while (true)
|
||||
@@ -128,118 +94,101 @@ LogComponentEnableEnvVar (void)
|
||||
}
|
||||
std::string::size_type equal = tmp.find ("=");
|
||||
std::string component;
|
||||
int level = 0;
|
||||
if (equal == std::string::npos)
|
||||
{
|
||||
component = tmp;
|
||||
level = LOG_DEBUG;
|
||||
if (component == myName || component == "*")
|
||||
{
|
||||
Enable (LOG_DEBUG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
component = tmp.substr (0, equal);
|
||||
std::string::size_type cur_lev;
|
||||
std::string::size_type next_lev = equal;
|
||||
do
|
||||
if (component == myName || component == "*")
|
||||
{
|
||||
cur_lev = next_lev + 1;
|
||||
next_lev = tmp.find ("|", cur_lev);
|
||||
std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
|
||||
if (lev == "error")
|
||||
int level = 0;
|
||||
std::string::size_type cur_lev;
|
||||
std::string::size_type next_lev = equal;
|
||||
do
|
||||
{
|
||||
level |= LOG_ERROR;
|
||||
}
|
||||
else if (lev == "warn")
|
||||
{
|
||||
level |= LOG_WARN;
|
||||
}
|
||||
else if (lev == "debug")
|
||||
{
|
||||
level |= LOG_DEBUG;
|
||||
}
|
||||
else if (lev == "info")
|
||||
{
|
||||
level |= LOG_INFO;
|
||||
}
|
||||
else if (lev == "function")
|
||||
{
|
||||
level |= LOG_FUNCTION;
|
||||
}
|
||||
else if (lev == "param")
|
||||
{
|
||||
level |= LOG_PARAM;
|
||||
}
|
||||
else if (lev == "logic")
|
||||
{
|
||||
level |= LOG_LOGIC;
|
||||
}
|
||||
else if (lev == "all")
|
||||
{
|
||||
level |= LOG_ALL;
|
||||
}
|
||||
else if (lev == "prefix")
|
||||
{
|
||||
level |= LOG_PREFIX_ALL;
|
||||
}
|
||||
else if (lev == "level_error")
|
||||
{
|
||||
level |= LOG_LEVEL_ERROR;
|
||||
}
|
||||
else if (lev == "level_warn")
|
||||
{
|
||||
level |= LOG_LEVEL_WARN;
|
||||
}
|
||||
else if (lev == "level_debug")
|
||||
{
|
||||
level |= LOG_LEVEL_DEBUG;
|
||||
}
|
||||
else if (lev == "level_info")
|
||||
{
|
||||
level |= LOG_LEVEL_INFO;
|
||||
}
|
||||
else if (lev == "level_function")
|
||||
{
|
||||
level |= LOG_LEVEL_FUNCTION;
|
||||
}
|
||||
else if (lev == "level_param")
|
||||
{
|
||||
level |= LOG_LEVEL_PARAM;
|
||||
}
|
||||
else if (lev == "level_logic")
|
||||
{
|
||||
level |= LOG_LEVEL_LOGIC;
|
||||
}
|
||||
else if (lev == "level_all")
|
||||
{
|
||||
level |= LOG_LEVEL_ALL;
|
||||
}
|
||||
} while (next_lev != std::string::npos);
|
||||
}
|
||||
bool found = false;
|
||||
if (component == "*")
|
||||
{
|
||||
found = true;
|
||||
LogComponentEnableAll ((enum LogLevel)level);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentList *components = GetComponentList ();
|
||||
for (ComponentListI i = components->begin ();
|
||||
i != components->end ();
|
||||
i++)
|
||||
{
|
||||
if (i->first.compare (component) == 0)
|
||||
{
|
||||
found = true;
|
||||
|
||||
i->second->Enable ((enum LogLevel)level);
|
||||
break;
|
||||
}
|
||||
cur_lev = next_lev + 1;
|
||||
next_lev = tmp.find ("|", cur_lev);
|
||||
std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
|
||||
if (lev == "error")
|
||||
{
|
||||
level |= LOG_ERROR;
|
||||
}
|
||||
else if (lev == "warn")
|
||||
{
|
||||
level |= LOG_WARN;
|
||||
}
|
||||
else if (lev == "debug")
|
||||
{
|
||||
level |= LOG_DEBUG;
|
||||
}
|
||||
else if (lev == "info")
|
||||
{
|
||||
level |= LOG_INFO;
|
||||
}
|
||||
else if (lev == "function")
|
||||
{
|
||||
level |= LOG_FUNCTION;
|
||||
}
|
||||
else if (lev == "param")
|
||||
{
|
||||
level |= LOG_PARAM;
|
||||
}
|
||||
else if (lev == "logic")
|
||||
{
|
||||
level |= LOG_LOGIC;
|
||||
}
|
||||
else if (lev == "all")
|
||||
{
|
||||
level |= LOG_ALL;
|
||||
}
|
||||
else if (lev == "prefix")
|
||||
{
|
||||
level |= LOG_PREFIX_ALL;
|
||||
}
|
||||
else if (lev == "level_error")
|
||||
{
|
||||
level |= LOG_LEVEL_ERROR;
|
||||
}
|
||||
else if (lev == "level_warn")
|
||||
{
|
||||
level |= LOG_LEVEL_WARN;
|
||||
}
|
||||
else if (lev == "level_debug")
|
||||
{
|
||||
level |= LOG_LEVEL_DEBUG;
|
||||
}
|
||||
else if (lev == "level_info")
|
||||
{
|
||||
level |= LOG_LEVEL_INFO;
|
||||
}
|
||||
else if (lev == "level_function")
|
||||
{
|
||||
level |= LOG_LEVEL_FUNCTION;
|
||||
}
|
||||
else if (lev == "level_param")
|
||||
{
|
||||
level |= LOG_LEVEL_PARAM;
|
||||
}
|
||||
else if (lev == "level_logic")
|
||||
{
|
||||
level |= LOG_LEVEL_LOGIC;
|
||||
}
|
||||
else if (lev == "level_all")
|
||||
{
|
||||
level |= LOG_LEVEL_ALL;
|
||||
}
|
||||
} while (next_lev != std::string::npos);
|
||||
|
||||
Enable ((enum LogLevel)level);
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
allFound = false;
|
||||
}
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
break;
|
||||
@@ -250,26 +199,9 @@ LogComponentEnableEnvVar (void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allFound)
|
||||
{
|
||||
isFirstLog = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
LogComponent::LogComponent (char const * name)
|
||||
: m_levels (0), m_name (name)
|
||||
{
|
||||
ComponentList *components = GetComponentList ();
|
||||
for (ComponentListI i = components->begin ();
|
||||
i != components->end ();
|
||||
i++)
|
||||
{
|
||||
NS_ASSERT (i->first != name);
|
||||
}
|
||||
components->push_back (std::make_pair (name, this));
|
||||
}
|
||||
|
||||
bool
|
||||
LogComponent::IsEnabled (enum LogLevel level) const
|
||||
|
||||
@@ -34,6 +34,21 @@
|
||||
* messages, use the ns3::LogComponentEnable
|
||||
* function or use the NS_LOG environment variable and
|
||||
* ns3::LogComponentEnableEnvVar
|
||||
*
|
||||
* Use the environment variable NS_LOG to define a ';'-separated list of
|
||||
* logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
|
||||
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
|
||||
* NS_LOG=* will enable all available log components.
|
||||
*
|
||||
* For each component, the "debug" log level is enabled by default
|
||||
* but more components can be enabled selectively with the following
|
||||
* syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
|
||||
* This example would enable the 'func', 'param', and 'warn' log
|
||||
* levels for 'Component1' and the 'error' and 'debug' log levels
|
||||
* for 'Component2'. The wildcard can be used here as well. For example
|
||||
* NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
|
||||
* prints with the component and function names.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -94,7 +109,7 @@
|
||||
if (g_log.IsEnabled (level)) \
|
||||
{ \
|
||||
std::clog << g_log.Name () << ":" << __FUNCTION__ << \
|
||||
"(): " << std::endl; \
|
||||
"()" << std::endl; \
|
||||
} \
|
||||
} \
|
||||
while (false)
|
||||
@@ -179,28 +194,6 @@ enum LogLevel {
|
||||
#endif
|
||||
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
/**
|
||||
* \brief Enable the logging output based on an environment variable.
|
||||
*
|
||||
* Use the environment variable NS_LOG to define a ';'-separated list of
|
||||
* logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
|
||||
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
|
||||
* NS_LOG=* will enable all available log components.
|
||||
*
|
||||
* For each component, the "debug" log level is enabled by default
|
||||
* but more components can be enabled selectively with the following
|
||||
* syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
|
||||
* This example would enable the 'func', 'param', and 'warn' log
|
||||
* levels for 'Component1' and the 'error' and 'debug' log levels
|
||||
* for 'Component2'. The wildcard can be used here as well. For example
|
||||
* NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
|
||||
* prints with the component and function names.
|
||||
*
|
||||
* The list of available log components can be printed on stdout
|
||||
* with the NS_LOG=print-list syntax.
|
||||
*/
|
||||
void LogComponentEnableEnvVar (void);
|
||||
|
||||
/**
|
||||
* \param name a log component name
|
||||
* \param level a logging level
|
||||
@@ -222,7 +215,6 @@ enum LogLevel {
|
||||
*/
|
||||
void LogComponentEnableAll (enum LogLevel level);
|
||||
#else
|
||||
#define LogComponentEnableEnvVar()
|
||||
#define LogComponentEnable(a,b)
|
||||
#define LogComponentEnableAll(a)
|
||||
#endif
|
||||
@@ -259,11 +251,6 @@ void LogComponentDisableAll (enum LogLevel level);
|
||||
* \ingroup logging
|
||||
*
|
||||
* Print the list of logging messages available.
|
||||
* The output of this function can be obtained by setting
|
||||
* the NS_LOG environment variable to the special value
|
||||
* 'print-list'.
|
||||
*
|
||||
* For example: NS_LOG=print-list
|
||||
*/
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
void LogComponentPrintList (void);
|
||||
@@ -276,6 +263,7 @@ void LogComponentPrintList (void);
|
||||
class LogComponent {
|
||||
public:
|
||||
LogComponent (char const *name);
|
||||
void EnvVarCheck (char const *name);
|
||||
bool IsEnabled (enum LogLevel level) const;
|
||||
bool IsNoneEnabled (void) const;
|
||||
void Enable (enum LogLevel level);
|
||||
|
||||
Reference in New Issue
Block a user