mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
gmessages: add syslog support
Introduce g_log_writer_syslog() that is suitable for use as a GLogWriterFunc and sends the log message to the syslog daemon. Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
This commit is contained in:
parent
686ab492cf
commit
c8437611f0
137
glib/gmessages.c
137
glib/gmessages.c
@ -64,6 +64,10 @@
|
|||||||
#include "gthreadprivate.h"
|
#include "gthreadprivate.h"
|
||||||
#include "gutilsprivate.h"
|
#include "gutilsprivate.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(__BIONIC__)
|
#if defined(__linux__) && !defined(__BIONIC__)
|
||||||
#include "gjournal-private.h"
|
#include "gjournal-private.h"
|
||||||
#endif
|
#endif
|
||||||
@ -1326,6 +1330,25 @@ log_level_to_priority (GLogLevelFlags log_level)
|
|||||||
return "5";
|
return "5";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
static int
|
||||||
|
str_to_syslog_facility (const gchar *syslog_facility_str)
|
||||||
|
{
|
||||||
|
int syslog_facility = LOG_USER;
|
||||||
|
|
||||||
|
if (g_strcmp0 (syslog_facility_str, "auth") == 0)
|
||||||
|
{
|
||||||
|
syslog_facility = LOG_AUTH;
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (syslog_facility_str, "daemon") == 0)
|
||||||
|
{
|
||||||
|
syslog_facility = LOG_DAEMON;
|
||||||
|
}
|
||||||
|
|
||||||
|
return syslog_facility;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline FILE *
|
static inline FILE *
|
||||||
log_level_to_file (GLogLevelFlags log_level)
|
log_level_to_file (GLogLevelFlags log_level)
|
||||||
{
|
{
|
||||||
@ -2009,6 +2032,13 @@ reset_invalid_param_handler:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
static gboolean syslog_opened = FALSE;
|
||||||
|
#ifndef __linux__
|
||||||
|
G_LOCK_DEFINE_STATIC (syslog_opened);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(__BIONIC__)
|
#if defined(__linux__) && !defined(__BIONIC__)
|
||||||
static int journal_fd = -1;
|
static int journal_fd = -1;
|
||||||
|
|
||||||
@ -2195,6 +2225,113 @@ g_log_writer_format_fields (GLogLevelFlags log_level,
|
|||||||
return g_string_free (gstring, FALSE);
|
return g_string_free (gstring, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_log_writer_syslog:
|
||||||
|
* @log_level: log level, either from [type@GLib.LogLevelFlags], or a user-defined
|
||||||
|
* level
|
||||||
|
* @fields: (array length=n_fields): key–value pairs of structured data forming
|
||||||
|
* the log message
|
||||||
|
* @n_fields: number of elements in the @fields array
|
||||||
|
* @user_data: user data passed to [func@GLib.log_set_writer_func]
|
||||||
|
*
|
||||||
|
* Format a structured log message and send it to the syslog daemon. Only fields
|
||||||
|
* which are understood by this function are included in the formatted string
|
||||||
|
* which is printed.
|
||||||
|
*
|
||||||
|
* Log facility will be defined via the SYSLOG_FACILITY field and accepts the following
|
||||||
|
* values: "auth", "daemon", and "user". If SYSLOG_FACILITY is not specified, LOG_USER
|
||||||
|
* facility will be used.
|
||||||
|
*
|
||||||
|
* This is suitable for use as a [type@GLib.LogWriterFunc].
|
||||||
|
*
|
||||||
|
* If syslog is not supported, this function is still defined, but will always
|
||||||
|
* return [enum@GLib.LogWriterOutput.UNHANDLED].
|
||||||
|
*
|
||||||
|
* Returns: [enum@GLib.LogWriterOutput.HANDLED] on success, [enum@GLib.LogWriterOutput.UNHANDLED] otherwise
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
GLogWriterOutput
|
||||||
|
g_log_writer_syslog (GLogLevelFlags log_level,
|
||||||
|
const GLogField *fields,
|
||||||
|
gsize n_fields,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
gsize i;
|
||||||
|
const char *message = NULL;
|
||||||
|
const char *log_domain = NULL;
|
||||||
|
int syslog_facility = 0;
|
||||||
|
int syslog_level;
|
||||||
|
gssize message_length = -1;
|
||||||
|
gssize log_domain_length = -1;
|
||||||
|
GString *gstring;
|
||||||
|
|
||||||
|
g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
|
||||||
|
g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
|
||||||
|
|
||||||
|
/* As not all man pages provide sufficient information about the thread safety
|
||||||
|
* of the openlog() routine or even describe alternative routines like logopen_r()
|
||||||
|
* intended for multi-threaded applications, use locking on non-Linux platforms till
|
||||||
|
* the situation can be cleared. See the following links for more information:
|
||||||
|
* FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=openlog
|
||||||
|
* NetBSD: https://man.netbsd.org/openlog.3
|
||||||
|
* POSIX: https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/functions/openlog.html#
|
||||||
|
*/
|
||||||
|
#ifndef __linux__
|
||||||
|
G_LOCK (syslog_opened);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!syslog_opened)
|
||||||
|
{
|
||||||
|
openlog (NULL, 0, 0);
|
||||||
|
syslog_opened = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __linux__
|
||||||
|
G_UNLOCK (syslog_opened);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < n_fields; i++)
|
||||||
|
{
|
||||||
|
const GLogField *field = &fields[i];
|
||||||
|
|
||||||
|
if (g_strcmp0 (field->key, "MESSAGE") == 0)
|
||||||
|
{
|
||||||
|
message = field->value;
|
||||||
|
message_length = field->length;
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (field->key, "GLIB_DOMAIN") == 0)
|
||||||
|
{
|
||||||
|
log_domain = field->value;
|
||||||
|
log_domain_length = field->length;
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (field->key, "SYSLOG_FACILITY") == 0)
|
||||||
|
{
|
||||||
|
syslog_facility = str_to_syslog_facility (field->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gstring = g_string_new (NULL);
|
||||||
|
|
||||||
|
if (log_domain != NULL)
|
||||||
|
{
|
||||||
|
g_string_append_len (gstring, log_domain, log_domain_length);
|
||||||
|
g_string_append (gstring, ": ");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_len (gstring, message, message_length);
|
||||||
|
|
||||||
|
syslog_level = atoi (log_level_to_priority (log_level));
|
||||||
|
syslog (syslog_level | syslog_facility, "%s", gstring->str);
|
||||||
|
|
||||||
|
g_string_free (gstring, TRUE);
|
||||||
|
|
||||||
|
return G_LOG_WRITER_HANDLED;
|
||||||
|
#else
|
||||||
|
return G_LOG_WRITER_UNHANDLED;
|
||||||
|
#endif /* HAVE_SYSLOG_H */
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable support for the journal if we're on a recent enough Linux */
|
/* Enable support for the journal if we're on a recent enough Linux */
|
||||||
#if defined(__linux__) && !defined(__BIONIC__) && defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
|
#if defined(__linux__) && !defined(__BIONIC__) && defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
|
||||||
#define ENABLE_JOURNAL_SENDV
|
#define ENABLE_JOURNAL_SENDV
|
||||||
|
@ -229,6 +229,11 @@ gchar *g_log_writer_format_fields (GLogLevelFlags log_level,
|
|||||||
gsize n_fields,
|
gsize n_fields,
|
||||||
gboolean use_color);
|
gboolean use_color);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_80
|
||||||
|
GLogWriterOutput g_log_writer_syslog (GLogLevelFlags log_level,
|
||||||
|
const GLogField *fields,
|
||||||
|
gsize n_fields,
|
||||||
|
gpointer user_data);
|
||||||
GLIB_AVAILABLE_IN_2_50
|
GLIB_AVAILABLE_IN_2_50
|
||||||
GLogWriterOutput g_log_writer_journald (GLogLevelFlags log_level,
|
GLogWriterOutput g_log_writer_journald (GLogLevelFlags log_level,
|
||||||
const GLogField *fields,
|
const GLogField *fields,
|
||||||
|
@ -414,6 +414,7 @@ headers = [
|
|||||||
'sys/vfstab.h',
|
'sys/vfstab.h',
|
||||||
'sys/vmount.h',
|
'sys/vmount.h',
|
||||||
'sys/wait.h',
|
'sys/wait.h',
|
||||||
|
'syslog.h',
|
||||||
'termios.h',
|
'termios.h',
|
||||||
'unistd.h',
|
'unistd.h',
|
||||||
'values.h',
|
'values.h',
|
||||||
|
Loading…
Reference in New Issue
Block a user