如何使用GLib实现C程序的日志级别控制与分级输出
GLib 日志分级功能实现方案
GLib 原生提供了完整的日志管理框架,无需手动基于 printf 封装,结合内置的命令行参数解析能力即可快速实现你需要的启动参数控制日志级别的需求。
1. 内置日志级别说明
GLib 默认定义了6个从低到高的日志级别,对应不同的使用场景:
G_LOG_LEVEL_DEBUG:调试用细节信息,仅开发阶段需要G_LOG_LEVEL_INFO:运行状态提示信息G_LOG_LEVEL_MESSAGE:常规业务输出G_LOG_LEVEL_WARNING:非致命警告,不影响程序正常运行G_LOG_LEVEL_CRITICAL:严重错误,对应功能无法正常执行G_LOG_LEVEL_ERROR:致命错误,触发后程序会自动终止
你可以直接使用GLib提供的便捷宏输出对应级别日志:g_debug()、g_info()、g_message()、g_warning()、g_critical()、g_error()。
2. 核心实现步骤
2.1 解析命令行日志参数
使用GLib内置的GOptionContext解析-log参数,避免手动处理命令行输入的边界问题。参数值和日志级别掩码的对应规则可自行定义,比如:
debug:允许所有级别日志输出info:允许INFO及以上级别warning:允许WARNING及以上级别error:仅允许ERROR级别输出
2.2 自定义日志过滤 handler
通过g_log_set_handler()注册全局日志处理函数,在回调中判断当前日志级别是否符合设置的阈值,符合则输出到标准输出。你可以在handler中自定义输出格式,比如添加时间戳、线程ID等字段。
3. 完整示例代码
#include <glib.h> // 全局日志级别阈值 static GLogLevelFlags log_threshold = G_LOG_LEVEL_WARNING; // 自定义日志处理函数 static void log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { // 低于阈值的日志直接丢弃 if (log_level < log_threshold) { return; } // 输出到标准输出,可自行修改格式 const gchar *level_str; switch (log_level & G_LOG_LEVEL_MASK) { case G_LOG_LEVEL_DEBUG: level_str = "DEBUG"; break; case G_LOG_LEVEL_INFO: level_str = "INFO"; break; case G_LOG_LEVEL_MESSAGE: level_str = "MESSAGE"; break; case G_LOG_LEVEL_WARNING: level_str = "WARNING"; break; case G_LOG_LEVEL_CRITICAL: level_str = "CRITICAL"; break; case G_LOG_LEVEL_ERROR: level_str = "ERROR"; break; default: level_str = "UNKNOWN"; } g_print("[%s] %s\n", level_str, message); } int main(int argc, char *argv[]) { gchar *log_level_str = NULL; // 定义命令行参数规则 GOptionEntry entries[] = { {"log", 'l', 0, G_OPTION_ARG_STRING, &log_level_str, "Set log level (debug/info/warning/error)", "LEVEL"}, {NULL} }; GError *error = NULL; GOptionContext *context = g_option_context_new("- test program"); g_option_context_add_main_entries(context, entries, NULL); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_printerr("Option parsing failed: %s\n", error->message); g_error_free(error); return 1; } g_option_context_free(context); // 映射参数到日志阈值 if (log_level_str) { if (g_str_equal(log_level_str, "debug")) { log_threshold = G_LOG_LEVEL_DEBUG; } else if (g_str_equal(log_level_str, "info")) { log_threshold = G_LOG_LEVEL_INFO; } else if (g_str_equal(log_level_str, "warning")) { log_threshold = G_LOG_LEVEL_WARNING; } else if (g_str_equal(log_level_str, "error")) { log_threshold = G_LOG_LEVEL_ERROR; } else { g_printerr("Invalid log level, use default 'warning'\n"); } g_free(log_level_str); } // 注册全局日志handler g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, log_handler, NULL); // 测试日志输出 g_debug("This is a debug message"); g_info("This is an info message"); g_warning("This is a warning message"); g_critical("This is a critical message"); g_error("This is an error message"); return 0; }
编译命令参考(需要依赖GLib2.0):gcc main.c -o my_program pkg-config --cflags --libs glib-2.0``
4. 使用效果
- 执行
./my_program -log=debug:输出所有级别的日志 - 执行
./my_program -log=warning:仅输出WARNING、CRITICAL、ERROR级别的日志 - 执行
./my_program -log=error:仅输出ERROR级别的日志
如果需要更复杂的日志能力,比如输出到文件、按大小切割日志,可以在自定义handler中扩展对应的逻辑即可。
内容的提问来源于stack exchange,提问作者V_0rigi
相关产品推荐
相关产品推荐

