The ns-3 logging facility can be used to monitor or debug the progress of simulation programs. Logging output can be enabled by program statements in your main() program or by the use of the NS_LOG environment variable.
Logging statements are not compiled into optimized builds of ns-3. To use logging, one must build the (default) debug build of ns-3.
The project makes no guarantee about whether logging output will remain the same over time. Users are cautioned against building simulation output frameworks on top of logging code, as the output and the way the output is enabled may change over time.
ns-3 logging statements are typically used to log various program execution events, such as the occurrence of simulation events or the use of a particular function.
For example, this code snippet is from Ipv4L3Protocol::IsDestinationAddress():
if (address == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("For me (interface broadcast address)");
return true;
}
If logging has been enabled for the Ipv4L3Protocol component at a level of LOGIC or above (see below about logging levels), the statement will be printed out; otherwise, it will be suppressed.
The following levels are defined; each level will enable the levels above it, with the ALL level being most verbose:
A special logging level will cause logging output to unconditionally appear on std::clog, regardless of whether the user has explicitly enabled logging. This macro, NS_LOG_UNCOND(), can be used like a kind of printf() in your code. An example can be found in scratch/scratch-simulator.cc:
NS_LOG_UNCOND ("Scratch Simulator");
This section still needs documentation; bug 1496 is open on this:
$ NS_LOG="*=all|prefix_all" ./waf --run scratch-simulator
Scratch Simulator
ScratchSimulator:main(): [ERROR] error message
ScratchSimulator:main(): [WARN] warn message
ScratchSimulator:main(): [DEBUG] debug message
ScratchSimulator:main(): [INFO] info message
ScratchSimulator:main(function)
ScratchSimulator:main(): [LOGIC] logic message
There are two ways that users typically control logging output. The first is by setting an NS_LOG environment variable; e.g.:
$ NS_LOG="*" ./waf --run first
will run the first tutorial program with all logging output. This can be made more granular by selecting individual components:
$ NS_LOG="Ipv4L3Protocol" ./waf --run first
The second way to enable this is to use explicit statements in your program, such as in the first tutorial program:
int
main (int argc, char *argv[])
{
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
...
Some helpers have special methods to enable the logging of all components in a module (across different compilation units, but logically grouped together such as the ns-3 wifi code:
WifiHelper wifiHelper;
wifiHelper.EnableLogComponents ();
To add logging to your code, please follow the below steps:
Create a unique string identifier (usually based on the name of the file and/or class defined within the file) and register it with a macro call such as follows:
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
namespace ns3 {
...
The macro was carefully written to permit inclusion either within or outside of namespace ns3, and usage will vary across the codebase, but the original intent was to register this outside of namespace ns3.
There are a couple of guidelines on this: