5_02_GLib库入门与实践_日志和调试

简介

GLib提供了一套日志输出接口,包括不同日志级别的输出以及与systemd日志系统的对接。

数据结构

日志输出最主要的数据结构是日志级别。
GLib提供了debug、info、message、warning、critical和error这六种日志输出级别。
其中,error默认是FATAL级别日志输出,输出该级别日志会调用abort()导致程序退出

enum GLogLevelFlags

函数列表

void 	g_log ()
void 	g_logv ()
#define 	g_message()
#define 	g_warning()
#define 	g_critical()
#define 	g_error()
#define 	g_info()
#define 	g_debug()
guint 	g_log_set_handler ()
guint 	g_log_set_handler_full ()
void 	g_log_remove_handler ()
GLogLevelFlags 	g_log_set_always_fatal ()
GLogLevelFlags 	g_log_set_fatal_mask ()
void 	g_log_default_handler ()
GLogFunc 	g_log_set_default_handler ()
void 	g_log_structured ()
void 	g_log_variant ()
void 	g_log_structured_array ()
#define 	G_DEBUG_HERE
GLogWriterOutput 	(*GLogWriterFunc) ()
void 	g_log_set_writer_func ()
gboolean 	g_log_writer_supports_color ()
gboolean 	g_log_writer_is_journald ()
gchar * 	g_log_writer_format_fields ()
GLogWriterOutput 	g_log_writer_journald ()
GLogWriterOutput 	g_log_writer_standard_streams ()
GLogWriterOutput 	g_log_writer_default ()

函数功能分类

// 日志输出函数,g_logv接受valist变量
void 	g_log ()
void 	g_logv ()

// 不同的调试输出日志函数
// 按级别排序:debug<info<message<warning<critical<error
#define 	g_message()
#define 	g_warning()
#define 	g_critical()
#define 	g_error()
#define 	g_info()
#define 	g_debug()

// 设置和取消自定义日志函数
guint 	g_log_set_handler ()
guint 	g_log_set_handler_full ()
void 	g_log_remove_handler ()

// 给参数中指定的输出日志级别设置一个全局的fatal
// 如果设置了fatal,则在运行时,该日志输出之后会调用到abort()继而出现段错误。
// 默认情况下,只有error级别的输出,会导致段错误
GLogLevelFlags 	g_log_set_always_fatal ()

// 与g_log_set_always_fatal相似,但只对某一domain设置fatal,而非全局
GLogLevelFlags 	g_log_set_fatal_mask ()

// 设置默认输出函数
void 	g_log_default_handler ()
GLogFunc 	g_log_set_default_handler ()

// 与systemd日志相关的结构化日志输出函数
void 	g_log_structured ()
// 参数为泛型的结构化日志输出函数
void 	g_log_variant ()
// 参数为数组的结构化日志输出函数
void 	g_log_structured_array ()

// 设置写函数
void 	g_log_set_writer_func ()
// 是否支持ANSI颜色转义序列
gboolean 	g_log_writer_supports_color ()
// 判断给定的文件描述符是否与systemd日志文件有关
gboolean 	g_log_writer_is_journald ()

// 将结构化日志输出到systemd日志系统
GLogWriterOutput 	g_log_writer_journald ()
// 将结构化日志输出到标准输出stdout或标准错误输出stderr
GLogWriterOutput 	g_log_writer_standard_streams ()
// 将结构化日志输出到系统默认日志系统(一般是systemd),如果从终端运行或被重定向到文件,则会输出到标准输出
GLogWriterOutput 	g_log_writer_default ()

函数功能说明及综合演示

g_log函数用法演示

示例代码如下:
源码见glib_examples\glib_log\glib_log_g_log

#include <glib.h>

static void my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
    g_print("[%s]my_log_handler : %s \n",user_data,message);

}

