把g_log的输出记录到syslog中

用glib的时候,一直习惯用g_message, g_warning 这几个g_log 的 wrapper 函数,并且知道这些函数的输出是能通过一个handler进行额外处理的但是一直没实践过。

某个项目中需要记录程序的日志,而先前所有日志都是用g_log做的,于是需要把把g_log的输出保存到syslog中。我错误的以为,g_warning、g_error、g_critical和LOG_WARNING、LOG_ERR、LOG_CRIT是一一对应的,一查头文件,发现原来不是。

glib的log level是用bitmap实现的,其中最后两位是log level以外的标志位:

typedef enum
{
  /* log flags */
  G_LOG_FLAG_RECURSION          = 1 << 0,
  G_LOG_FLAG_FATAL              = 1 << 1,

  /* GLib log levels */
  G_LOG_LEVEL_ERROR             = 1 << 2,       /* always fatal */
  G_LOG_LEVEL_CRITICAL          = 1 << 3,
  G_LOG_LEVEL_WARNING           = 1 << 4,
  G_LOG_LEVEL_MESSAGE           = 1 << 5,
  G_LOG_LEVEL_INFO              = 1 << 6,
  G_LOG_LEVEL_DEBUG             = 1 << 7,

  G_LOG_LEVEL_MASK              = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL)
} GLogLevelFlags;

而syslog的level是用连续的整数实现的

#define	LOG_EMERG	0	/* system is unusable */
#define	LOG_ALERT	1	/* action must be taken immediately */
#define	LOG_CRIT	2	/* critical conditions */
#define	LOG_ERR		3	/* error conditions */
#define	LOG_WARNING	4	/* warning conditions */
#define	LOG_NOTICE	5	/* normal but significant condition */
#define	LOG_INFO	6	/* informational */
#define	LOG_DEBUG	7	/* debug-level messages */

于是它们之间需要一个映射,感觉如果用python会很简洁:

static const  char * logger_prioritynames[] = { "emerg",
"alert",
"crit",
"err",
"warning",
"notice",
"info",
"debug"
};

static void log2file (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
	log_level &= ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL);
	int prority = LOG_WARNING;

	switch (log_level)
	{
		case G_LOG_LEVEL_ERROR:
			prority = LOG_CRIT;
			break;
		case G_LOG_LEVEL_CRITICAL:
			prority = LOG_ERR;
			break;
		case G_LOG_LEVEL_WARNING:
			prority = LOG_WARNING;
			break;
		case G_LOG_LEVEL_MESSAGE:
			prority = LOG_NOTICE;
			break;
		case G_LOG_LEVEL_INFO:
			prority = LOG_INFO;
			break;
		case G_LOG_LEVEL_DEBUG:
			prority = LOG_DEBUG;
			break;
		default:
			break;
	}
	assert (prority <= (sizeof (logger_prioritynames) / sizeof (logger_prioritynames[0])));

	syslog (prority, "<%s> %s", logger_prioritynames[prority], message);

}

最后,在初始化的时候给glib设置这个handler:

g_log_set_default_handler (log2file, NULL);
updatedupdated2022-02-222022-02-22