日誌(Logging)


程式中不免會出現錯誤,當錯誤發生時,您可以使用printf()或是g_print()在主控台 (Console)顯示訊息給使用者,如果是在視窗程式中,可能是使用訊息方塊,您也可能想針對某個層級的訊息作個別處理,例如儲存在log檔案之中,在GLib中,您可以使用 Message Logging 中所介紹的函式來進行日誌功能。

要進行日誌,首先最基本的就是使用g_log()函式:
void g_log(const gchar *log_domain,
           GLogLevelFlags log_level,
           const gchar *format,
           ...);

第一個參數是log_domain,用來區別日誌訊息的發出者,若有設定日誌的處理函式,則log_domain亦會傳遞給處理函式,如果您沒有指定,則預設會使用G_LOG_DOMAIN,函式庫會定義G_LOG_DOMAIN,以區別於其它的函式庫,例如GTK在它的Makefine中定義為"Gtk":
INCLUDES = -DG_LOG_DOMAIN=\"Gtk\"

第二個參數是日誌層級,可以設定為以下的值:
  • G_LOG_LEVEL_ERROR(致命的,FATAL)
  • G_LOG_LEVEL_CRITICAL
  • G_LOG_LEVEL_WARNING
  • G_LOG_LEVEL_MESSAGE
  • G_LOG_LEVEL_INFO
  • G_LOG_LEVEL_DEBUG

另外還有兩個G_LOG_FLAG_FATAL與G_LOG_FLAG_RECURSION,作為內部的旗標使用,其中與 G_LOG_FLAG_FATAL相關聯的,例如G_LOG_LEVEL_ERROR,是屬於嚴重的致命訊息,當日誌時以這個層級輸出時,應用程式會被中 止並呼叫核心傾印(dump)。

第三個參數是要輸出的訊息,其它則是額外的訊息。

GLib還提供了五個巨集函式,方便使用日誌與相對應的訊息層級:
#define g_message(...)
#define g_warning(...)
#define g_critical(...)
#define g_error(...)
#define g_debug(...)

先前說過,G_LOG_FLAG_FATAL是內部旗標,預設是G_LOG_LEVEL_ERROR與之關聯,如果您想讓其它層級的訊息也成為FATAL 的,則可以使用g_log_set_always_fatal()函式,例如將DEBUG與CRITICAL設定為FATAL:
g_log_set_always_fatal(G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_CRITICAL);

對於日誌訊息,您可以設定相對應的處理函式,這是使用g_log_set_handler()函式來達成:
guint g_log_set_handler(const gchar *log_domain,
                        GLogLevelFlags log_levels,
                        GLogFunc log_func,
                        gpointer user_data);

傳回的整數值為Handler Id,其中GLogFunc為回呼函式,它的宣告定義如下:
void (*GLogFunc) (const gchar *log_domain,
                  GLogLevelFlags log_level,
                  const gchar *message,
                  gpointer user_data);

設定訊息處理函式之後,若想移除,則可以使用g_log_remove_handler()函式,根據Handler ID及log domain來移除:
void g_log_remove_handler(const gchar *log_domain,
                          guint handler_id);