gint main(gint argc, gchar **argv)
{
    g_log_set_default_handler(my_log_handler, "User_Data");

    g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);

    g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
    g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
    g_log ("baz", G_LOG_LEVEL_DEBUG, "6");

    return 0;
}

运行结果:

[root@centos7_6 build]# ./glib_log_g_log
[User_Data]my_log_handler : 6
[User_Data]my_log_handler : 6
[User_Data]my_log_handler : 6
不同级别的日志输出

示例代码如下:
源码见glib_examples\glib_log\glib_log_handler

#include <glib.h>

static void my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
    g_print("[%s]my_log_handler : %s \n",user_data,message);

}
gint main(gint argc, gchar **argv)
{
    guint handler_id = 0;

    g_print("set handler: G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION \n");
    handler_id = g_log_set_handler(NULL, 
        G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION, my_log_handler, "APP_TAG");

    g_debug("debug");
    g_info("info");
    g_message("message");
    g_warning("warning");
    g_critical("critical");
    //g_error("error");

    g_log_remove_handler(NULL, handler_id);

    g_print("set handler: G_LOG_LEVEL_INFO|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION \n");

    handler_id = g_log_set_handler(NULL, 
        G_LOG_LEVEL_INFO|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION, my_log_handler, "APP_TAG");
    g_debug("debug");
    g_info("info");
    g_message("message");
    g_warning("warning");
    g_critical("critical");

    g_log_remove_handler(NULL, handler_id);

    g_print("set handler: G_LOG_LEVEL_INFO|G_LOG_LEVEL_WARNING|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION \n");
    handler_id = g_log_set_handler(NULL, 
        G_LOG_LEVEL_INFO|G_LOG_LEVEL_WARNING|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION, my_log_handler, "APP_TAG");

    g_debug("debug");
    g_info("info");
    g_message("message");
    g_warning("warning");
    g_critical("critical");

    
    g_log_remove_handler(NULL, handler_id);

    g_print("set handler: G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION \n");
    handler_id = g_log_set_handler(NULL, 
        G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION, my_log_handler, "APP_TAG");

    g_log_set_always_fatal(G_LOG_LEVEL_MESSAGE);
    g_debug("debug");
    g_info("info");
    g_message("message");
    g_warning("warning");
    g_critical("critical");

    return 0;
}

运行结果:

[root@centos7_6 build]# ./glib_log_handler
set handler: G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION
[APP_TAG]my_log_handler : debug
[APP_TAG]my_log_handler : info
[APP_TAG]my_log_handler : message
[APP_TAG]my_log_handler : warning
[APP_TAG]my_log_handler : critical
set handler: G_LOG_LEVEL_INFO|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION
[APP_TAG]my_log_handler : info
** Message: 15:10:31.479: message

** (process:6101): WARNING **: 15:10:31.479: warning

** (process:6101): CRITICAL **: 15:10:31.479: critical
set handler: G_LOG_LEVEL_INFO|G_LOG_LEVEL_WARNING|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION
[APP_TAG]my_log_handler : info
** Message: 15:10:31.479: message
[APP_TAG]my_log_handler : warning

** (process:6101): CRITICAL **: 15:10:31.479: critical
set handler: G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION
[APP_TAG]my_log_handler : debug
[APP_TAG]my_log_handler : info
[APP_TAG]my_log_handler : message
Trace/breakpoint trap(吐核)

在上述例子中,对日志输出的handler进行了多次设置和取消设置,G_LOG_LEVEL_MASK会将所有的日志输出都重定向到hander设置的输出函数,也可以单独设置某一项或某几项。
注意:设置低级别时,高级别的日志也会输出,但不会走设置的输出函数,而是走默认输出函数。例如,如果设置的是info级别,则debug不会输出,但message会输出日志,因为debug的级别比info低,但message的级别比info要高。

设置全局或域FATAL错误

