554 lines
16 KiB
C++
554 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2006,2007 INRIA
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation;
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
|
*/
|
|
|
|
#ifndef NS3_LOG_H
|
|
#define NS3_LOG_H
|
|
|
|
#include "log-macros-disabled.h"
|
|
#include "log-macros-enabled.h"
|
|
#include "node-printer.h"
|
|
#include "time-printer.h"
|
|
|
|
#include <iostream>
|
|
#include <stdint.h>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
/**
|
|
* \file
|
|
* \ingroup logging
|
|
* Debug message logging
|
|
*/
|
|
|
|
/**
|
|
* \ingroup debugging
|
|
* \defgroup logging Logging
|
|
*
|
|
* \brief Logging functions and macros
|
|
*
|
|
* LOG functionality: macros which allow developers to
|
|
* send information to the \c std::clog output stream.
|
|
*
|
|
* All logging messages are disabled by default. To enable selected logging
|
|
* messages, use the ns3::LogComponentEnable
|
|
* function or use the NS_LOG environment variable
|
|
*
|
|
* Use the environment variable NS_LOG to define a ':'-separated list of
|
|
* logging components to enable. For example (using bash syntax),
|
|
* \code
|
|
* $ NS_LOG="OlsrAgent" ./ns3 run ...
|
|
* \endcode
|
|
* would enable one component at all log levels.
|
|
* \code
|
|
* $NS_LOG="OlsrAgent:Ipv4L3Protocol" ./ns3 run ...
|
|
* \endcode
|
|
* would enable two components, at all log levels, etc.
|
|
* \c NS_LOG="*" will enable all available log components at all levels.
|
|
*
|
|
* To control more selectively the log levels for each component, use
|
|
* this syntax:
|
|
* \code
|
|
* $ NS_LOG='Component1=func|warn:Component2=error|debug'
|
|
* \endcode
|
|
* This example would enable the \c func, and \c warn log
|
|
* levels for 'Component1' and the \c error and \c debug log levels
|
|
* for 'Component2'. The wildcard '*' can be used here as well. For example
|
|
* \c NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
|
|
* prints with the component and function names.
|
|
*
|
|
* A note on NS_LOG_FUNCTION() and NS_LOG_FUNCTION_NOARGS():
|
|
* generally, use of (at least) NS_LOG_FUNCTION(this) is preferred,
|
|
* with the any function parameters added:
|
|
* \code
|
|
* NS_LOG_FUNCTION (this << arg1 << args);
|
|
* \endcode
|
|
* Use NS_LOG_FUNCTION_NOARGS() only in static functions with no arguments.
|
|
*/
|
|
/** @{ */
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
/**
|
|
* Logging severity classes and levels.
|
|
*/
|
|
enum LogLevel
|
|
{
|
|
LOG_NONE = 0x00000000, //!< No logging.
|
|
|
|
LOG_ERROR = 0x00000001, //!< Serious error messages only.
|
|
LOG_LEVEL_ERROR = 0x00000001, //!< LOG_ERROR and above.
|
|
|
|
LOG_WARN = 0x00000002, //!< Warning messages.
|
|
LOG_LEVEL_WARN = 0x00000003, //!< LOG_WARN and above.
|
|
|
|
LOG_DEBUG = 0x00000004, //!< Rare ad-hoc debug messages.
|
|
LOG_LEVEL_DEBUG = 0x00000007, //!< LOG_DEBUG and above.
|
|
|
|
LOG_INFO = 0x00000008, //!< Informational messages (e.g., banners).
|
|
LOG_LEVEL_INFO = 0x0000000f, //!< LOG_INFO and above.
|
|
|
|
LOG_FUNCTION = 0x00000010, //!< Function tracing.
|
|
LOG_LEVEL_FUNCTION = 0x0000001f, //!< LOG_FUNCTION and above.
|
|
|
|
LOG_LOGIC = 0x00000020, //!< Control flow tracing within functions.
|
|
LOG_LEVEL_LOGIC = 0x0000003f, //!< LOG_LOGIC and above.
|
|
|
|
LOG_ALL = 0x0fffffff, //!< Print everything.
|
|
LOG_LEVEL_ALL = LOG_ALL, //!< Print everything.
|
|
|
|
LOG_PREFIX_FUNC = 0x80000000, //!< Prefix all trace prints with function.
|
|
LOG_PREFIX_TIME = 0x40000000, //!< Prefix all trace prints with simulation time.
|
|
LOG_PREFIX_NODE = 0x20000000, //!< Prefix all trace prints with simulation node.
|
|
LOG_PREFIX_LEVEL = 0x10000000, //!< Prefix all trace prints with log level (severity).
|
|
LOG_PREFIX_ALL = 0xf0000000 //!< All prefixes.
|
|
};
|
|
|
|
/**
|
|
* Enable the logging output associated with that log component.
|
|
*
|
|
* The logging output can be later disabled with a call
|
|
* to ns3::LogComponentDisable.
|
|
*
|
|
* Same as running your program with the NS_LOG environment
|
|
* variable set as NS_LOG='name=level'.
|
|
*
|
|
* \param [in] name The log component name.
|
|
* \param [in] level The logging level.
|
|
*/
|
|
void LogComponentEnable(const std::string& name, LogLevel level);
|
|
|
|
/**
|
|
* Enable the logging output for all registered log components.
|
|
*
|
|
* Same as running your program with the NS_LOG environment
|
|
* variable set as NS_LOG='*=level'
|
|
*
|
|
* \param [in] level The logging level.
|
|
*/
|
|
void LogComponentEnableAll(LogLevel level);
|
|
|
|
/**
|
|
* Disable the logging output associated with that log component.
|
|
*
|
|
* The logging output can be later re-enabled with a call
|
|
* to LogComponentEnable.
|
|
*
|
|
* \param [in] name The log component name.
|
|
* \param [in] level The logging level.
|
|
*/
|
|
void LogComponentDisable(const std::string& name, LogLevel level);
|
|
|
|
/**
|
|
* Disable all logging for all components.
|
|
*
|
|
* \param [in] level The logging level.
|
|
*/
|
|
void LogComponentDisableAll(LogLevel level);
|
|
|
|
} // namespace ns3
|
|
|
|
/**
|
|
* Define a Log component with a specific name.
|
|
*
|
|
* This macro should be used at the top of every file in which you want
|
|
* to use the NS_LOG macro. This macro defines a new
|
|
* "log component" which can be later selectively enabled
|
|
* or disabled with the ns3::LogComponentEnable and
|
|
* ns3::LogComponentDisable functions or with the NS_LOG
|
|
* environment variable.
|
|
*
|
|
* LogComponent names should be simple string tokens, _i.e._,
|
|
* "ArfWifiManager", not "ns3::ArfWifiManager".
|
|
*
|
|
* This macro should be placed within namespace ns3. If functions
|
|
* outside of namespace ns3 require access to logging, the preferred
|
|
* solution is to add the following 'using' directive at file scope,
|
|
* outside of namespace ns3, and after the inclusion of
|
|
* NS_LOG_COMPONENT_DEFINE, such as follows:
|
|
* \code
|
|
* namespace ns3 {
|
|
* NS_LOG_COMPONENT_DEFINE ("...");
|
|
*
|
|
* // Definitions within the ns3 namespace
|
|
*
|
|
* } // namespace ns3
|
|
*
|
|
* using ns3::g_log;
|
|
*
|
|
* // Further definitions outside of the ns3 namespace
|
|
*\endcode
|
|
*
|
|
* \param [in] name The log component name.
|
|
*/
|
|
#define NS_LOG_COMPONENT_DEFINE(name) \
|
|
static ns3::LogComponent g_log = ns3::LogComponent(name, __FILE__)
|
|
|
|
/**
|
|
* Define a logging component with a mask.
|
|
*
|
|
* See LogComponent().
|
|
*
|
|
* \param [in] name The log component name.
|
|
* \param [in] mask The default mask.
|
|
*/
|
|
#define NS_LOG_COMPONENT_DEFINE_MASK(name, mask) \
|
|
static ns3::LogComponent g_log = ns3::LogComponent(name, __FILE__, mask)
|
|
|
|
/**
|
|
* Declare a reference to a Log component.
|
|
*
|
|
* This macro should be used in the declaration of template classes
|
|
* to allow their methods (defined in an header file) to make use of
|
|
* the NS_LOG_* macros. This macro should be used in the private
|
|
* section to prevent subclasses from using the same log component
|
|
* as the base class.
|
|
*/
|
|
#define NS_LOG_TEMPLATE_DECLARE LogComponent& g_log
|
|
|
|
/**
|
|
* Initialize a reference to a Log component.
|
|
*
|
|
* This macro should be used in the constructor of template classes
|
|
* to allow their methods (defined in an header file) to make use of
|
|
* the NS_LOG_* macros.
|
|
*
|
|
* \param [in] name The log component name.
|
|
*/
|
|
#define NS_LOG_TEMPLATE_DEFINE(name) g_log(GetLogComponent(name))
|
|
|
|
/**
|
|
* Declare and initialize a reference to a Log component.
|
|
*
|
|
* This macro should be used in static template methods to allow their
|
|
* methods (defined in an header file) to make use of the NS_LOG_* macros.
|
|
*
|
|
* \param [in] name The log component name.
|
|
*/
|
|
#define NS_LOG_STATIC_TEMPLATE_DEFINE(name) \
|
|
static LogComponent& g_log [[maybe_unused]] = GetLogComponent(name)
|
|
|
|
/**
|
|
* Use \ref NS_LOG to output a message of level LOG_ERROR.
|
|
*
|
|
* \param [in] msg The message to log.
|
|
*/
|
|
#define NS_LOG_ERROR(msg) NS_LOG(ns3::LOG_ERROR, msg)
|
|
|
|
/**
|
|
* Use \ref NS_LOG to output a message of level LOG_WARN.
|
|
*
|
|
* \param [in] msg The message to log.
|
|
*/
|
|
#define NS_LOG_WARN(msg) NS_LOG(ns3::LOG_WARN, msg)
|
|
|
|
/**
|
|
* Use \ref NS_LOG to output a message of level LOG_DEBUG.
|
|
*
|
|
* \param [in] msg The message to log.
|
|
*/
|
|
#define NS_LOG_DEBUG(msg) NS_LOG(ns3::LOG_DEBUG, msg)
|
|
|
|
/**
|
|
* Use \ref NS_LOG to output a message of level LOG_INFO.
|
|
*
|
|
* \param [in] msg The message to log.
|
|
*/
|
|
#define NS_LOG_INFO(msg) NS_LOG(ns3::LOG_INFO, msg)
|
|
|
|
/**
|
|
* Use \ref NS_LOG to output a message of level LOG_LOGIC
|
|
*
|
|
* \param [in] msg The message to log.
|
|
*/
|
|
#define NS_LOG_LOGIC(msg) NS_LOG(ns3::LOG_LOGIC, msg)
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
/**
|
|
* Print the list of logging messages available.
|
|
* Same as running your program with the NS_LOG environment
|
|
* variable set as NS_LOG=print-list
|
|
*/
|
|
void LogComponentPrintList();
|
|
|
|
/**
|
|
* Set the TimePrinter function to be used
|
|
* to prepend log messages with the simulation time.
|
|
*
|
|
* The default is DefaultTimePrinter().
|
|
*
|
|
* \param [in] lp The TimePrinter function.
|
|
*/
|
|
void LogSetTimePrinter(TimePrinter lp);
|
|
/**
|
|
* Get the LogTimePrinter function currently in use.
|
|
* \returns The current LogTimePrinter function.
|
|
*/
|
|
TimePrinter LogGetTimePrinter();
|
|
|
|
/**
|
|
* Set the LogNodePrinter function to be used
|
|
* to prepend log messages with the node id.
|
|
*
|
|
* The default is DefaultNodePrinter().
|
|
*
|
|
* \param [in] np The LogNodePrinter function.
|
|
*/
|
|
void LogSetNodePrinter(NodePrinter np);
|
|
/**
|
|
* Get the LogNodePrinter function currently in use.
|
|
* \returns The current LogNodePrinter function.
|
|
*/
|
|
NodePrinter LogGetNodePrinter();
|
|
|
|
/**
|
|
* A single log component configuration.
|
|
*/
|
|
class LogComponent
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* \param [in] name The user-visible name for this component.
|
|
* \param [in] file The source code file which defined this LogComponent.
|
|
* \param [in] mask LogLevels blocked for this LogComponent. Blocking
|
|
* a log level helps prevent recursion by logging in
|
|
* functions which help implement the logging facility.
|
|
*/
|
|
LogComponent(const std::string& name, const std::string& file, const LogLevel mask = LOG_NONE);
|
|
/**
|
|
* Check if this LogComponent is enabled for \c level
|
|
*
|
|
* \param [in] level The level to check for.
|
|
* \return \c true if we are enabled at \c level.
|
|
*/
|
|
bool IsEnabled(const LogLevel level) const;
|
|
/**
|
|
* Check if all levels are disabled.
|
|
*
|
|
* \return \c true if all levels are disabled.
|
|
*/
|
|
bool IsNoneEnabled() const;
|
|
/**
|
|
* Enable this LogComponent at \c level
|
|
*
|
|
* \param [in] level The LogLevel to enable.
|
|
*/
|
|
void Enable(const LogLevel level);
|
|
/**
|
|
* Disable logging at \c level for this LogComponent.
|
|
*
|
|
* \param [in] level The LogLevel to disable.
|
|
*/
|
|
void Disable(const LogLevel level);
|
|
/**
|
|
* Get the name of this LogComponent.
|
|
*
|
|
* \return The name of this LogComponent.
|
|
*/
|
|
std::string Name() const;
|
|
/**
|
|
* Get the compilation unit defining this LogComponent.
|
|
* \returns The file name.
|
|
*/
|
|
std::string File() const;
|
|
/**
|
|
* Get the string label for the given LogLevel.
|
|
*
|
|
* \param [in] level The LogLevel to get the label for.
|
|
* \return The string label for \c level.
|
|
*/
|
|
static std::string GetLevelLabel(const LogLevel level);
|
|
/**
|
|
* Prevent the enabling of a specific LogLevel.
|
|
*
|
|
* \param [in] level The LogLevel to block.
|
|
*/
|
|
void SetMask(const LogLevel level);
|
|
|
|
/**
|
|
* LogComponent name map.
|
|
*
|
|
* \internal
|
|
* This should really be considered an internal API.
|
|
* It is exposed here to allow print-introspected-doxygen.cc
|
|
* to generate a list of all LogComponents.
|
|
*/
|
|
using ComponentList = std::unordered_map<std::string, LogComponent*>;
|
|
|
|
/**
|
|
* Get the list of LogComponents.
|
|
*
|
|
* \internal
|
|
* This should really be considered an internal API.
|
|
* It is exposed here to allow print-introspected-doxygen.cc
|
|
* to generate a list of all LogComponents.
|
|
*
|
|
* \returns The list of LogComponents.
|
|
*/
|
|
static ComponentList* GetComponentList();
|
|
|
|
private:
|
|
/**
|
|
* Parse the `NS_LOG` environment variable for options relating to this
|
|
* LogComponent.
|
|
*/
|
|
void EnvVarCheck();
|
|
|
|
int32_t m_levels; //!< Enabled LogLevels.
|
|
int32_t m_mask; //!< Blocked LogLevels.
|
|
std::string m_name; //!< LogComponent name.
|
|
std::string m_file; //!< File defining this LogComponent.
|
|
|
|
}; // class LogComponent
|
|
|
|
/**
|
|
* Get the LogComponent registered with the given name.
|
|
*
|
|
* \param [in] name The name of the LogComponent.
|
|
* \return a reference to the requested LogComponent
|
|
*/
|
|
LogComponent& GetLogComponent(const std::string name);
|
|
|
|
/**
|
|
* Insert `, ` when streaming function arguments.
|
|
*/
|
|
class ParameterLogger
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* \param [in] os Underlying output stream.
|
|
*/
|
|
ParameterLogger(std::ostream& os);
|
|
|
|
/**
|
|
* Write a function parameter on the output stream,
|
|
* separating parameters after the first by `,` strings.
|
|
* Overload for arithmetic types (integral type or floating point type),
|
|
* enabling the parameter to be passed by value.
|
|
*
|
|
* \param [in] param The function parameter.
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <typename T, typename U = std::enable_if_t<std::is_arithmetic_v<T>>>
|
|
ParameterLogger& operator<<(T param);
|
|
|
|
/**
|
|
* Write a function parameter on the output stream,
|
|
* separating parameters after the first by `,` strings.
|
|
* Overload for non-arithmetic types, enabling the parameter
|
|
* to be passed by reference.
|
|
*
|
|
* \param [in] param The function parameter.
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <typename T, typename U = std::enable_if_t<!std::is_arithmetic_v<T>>>
|
|
ParameterLogger& operator<<(const T& param);
|
|
|
|
/**
|
|
* Overload for vectors, to print each element.
|
|
*
|
|
* \param [in] vector The vector of parameters
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <typename T>
|
|
ParameterLogger& operator<<(const std::vector<T>& vector);
|
|
|
|
/**
|
|
* Overload for C-strings.
|
|
*
|
|
* \param [in] param The C-string
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
ParameterLogger& operator<<(const char* param);
|
|
|
|
private:
|
|
/** Add `, ` before every parameter after the first. */
|
|
void CommaRest();
|
|
|
|
bool m_first{true}; //!< First argument flag, doesn't get `, `.
|
|
std::ostream& m_os; //!< Underlying output stream.
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
ParameterLogger&
|
|
ParameterLogger::operator<<(T param)
|
|
{
|
|
CommaRest();
|
|
m_os << param;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
ParameterLogger&
|
|
ParameterLogger::operator<<(const T& param)
|
|
{
|
|
CommaRest();
|
|
m_os << param;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
ParameterLogger&
|
|
ParameterLogger::operator<<(const std::vector<T>& vector)
|
|
{
|
|
for (const auto& i : vector)
|
|
{
|
|
*this << i;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Specialization for strings.
|
|
* \param [in] param The function parameter.
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <>
|
|
ParameterLogger& ParameterLogger::operator<< <std::string>(const std::string& param);
|
|
|
|
/**
|
|
* Specialization for int8_t.
|
|
* \param [in] param The function parameter.
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <>
|
|
ParameterLogger& ParameterLogger::operator<< <int8_t>(const int8_t param);
|
|
|
|
/**
|
|
* Specialization for uint8_t.
|
|
* \param [in] param The function parameter.
|
|
* \return This ParameterLogger, so it's chainable.
|
|
*/
|
|
template <>
|
|
ParameterLogger& ParameterLogger::operator<< <uint8_t>(const uint8_t param);
|
|
|
|
} // namespace ns3
|
|
|
|
/**@}*/ // \ingroup logging
|
|
|
|
#endif /* NS3_LOG_H */
|