LTE Manual ——Logging(翻译)

LTE Manual ——Logging(翻译)

(本文为个人学习笔记,如有不当的地方,欢迎指正!)

9 Logging

ns-3 日志功能可以用于监测或调试仿真程序的进展。日志输出可以通过 main()  程序中的语句或通过使用 NS_LOG 环境变量来启用。

日志语句并没有编译成 ns-3 的优化版本(Logging statements are not compiled into optimized builds of ns-3)。为了使用日志,必须 build  ns-3  的默认调试 build 。

这个项目并不能保证日志输出会随时间而保持不变。提醒用户不要在日志代码顶部建立仿真输出框架,因为输出和启用输出的方式可能会随时间改变。

9.1 概述

ns-3 日志语句通常用于记录各种程序执行事件,例如仿真事件的发生或特定函数的使用。

例如,这个代码片段来自  Ipv4L3Protocol::IsDestinationAddress():

if (address == iaddr.GetBroadcast ())
  {
    NS_LOG_LOGIC ("For me (interface broadcast address)");
    return true;
  }

如果 Ipv4L3Protocol component 在 大于或等于 LOGIC severity 级别上开启日志功能,那么日志声明会被打印输出;否则会被抑制。

9.1.1 启用输出

用户通常使用两种方式控制日志输出。第一种是设置 NS_LOG 环境变量;例如:

$ NS_LOG="*" ./waf --run first

上述代码将运行 first tutorial 程序,得到所有的日志输出。 (下面将讨论特定的 NS_LOG 格式。)

通过选择单独的组件,日志输出可以变得更详细:

$ NS_LOG="Ipv4L3Protocol" ./waf --run first

输出可以进一步根据前缀选项来定制。

第二种启用输出的方式是在程序中使用明确的语句。例如在 first tutorial 程序中添加下列代码:

int main (int argc, char *argv[]){
  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
  ...

(下面讨论 LOG_LEVEL_INFO  的含义和其他可能的值。 )

9.1.2 NS_LOG 语法

NS_LOG 环境变量包含一系列日志组件和选项。日志组件通过冒号‘:‘ 隔开:

$ NS_LOG="<log-component>:<log-component>..."

每个日志组件选项通过标识符(flags)给定,位于日志组件后面:

$ NS_LOG="<log-component>=<option>|<option>...:<log-component>..."

选项(options)控制该组件的 severity 和 level ,以及是否应包含可选信息,例如仿真时间、仿真节点、函数名和象征性的 severity。

9.1.3 日志组件

通常来说,一个日志组件指的是单个的 .cc 源码文件,并且包含整个文件。

一些 helpers 有特殊的方法用于启用 一个模块中所有组件的日志功能,跨越不同的编译单位,但是逻辑上能组合在一起,例如  ns-3 wifi 代码:

WifiHelper wifiHelper;wifiHelper.EnableLogComponents ();

NS_LOG 日志组件通配符 ‘*‘ 启用所有的组件。

为了查看日志组件的定义,使用下面任何一个都可以:

$ NS_LOG="print-list" ./waf --run ...

$ NS_LOG="foo"  # a token not matching any log-component

第一种形式会打印输出所有日志组件的名称和启用标识符(flags);可以使用 scratch-simulator 去尝试。第二种形式会打印输出所有注册的日志组件,然后以一个错误退出。

9.1.4 Severity 和 Level 选项

单个的消息属于单个的 “severity class” ,由宏创建消息。在上述例子中, NS_LOG_LOGIC(..)  在 LOG_LOGIC severity 类中创建消息。

下列 severity 类定义为 enum 常量:

Severity Class Meaning
LOG_NONE The default, no logging
LOG_ERROR Serious error messages only
LOG_WARN Warning messages
LOG_DEBUG For use in debugging
LOG_INFO Informational
LOG_FUNCTION Function tracing
LOG_LOGIC Control flow tracing within functions

通常情况下, 人们想在给定的 severity 类和更高的类上看到消息。这可以通过定义包含的日志 “levels”来定义:

Level Meaning
LOG_LEVEL_ERROR Only LOG_ERROR severity class messages.
LOG_LEVEL_WARN LOG_WARN and above.
LOG_LEVEL_DEBUG LOG_DEBUG and above.
LOG_LEVEL_INFO LOG_INFO and above.
LOG_LEVEL_FUNCTION LOG_FUNCTION and above.
LOG_LEVEL_LOGIC LOG_LOGIC and above.
LOG_LEVEL_ALL All severity classes.
LOG_ALL Synonym for LOG_LEVEL_ALL

severity 类和 level 选项可以通过这些令牌在 NS_LOG 环境变量中给定 :

Class Level
error level_error
warn level_warn
debug level_debug
info level_info
function level_function
logic level_logic
  level_allall*

使用一个 severity 类令牌只能启用该 severity 的日志消息。 例如, NS_LOG="*=warn" 不会输出 severity 为  error 的消息。 NS_LOG="*=level_debug" 只会输出 severity 级别为 debug 及以上的日志消息。

severity 类和级别可以使用 `|’ 运算符进行结合: NS_LOG="*=level_warn|logic" 将输出 severity 级别为 error、 warn 和 logic 的消息。

NS_LOG severity 级别的通配符‘*‘ 与  all 的同义词为  level_all。

对于只在 NS_LOG 中提到的日志组件:

$ NS_LOG="<log-component>:..."

默认的 severity 为 LOG_LEVEL_ALL。

9.1.5 前缀选项

很多前缀有助于确定消息起源于何时何地,是什么 severity。

可用的前缀选项 (如同 enum 常量)有

Prefix Symbol Meaning
LOG_PREFIX_FUNC Prefix the name of the calling function.
LOG_PREFIX_TIME Prefix the simulation time.
LOG_PREFIX_NODE Prefix the node id.
LOG_PREFIX_LEVEL Prefix the severity level.
LOG_PREFIX_ALL Enable all prefixes.

下面简要描述前缀选项。

选项可以通过这些令牌在 NS_LOG 环境变量中给出:

Token Alternate
prefix_func func
prefix_time time
prefix_node node
prefix_level level
prefix_all all*

对于只在 NS_LOG 中提到的日志组件:

$ NS_LOG="<log-component>:..."

默认的前缀选项为 LOG_PREFIX_ALL。

(1)Severity 前缀

一个消息的 severity 类包含在选项 prefix_level 或 level 中。 例如, NS_LOG 的值启用所有日志组件 (‘*‘) 和所有 severity 类 (=all) 的日志功能,并且给 severity 类 (|prefix_level) 的消息添加前缀。

$ NS_LOG="*=all|prefix_level" ./waf --run scratch-simulator
Scratch Simulator
[ERROR] error message
[WARN] warn message
[DEBUG] debug message
[INFO] info message
[FUNCT] function message
[LOGIC] logic message

(2)时间前缀

仿真时间包含在选项 prefix_time 后 time 中,以秒为单位输出仿真时间。

(3)节点前缀

仿真节点 id 包含在选项 prefix_node 或 node 中。

(4)函数前缀

调用的函数名包含在选项 prefix_func 或  func 中。

(5)NS_LOG 通配符

日志组件通配符 ‘*‘ 表示启用所有的组件。 在特定的 severity 级别启用所有组件,可以使用 *=<severity> 。

severity 级别选项通配符 ‘*‘ 是  all 的同义词。 它必须出现在任何 ‘|‘ 字符分隔选项之前。为了启用所有的 severity 类,可以使用  <log-component>=*  或 <log-component>=*|<options>。

选项通配符 ‘*‘ 或令牌 all 开启所有的前缀选项,但是必须出现 ‘|‘ 字符的后面。为了启用特定的 severity 类或级别,以及所有的前缀,可以使用 <log-component>=<severity>|*。

结合选项通配符  ** 表示启用所有的 severities 和所有的前缀;例如, <log-component>=**。

uber-wildcard *** 表示启用所有日志组件的所有 severities 和所有前缀。这些都是等价的:

$ NS_LOG="***" ...      $ NS_LOG="*=all|*" ...        $ NS_LOG="*=*|all" ...
$ NS_LOG="*=**" ...    $ NS_LOG="*=level_all|*" ...  $ NS_LOG="*=*|prefix_all" ...
$ NS_LOG="*=*|*" ...

建议: 使用 NS_LOG="***",甚至连微不足道的 scratch-simulator 也会产生超过 46K 行的输出!

9.2 如何在代码中添加日志功能

在你的代码中添加日志功能非常重要:

(1)调用 namespace ns3 里的 NS_LOG_COMPONENT_DEFINE (...); 宏。

创建唯一的字符串标识符(通常基于文件名或文件内定义的类名),并使用宏调用注册它,例如:

namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");...

它会注册 Ipv4L3Protocol 为一个日志组件。

(宏是精心编写的,目的是允许其包含在命名空间 ns3 内部或外部,并且整个代码库的使用情况有所不同,但是最初的目的是在命名空间 ns3 的外部、在文件全局范围内注册宏。)

(2)在函数和函数体中添加日志声明(宏调用)。

9.2.1 Logging Macros(日志宏)

日志宏和相关的 severity 等级为

Severity Class Macro
LOG_NONE (none needed)
LOG_ERROR NS_LOG_ERROR (...);
LOG_WARN NS_LOG_WARN (...);
LOG_DEBUG NS_LOG_DEBUG (...);
LOG_INFO NS_LOG_INFO (...);
LOG_FUNCTION NS_LOG_FUNCTION (...);
LOG_LOGIC NS_LOG_LOGIC (...);

宏的功能为输出 streamers,因此发送 std::cout、使用  << 运算符连接的任何东西都是允许的:

void MyClass::Check (int value, char * item){
  NS_LOG_FUNCTION (this << arg << item);
  if (arg > 10)
    {
      NS_LOG_ERROR ("encountered bad value " << value <<
                    " while checking " << name << "!");
    }
  ...}

注意 NS_LOG_FUNCTION 自动会在每个参数间插入一个 ‘,‘ (comma-space) 分隔符。 这简化了函数参数的日志; 只是如同上述例子一样,将它们用 << 运算符进行连接。

9.2.2 Unconditional Logging(无条件的日志)

为方便起见, NS_LOG_UNCOND (...); 宏将总是记录它的参数,即使相关的日志组件没有在任何 severity 开启。 该宏不会使用任何前缀选项。注意日志只能在调试 builds 中启用;该宏不会在优化的 builds 中产生输出。

9.2.3 Guidelines(指南)

  • 使用 NS_LOG_FUNCTION (this << args...); 开始每个类的方法。 这会启用简单的函数调用  tracing 。
    • 除了: 不要记录运算符或明确的副本构造函数,因为这些会造成无穷递归和堆栈溢出。
    • 对于没有参数的方法,使用相同形式:NS_LOG_FUNCTION (this);
    • 对于静态函数:
      • 有参数的话,像往常一样使用 NS_LOG_FUNCTION (...); 。
      • 没有参数的话使用 NS_LOG_FUNCTION_NOARGS ();
  • NS_LOG_ERROR 用于错误严重的条件(可能使仿真执行无效)。
  • NS_LOG_WARN 用于不寻常的条件(可以纠正的)。 请给出问题本质以及如何纠正它的的有关提示。
  • NS_LOG_DEBUG  通常以一种特别的方式使用,目的是理解模型的执行。
  • NS_LOG_INFO 用于执行的附加信息,例如数据结构的大小(当添加/移除数据结构时)。
  • NS_LOG_LOGIC 用于 trace 一个函数的重要逻辑分支
  • 测试你的日志变化不会打破代码(break the code)。运行一些启用所有日志组件的示例程序(例如 NS_LOG="***")。
  • 使用显式类型转换,用于任何类型的变量 uint8_t 或 int8_t,例如, NS_LOG_LOGIC ("Variable i is " << static_cast<int> (i));。没有了 cast, 整数会被理解为一个字符,结果最可能不符合期望。这是一个有据可查的 C++ ‘feature’。

参考文献:https://www.nsnam.org/docs/manual/singlehtml/index.html#document-logging

时间: 2024-10-19 09:49:40

LTE Manual ——Logging(翻译)的相关文章

【socket编程】select manual page翻译

原文: select manual page 依赖的头文件 /* According to POSIX.1-2001, POSIX.1-2008 */ #include <sys/select.h> /* According to earlier standards */ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> 方法定义 int select(int nfds, fd_

trove manual installation 翻译

目标 此文件提供了一步一步的指导手动安装trove在一个现有OpenStack的环境为了开发. 该文件将不包括: OpenStack的设置 trove服务配置 要求 正在运行的OpenStack的环境是必需的,包括以下组件: 计算 (Nova) 镜像服务 (Glance) 身份认证 (Keystone) 一个网络组件 (either Neutron or Nova-Network) 如果你想在块存储卷提供数据存储,还需要块存储(Cinder) 如果你想要做的备份/恢复和复制,你也需要对象存储(S

如何使用Python的logging模块

几个学习连接: Python官方链接: https://docs.python.org/3.4/library/logging.html?highlight=logging 翻译(不过是2.3版本的) http://crazier9527.iteye.com/blog/290018 另外的一个人的总结: http://blog.csdn.net/fxjtoday/article/details/6307285 最好理解,写的最好的: http://bbs.chinaunix.net/thread

grep manual

名称    grep - 打印匹配的行语法:     grep [option] pattern [file...]     grep [option] [-e pattern] | -f file [file] 简介    grep 就是从文件或者标准输入中搜索你给的样式,默认把匹配到的行打印下来.    除grep外,还有其他两个程序可以用,egrep和fgrep.egrep等同于grep -E,frep等同于grep -F.直接使用egrep和fgrep的方法被丢弃了,提供这两个命令时是为

MySQL - Show Processlist 整理(转)

原文来源:MySQL 5.5 Reference Manual 部分翻译取自:<MySQL_5.1中文参考手册> 转载请注明原文链接http://www.cnblogs.com/lenagt/archive/2012/06/06/2538201.html 谢谢. ------------------------------------------------------------------------------------------ Show processlist 在Show pro

【编程书籍 大系】 计算机开放电子书汇总

计算机开放电子书汇总 站点 站点源码 100个gcc小技巧 在线阅读 PDF格式 EPUB格式 MOBI格式 100个gdb小技巧 在线阅读 PDF格式 EPUB格式 MOBI格式 关于浏览器和网络的 20 项须知 在线阅读 PDF格式 EPUB格式 MOBI格式 2015互联网企业校招笔试题 MEGA下载 Github下载 3周3页面 在线阅读 PDF格式 EPUB格式 MOBI格式 简明 Python 教程 在线阅读 PDF格式 EPUB格式 A Guide to HTML5 and CSS

Swift2

Oct 7, 2014 创建第一个Swift 应用Building Your First Swift App Video 目前Swift 博客关注在先进的编程话题,包括Swift 语言的设计概念.我们认为这对新开发者和该接触Swift 的开发者是有帮助的.为了让每个人都能够使用,我们放了一段小的视频,演示如何从零开始用Swift创建一个应用,用少于10分钟的时间. So far the Swift blog has focused on advanced programming topics,

用LuaBridge为Lua绑定C/C++对象

最近为了总结Lua绑定C/C++对象的各种方法.第三方库和原理,学习了LuaBridge库为Lua绑定C/C++对象,下面是学习笔记,实质是对该库的Reference Manual基本上翻译了一遍,学习过程中测试代码,放在我的github上. LuaBridge的主要特点 源码只有头文件,没有.cpp文件,没有MakeFile,使用时只需一个#include即可. 支持不同的对象生命周期管理模式. 对Lua栈访问方便并且是类型安全的(type-safe). Automatic function

Show Global Status 整理

原文来源:MySQL 5.5 Reference Manual 部分翻译取自:<MySQL_5.1中文参考手册> 转载请注明原文链接http://www.cnblogs.com/lenagt/archive/2012/06/06/2538240.html 谢谢. ------------------------------------------------------------------------------------------ Show global status 在Show g