FATAL错误是一种无法恢复的错误,当出现FATAL时,需要退出程序,GLib通过调用abort()使程序退出。默认情况下,只有error输出为FATAL级别,会导致段错误使程序退出,但可以使用g_log_set_always_fatal或者g_log_set_fatal_mask为某一域设置FATAL错误。

示例代码如下:
源码见glib_examples\glib_log_fatal\glib_log_fatal

#include <glib.h>

static void my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
    g_print("[domain:%s][LEVEL:%3d][%s]my_log_handler : %s \n",log_domain,log_level,user_data,message);
}

gint main(gint argc, gchar **argv)
{
    g_log_set_default_handler(my_log_handler, "User_Data");

    g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);

    g_log ("foo", G_LOG_LEVEL_DEBUG, "foo debug");
    g_log ("foo", G_LOG_LEVEL_INFO, "foo info");
    g_log ("bar", G_LOG_LEVEL_MESSAGE, "bar message");
    g_log ("bar", G_LOG_LEVEL_WARNING, "bar warning");
    g_log ("baz", G_LOG_LEVEL_CRITICAL, "bar critical");

    g_print("set fatal mask: baz G_LOG_LEVEL_MESSAGE \n");
    g_log_set_fatal_mask("baz", G_LOG_LEVEL_MESSAGE);

    g_log ("foo", G_LOG_LEVEL_DEBUG, "foo debug");
    g_log ("foo", G_LOG_LEVEL_INFO, "foo info");
    g_log ("foo", G_LOG_LEVEL_MESSAGE, "foo message");
    g_log ("bar", G_LOG_LEVEL_MESSAGE, "bar message");
    g_log ("bar", G_LOG_LEVEL_WARNING, "bar warning");
    g_log ("baz", G_LOG_LEVEL_INFO, "baz info");
    g_log ("baz", G_LOG_LEVEL_CRITICAL, "baz critical");

    g_print("set always fatal: G_LOG_LEVEL_MESSAGE \n");
    g_log_set_always_fatal(G_LOG_LEVEL_MESSAGE);

    g_log ("foo", G_LOG_LEVEL_DEBUG, "foo debug");
    g_log ("foo", G_LOG_LEVEL_INFO, "foo info");
    g_log ("bar", G_LOG_LEVEL_MESSAGE, "bar message");
    g_log ("bar", G_LOG_LEVEL_WARNING, "bar warning");
    g_log ("baz", G_LOG_LEVEL_CRITICAL, "baz critical");

    return 0;
}

运行结果:

[root@centos7_6 build]# ./glib_log_fatal
[domain:foo][LEVEL:128][User_Data]my_log_handler : foo debug
[domain:foo][LEVEL: 64][User_Data]my_log_handler : foo info
[domain:bar][LEVEL: 32][User_Data]my_log_handler : bar message
[domain:bar][LEVEL: 16][User_Data]my_log_handler : bar warning
[domain:baz][LEVEL:  8][User_Data]my_log_handler : bar critical
set fatal mask: baz G_LOG_LEVEL_MESSAGE
[domain:foo][LEVEL:128][User_Data]my_log_handler : foo debug
[domain:foo][LEVEL: 64][User_Data]my_log_handler : foo info
[domain:foo][LEVEL: 32][User_Data]my_log_handler : foo message
[domain:bar][LEVEL: 32][User_Data]my_log_handler : bar message
[domain:bar][LEVEL: 16][User_Data]my_log_handler : bar warning
[domain:baz][LEVEL: 64][User_Data]my_log_handler : baz info
[domain:baz][LEVEL:  8][User_Data]my_log_handler : baz critical
set always fatal: G_LOG_LEVEL_MESSAGE
[domain:foo][LEVEL:128][User_Data]my_log_handler : foo debug
[domain:foo][LEVEL: 64][User_Data]my_log_handler : foo info
[domain:bar][LEVEL: 34][User_Data]my_log_handler : bar message
Trace/breakpoint trap(吐核)
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值