ns-3中的数据跟踪与采集——Logging系统

ns-3中的数据跟踪与采集——Logging系统

在很多大型系统中,都会提供一种基于控制台的消息记录模块,用来向用户即时地反馈命令的执行情况或者系统的运行情况,ns-3采用这种机制实现了一种可选的多等级的消息记录模块——Logging系统。

Logging系统提供七个等级,由低到高依次为:

日志级别 含义
LOG_ERROR 记录错误信息
LOG_WARN 记录警告信息
LOG_DEBUG 记录一些调试信息
LOG_INFO 记录一些程序相关的信息
LOG_FUNCTION 当函数被调用时,该调用信息就被记录
LOG_LOGIC 对于整体逻辑的描述
LOG_ALL 包含上述所有信息

每一个高等级记录的信息都包含低等级所要记录的信息。
在使用时,不同等级之间可以单独设置也可以累加设置,可以通过修改环境变量NS_LOG设置也可以通过函数调用在脚本设置

另,每一个LOG_TYPE都等价与一个LOG_LEVEL_TYPE,例如LOG_FUNCTION和LOG_TYPE_FUNCTION的功能是一样的。

Logging系统在ns-3中主要有2种应用:一是通过输出网络组件内部模块执行过程来方便用户理解,二是通过输出简单的调试信息来方便用户调试。

1)有效化系统记录模块(通过函数调用在脚本设置等级)

在运行脚本first.cc时的结果为:
first.cc运行结果
这些信息是怎么得来的?其实在first.cc的分析中已经指出,这些信息来自一下两行语句:

  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

LogComponentEnable()函数的作用是使记录模块有效。

第一个参数为用户要注册的具有一定行为能力的类组件字符串。在该例子中,需要得到的是客户端和服务器端所运行应用程序的行为信息,因此使用的参数为UdpEchoClientApplication和UdpEchoServerApplication,这两个类正是该脚本中用到的程序类。

第二个参数是设置该显示的等级,这里设置的都是LOG_LEVEL_INFO。可以修改这个等级参数来得到所需要的信息,等级越高信息越详细。若把此处的等级改为LOG_LEVEL_FUNCTION,则运行结果如下:
修改后的运行结果可以看出除了包含在LOG_LEVEL_INFO等级下的信息外,还得到了一些关于函数调用的信息。这样就验证了高等级包含低等级所记录的信息。但并不能说记录等级越高越好,因为等级越高输出的信息量越大,处理起来就复杂相反,如果低等级的记录能够满足需求,应该尽量使用低等级。

2)通过环境变量修改系统等级

通过修改脚本代码可以修改Logging等级,但是每一次都要修改代码非常不方便。其实,Logging系统模块提供了通过修改环境变量的方法来修改记录系统等级。**使用方法:在编译脚本前使用export命令修改NS_LOG的值。**仍以first.cc为例,可以做:

export 'NS_LOG=UdpEchoClientApplication=level_all:
               UdpEchoServerApplication=level_all'

export是命令,第一个“=”为赋值符号,“=”左面NS_LOG为要设置的环境变量,“=”右面是要赋值给左值的字符串。注意UdpEchoClientApplication=level_all等号右边是小写字母和程序脚本中使用的大写字母不同。level_all等级意味着要显示全部的调用信息。在此基础上运行first.cc脚本结果如下:
level_all运行结果

3)添加附加前缀

很多情况下,用户不仅想要了解每一个信息,还想知道信息是何时由什么函数产生的,以便去调试代码以达到想要的效果。例如上面运行结果中At time 2s client sent 1024 bytes to 10.1.1.2 port 9这条信息是由哪个函数在什么时间产生的。在这种情况下,可以为NS_LOG环境变量增加更多的字符串参数来达到这一效果。

①添加prefix_func 来为每一条信息显示其产生函数,将会发现每一条信息前都会有一个函数前缀。具体操作如下:

export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
               UdpEchoServerApplication=level_all|prefix_func'

结果如下:
有函数前缀的结果
②添加prefix_time 来分析仿真程序中各个函数调用的时间以及各个事件的发生时间,将会发现每一条信息前都会显示其产生时间。具体操作如下:

export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:
               UdpEchoServerApplication=level_all|prefix_func|prefix_time'

结果如下:
有时间的结果

4)自定义Logging代码

上面所有关于Logging模块的知识全部是系统定义好的,但在实际写仿真脚本时难免需要输出一些自定义的信息。下面介绍自定义Logging代码的实现。

在first.cc脚本中有这样一行代码:

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

在此之前这行代码看起来似乎没有任何意义,其实不然,这句代码的作用是用来向ns-3系统注册一个名为“FirstScriptExample”的记录组件。只有定义了记录组件,才能在仿真脚本中使用Logging系统来自定义输出语句。下面在first.cc中添加语句 NS_LOG_INFO("Creating Topology");(这条语句要在创建节点之前添加),如下图所示:
添加语句
接下来要激活有效化这个自定义的记录组件,方法和激活系统定义好的组件方法一样,可以在脚本中添加代码,也可以通过环境变量的方法:
①LogComponentEnable (“FirstScriptExample”, LOG_LEVEL_INFO);
②export NS_LOG=FirstScriptExample=info
推荐选用第二种方法(环境变量的方法)。
采用该方法再次运行脚本,就会发现输出信息中多了一个“Creating Topology”,如下:
新的运行结果

在使用自定义Logging系统时,要注意以下两点:
①一定要在使用前向系统注册自己的组件。
②要激活已经注册好的组件,建议使用环境变量的方法。

猜你喜欢

转载自blog.csdn.net/qq_31676673/article/details/88668930