ovs的两个进程ovsdb-server和ovs-vswitchd都使用了内置的vlog来控制各自的log内容,合理的设置log模块和log等级方便定位问题或者学习。
可以使用ovs-appctl查看或者修改目标进程的log,默认的目标是ovs-vswitchd,可以通过参数 -t 指定具体目标,
-t ovsdb-server 指定目标进程为 ovsdb-server
-t ovs-vswitchd 指定目标进程为 ovs-vswitchd
下面以ovsdb-server目标为例,看一下如何修改log。
a. 使用list-commands查看vlog相关的命令
root@master:~# ovs-appctl -t ovsdb-server list-commands
...
vlog/close
vlog/disable-rate-limit [module]...
vlog/enable-rate-limit [module]...
vlog/list
vlog/list-pattern
vlog/reopen
vlog/set {spec | PATTERN:destination:pattern}
b. 查看默认的 log 使能情况
#可看到ovsdb-server内部分成了很多模块,每种模块的log都可以输出到console,syslog和指定file中。
root@master:~# ovs-appctl -t ovsdb-server vlog/list
console syslog file
------- ------ ------
backtrace INFO INFO INFO
command_line INFO INFO INFO
coverage INFO INFO INFO
daemon INFO INFO INFO
daemon_unix INFO INFO INFO
entropy INFO INFO INFO
fatal_signal INFO INFO INFO
hmap INFO INFO INFO
jsonrpc INFO INFO INFO
lockfile INFO INFO INFO
memory INFO INFO INFO
ovs_rcu INFO INFO INFO
ovs_thread INFO INFO INFO
ovsdb_error INFO INFO INFO
ovsdb_file INFO INFO INFO
ovsdb_jsonrpc_server INFO INFO INFO
ovsdb_monitor INFO INFO INFO
ovsdb_rbac INFO INFO INFO
ovsdb_server INFO INFO INFO
ovsdb_util INFO INFO INFO
poll_loop INFO INFO INFO
process INFO INFO INFO
reconnect INFO INFO INFO
replication INFO INFO INFO
signals INFO INFO INFO
socket_util INFO INFO INFO
socket_util_unix INFO INFO INFO
stream INFO INFO INFO
stream_fd INFO INFO INFO
stream_nossl INFO INFO INFO
stream_tcp INFO INFO INFO
stream_unix INFO INFO INFO
svec INFO INFO INFO
timeval INFO INFO INFO
unixctl INFO INFO INFO
util INFO INFO INFO
vlog INFO INFO INFO
c. 设置所有模块,所有输出方式,为dbg
#如果只指定log等级,则会应用的所有模块和所有输出方式
root@master:~# ovs-appctl -t ovsdb-server vlog/set dbg
root@master:~# ovs-appctl -t ovsdb-server vlog/list
console syslog file
------- ------ ------
backtrace DBG DBG DBG
command_line DBG DBG DBG
coverage DBG DBG DBG
daemon DBG DBG DBG
daemon_unix DBG DBG DBG
entropy DBG DBG DBG
fatal_signal DBG DBG DBG
hmap DBG DBG DBG
jsonrpc DBG DBG DBG
lockfile DBG DBG DBG
memory DBG DBG DBG
ovs_rcu DBG DBG DBG
ovs_thread DBG DBG DBG
ovsdb_error DBG DBG DBG
ovsdb_file DBG DBG DBG
ovsdb_jsonrpc_server DBG DBG DBG
ovsdb_monitor DBG DBG DBG
ovsdb_rbac DBG DBG DBG
ovsdb_server DBG DBG DBG
ovsdb_util DBG DBG DBG
poll_loop DBG DBG DBG
process DBG DBG DBG
reconnect DBG DBG DBG
replication DBG DBG DBG
signals DBG DBG DBG
socket_util DBG DBG DBG
socket_util_unix DBG DBG DBG
stream DBG DBG DBG
stream_fd DBG DBG DBG
stream_nossl DBG DBG DBG
stream_tcp DBG DBG DBG
stream_unix DBG DBG DBG
svec DBG DBG DBG
timeval DBG DBG DBG
unixctl DBG DBG DBG
util DBG DBG DBG
vlog DBG DBG DBG
d. 设置指定模块,所有输出方式,为dbg level(中间的逗号不能去)
#可看到只有jsonrpc的log等级变为dbg,其他模块仍然为info
root@master:~# ovs-appctl -t ovsdb-server vlog/set jsonrpc,dbg
root@master:~# ovs-appctl -t ovsdb-server vlog/list
console syslog file
------- ------ ------
backtrace INFO INFO INFO
command_line INFO INFO INFO
coverage INFO INFO INFO
daemon INFO INFO INFO
daemon_unix INFO INFO INFO
entropy INFO INFO INFO
fatal_signal INFO INFO INFO
hmap INFO INFO INFO
jsonrpc DBG DBG DBG
lockfile INFO INFO INFO
memory INFO INFO INFO
ovs_rcu INFO INFO INFO
ovs_thread INFO INFO INFO
ovsdb_error INFO INFO INFO
ovsdb_file INFO INFO INFO
ovsdb_jsonrpc_server INFO INFO INFO
ovsdb_monitor INFO INFO INFO
ovsdb_rbac INFO INFO INFO
ovsdb_server INFO INFO INFO
ovsdb_util INFO INFO INFO
poll_loop INFO INFO INFO
process INFO INFO INFO
reconnect INFO INFO INFO
replication INFO INFO INFO
signals INFO INFO INFO
socket_util INFO INFO INFO
socket_util_unix INFO INFO INFO
stream INFO INFO INFO
stream_fd INFO INFO INFO
stream_nossl INFO INFO INFO
stream_tcp INFO INFO INFO
stream_unix INFO INFO INFO
svec INFO INFO INFO
timeval INFO INFO INFO
unixctl INFO INFO INFO
util INFO INFO INFO
vlog INFO INFO INFO
e.设置指定模块,指定输出方式,为dbg level(中间的逗号不能去)
#可看到只有jsonrpc模块的console输出改完dbg,其他的仍然为info
root@master:~# ovs-appctl -t ovsdb-server vlog/set jsonrpc,console,dbg
root@master:~# ovs-appctl -t ovsdb-server vlog/list
console syslog file
------- ------ ------
backtrace INFO INFO INFO
command_line INFO INFO INFO
coverage INFO INFO INFO
daemon INFO INFO INFO
daemon_unix INFO INFO INFO
entropy INFO INFO INFO
fatal_signal INFO INFO INFO
hmap INFO INFO INFO
jsonrpc DBG INFO INFO
lockfile INFO INFO INFO
memory INFO INFO INFO
ovs_rcu INFO INFO INFO
ovs_thread INFO INFO INFO
ovsdb_error INFO INFO INFO
ovsdb_file INFO INFO INFO
ovsdb_jsonrpc_server INFO INFO INFO
ovsdb_monitor INFO INFO INFO
ovsdb_rbac INFO INFO INFO
ovsdb_server INFO INFO INFO
ovsdb_util INFO INFO INFO
poll_loop INFO INFO INFO
process INFO INFO INFO
reconnect INFO INFO INFO
replication INFO INFO INFO
signals INFO INFO INFO
socket_util INFO INFO INFO
socket_util_unix INFO INFO INFO
stream INFO INFO INFO
stream_fd INFO INFO INFO
stream_nossl INFO INFO INFO
stream_tcp INFO INFO INFO
stream_unix INFO INFO INFO
svec INFO INFO INFO
timeval INFO INFO INFO
unixctl INFO INFO INFO
util INFO INFO INFO
vlog INFO INFO INFO
源码分析
每个模块源文件都会调用以下宏声明一个静态变量 this_module 。
VLOG_DEFINE_THIS_MODULE(dpctl);
我们都知道,在c代码中,静态变量的作用就是限制此变量只能在本源文件中被使用,所以虽然多个模块都声明了静态变量this_module,但是都是互不冲突的,只要代码执行到此模块的相关函数时,调用的this_module肯定就是自己的变量。
以下是 VLOG_DEFINE_THIS_MODULE 的定义,
a. 声明静态变量this_module,变量类型为结构体 struct vlog_module,初始化其成员变量,其中 levels 表示三种输出方式: syslog, console, file
b. 定义函数init_this_module_##MODULE,此函数使用到了gcc的属性attribute((constructor)),可以在main函数之前就被执行。调用函数 vlog_insert_module 将 this_module 挂到全局链表 vlog_modules。查看/设置log登记都是通过遍历全局链表 vlog_modules 找到对应的模块进行操作。
/* A log module. */
struct vlog_module {
struct ovs_list list;
const char *name; /* User-visible name. */
int levels[VLF_N_DESTINATIONS]; /* Minimum log level for each
destination. */
int min_level; /* Minimum log level for any destination. */
bool honor_rate_limits; /* Set false to ignore rate limits. */
};
#define OVS_CONSTRUCTOR(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
/* Defines a logging module whose name is MODULE, which should generally be
* roughly the name of the source file, and makes it the module used by the
* logging convenience macros defined below. */
#define VLOG_DEFINE_THIS_MODULE(MODULE) \
static struct vlog_module this_module = { \
OVS_LIST_INITIALIZER(&this_module.list), \
#MODULE, /* name */ \
{ VLL_INFO, VLL_INFO, VLL_INFO }, /* levels */ \
VLL_INFO, /* min_level */ \
true /* honor_rate_limits */ \
}; \
OVS_CONSTRUCTOR(init_this_module_##MODULE) { \
vlog_insert_module(&this_module.list); \
} \
\
/* Prevent duplicate module names, via linker error. \
* The extra "extern" declaration makes sparse happy. */ \
extern struct vlog_module *VLM_##MODULE; \
struct vlog_module *VLM_##MODULE = &this_module;
void
vlog_insert_module(struct ovs_list *vlog)
{
ovs_mutex_lock(&log_file_mutex);
ovs_list_insert(&vlog_modules, vlog);
ovs_mutex_unlock(&log_file_mutex);
}
代码执行过程中,可以使用函数 VLOG_IS_DBG_ENABLED 判断是否需要打印log,其直接使用 this_module ,因为在 jsonrpc.c 源文件中,所以 this_module 就是jsonrpc模块的变量。
bool
vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
{
return module->min_level >= level;
}
vlog_is_enabled(&this_module, VLL_DBG)
#define VLOG_IS_DBG_ENABLED() vlog_is_enabled(&this_module, VLL_DBG)
static void
jsonrpc_log_msg(const struct jsonrpc *rpc, const char *title,
const struct jsonrpc_msg *msg)
{
if (VLOG_IS_DBG_ENABLED()) {
struct ds s = DS_EMPTY_INITIALIZER;
if (msg->method) {
ds_put_format(&s, ", method=\"%s\"", msg->method);
}
...
}
网友评论