[pulseaudio-discuss] [PATCH v2] log: Add support for the systemd journal
poljar (Damir Jelić)
poljarinho at gmail.com
Mon Dec 2 16:09:56 PST 2013
The journal is a component of systemd, that captures Syslog messages,
Kernel log messages, initial RAM disk and early boot messages as well
as messages written to STDOUT/STDERR of all services, indexes them and
makes this available to the user.
It can be used in parallel, or in place of a traditional syslog daemon,
such as rsyslog or syslog-ng.
The journal offers a couple of improvements over traditional logging
facilities (e.g. advanced filtering capabilities).
This patch adds support for logging directly to the journal using its
native API.
---
Changes for v2:
- if systemd journal support is enabled the journal is the default
log target
- changed the configure option name: journal -> systemd-journal
- fixed spelling error
- proper return value checking of sd_journal_send()
configure.ac | 18 ++++++++++
man/pulse-daemon.conf.5.xml.in | 11 +++---
man/pulseaudio.1.xml.in | 5 +--
src/Makefile.am | 5 +++
src/daemon/cmdline.c | 4 +++
src/daemon/main.c | 4 +++
src/pulsecore/log.c | 76 +++++++++++++++++++++++++++++++++++++-----
src/pulsecore/log.h | 3 ++
8 files changed, 110 insertions(+), 16 deletions(-)
diff --git a/configure.ac b/configure.ac
index 72e7695..d4b4817 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1160,6 +1160,22 @@ AC_SUBST(HAVE_SYSTEMD)
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$HAVE_SYSTEMD" = x1])
AS_IF([test "x$HAVE_SYSTEMD" = "x1"], AC_DEFINE([HAVE_SYSTEMD], 1, [Have SYSTEMD?]))
+#### journal support (optional) ####
+
+AC_ARG_ENABLE([systemd-journal],
+ AS_HELP_STRING([--disable-systemd-journal],[Disable optional systemd journal support]))
+
+AS_IF([test "x$enable_systemd_journal" != "xno"],
+ [PKG_CHECK_MODULES(JOURNAL, [ libsystemd-journal ], HAVE_SYSTEMD_JOURNAL=1, HAVE_SYSTEMD_JOURNAL=0)],
+ HAVE_SYSTEMD_JOURNAL=0)
+
+AS_IF([test "x$enable_systemd_journal" = "xyes" && test "x$HAVE_SYSTEMD_JOURNAL" = "x0"],
+ [AC_MSG_ERROR([*** Needed systemd journal support not found])])
+
+AC_SUBST(HAVE_SYSTEMD_JOURNAL)
+AM_CONDITIONAL([HAVE_SYSTEMD_JOURNAL], [test "x$HAVE_SYSTEMD_JOURNAL" = x1])
+AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], AC_DEFINE([HAVE_JOURNAL], 1, [Have JOURNAL?]))
+
#### Build and Install man pages ####
AC_ARG_ENABLE([manpages],
@@ -1405,6 +1421,7 @@ AS_IF([test "x$HAVE_XEN" = "x1"], ENABLE_XEN=yes, ENABLE_XEN=no)
AS_IF([test "x$HAVE_DBUS" = "x1"], ENABLE_DBUS=yes, ENABLE_DBUS=no)
AS_IF([test "x$HAVE_UDEV" = "x1"], ENABLE_UDEV=yes, ENABLE_UDEV=no)
AS_IF([test "x$HAVE_SYSTEMD" = "x1"], ENABLE_SYSTEMD=yes, ENABLE_SYSTEMD=no)
+AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], ENABLE_SYSTEMD_JOURNAL=yes, ENABLE_SYSTEMD_JOURNAL=no)
AS_IF([test "x$HAVE_BLUEZ_4" = "x1"], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no)
AS_IF([test "x$HAVE_BLUEZ_5" = "x1"], ENABLE_BLUEZ_5=yes, ENABLE_BLUEZ_5=no)
AS_IF([test "x$HAVE_HAL_COMPAT" = "x1"], ENABLE_HAL_COMPAT=yes, ENABLE_HAL_COMPAT=no)
@@ -1463,6 +1480,7 @@ echo "
Enable udev: ${ENABLE_UDEV}
Enable HAL->udev compat: ${ENABLE_HAL_COMPAT}
Enable systemd login: ${ENABLE_SYSTEMD}
+ Enable systemd journal: ${ENABLE_SYSTEMD_JOURNAL}
Enable TCP Wrappers: ${ENABLE_TCPWRAP}
Enable libsamplerate: ${ENABLE_LIBSAMPLERATE}
Enable IPv6: ${ENABLE_IPV6}
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index c40d570..9596738 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -297,11 +297,12 @@ USA.
<option>
<p><opt>log-target=</opt> The default log target. Use either
- <opt>stderr</opt>, <opt>syslog</opt>, <opt>auto</opt>,
- <opt>file:PATH</opt> or <opt>newfile:PATH</opt>. <opt>auto</opt> is
- equivalent to <opt>sylog</opt> in case <opt>daemonize</opt> is enabled,
- otherwise to <opt>stderr</opt>. If set to <opt>file:PATH</opt>, logging
- is directed to the file indicated by PATH. <opt>newfile:PATH</opt> is
+ <opt>stderr</opt>, <opt>syslog</opt>, <opt>journal</opt> (optional),
+ <opt>auto</opt>, <opt>file:PATH</opt> or <opt>newfile:PATH</opt>. On traditional
+ systems <opt>auto</opt> is equivalent to <opt>syslog</opt>. On systemd-enabled
+ systems, auto is equivalent to <opt>journal</opt>, in case <opt>daemonize</opt>
+ is enabled, and to <opt>stderr</opt> otherwise. If set to <opt>file:PATH</opt>,
+ logging is directed to the file indicated by PATH. <opt>newfile:PATH</opt> is
otherwise the same as <opt>file:PATH</opt>, but existing files are never
overwritten. If the specified file already exists, a suffix is added to
the file name to avoid overwriting. Defaults to <opt>auto</opt>. The
diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in
index d7d7458..114cd96 100644
--- a/man/pulseaudio.1.xml.in
+++ b/man/pulseaudio.1.xml.in
@@ -217,12 +217,13 @@ USA.
</option>
<option>
- <p><opt>--log-target</opt><arg>={auto,syslog,stderr,file:PATH,newfile:PATH}</arg></p>
+ <p><opt>--log-target</opt><arg>={auto,syslog,journal,stderr,file:PATH,newfile:PATH}</arg></p>
<optdesc><p>Specify the log target. If set to <arg>auto</arg>
(which is the default), then logging is directed to syslog when
<opt>--daemonize</opt> is passed, otherwise to
- STDERR. If set to <arg>file:PATH</arg>, logging is directed to
+ STDERR. If set to <arg>journal</arg> logging is directed to the systemd
+ journal. If set to <arg>file:PATH</arg>, logging is directed to
the file indicated by PATH. <arg>newfile:PATH</arg> is otherwise
the same as file:PATH, but existing files are never overwritten.
If the specified file already exists, a suffix is added to the
diff --git a/src/Makefile.am b/src/Makefile.am
index 0296b3c..c89cd6d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -687,6 +687,11 @@ libpulsecommon_ at PA_MAJORMINOR@_la_CFLAGS += $(X11_CFLAGS)
libpulsecommon_ at PA_MAJORMINOR@_la_LDFLAGS += $(X11_LIBS)
endif
+if HAVE_SYSTEMD_JOURNAL
+libpulsecommon_ at PA_MAJORMINOR@_la_CFLAGS += $(JOURNAL_FLAGS)
+libpulsecommon_ at PA_MAJORMINOR@_la_LDFLAGS += $(JOURNAL_LIBS)
+endif
+
# proplist-util.h uses these header files, but not the library itself!
libpulsecommon_ at PA_MAJORMINOR@_la_CFLAGS += $(GLIB20_CFLAGS) $(GTK30_CFLAGS)
diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index 6361a3d..0fa8492 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -323,7 +323,11 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
case ARG_LOG_TARGET:
if (pa_daemon_conf_set_log_target(conf, optarg) < 0) {
+#ifdef HAVE_JOURNAL
+ pa_log(_("Invalid log target: use either 'syslog', 'journal','stderr' or 'auto' or a valid file name 'file:<path>', 'newfile:<path>'."));
+#else
pa_log(_("Invalid log target: use either 'syslog', 'stderr' or 'auto' or a valid file name 'file:<path>', 'newfile:<path>'."));
+#endif
goto fail;
}
break;
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 58cacf8..e01371e 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -817,7 +817,11 @@ int main(int argc, char *argv[]) {
#endif
if (!conf->log_target) {
+#ifdef HAVE_JOURNAL
+ pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL };
+#else
pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
+#endif
pa_log_set_target(&target);
}
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index 5535045..cf96dce 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -40,6 +40,10 @@
#include <syslog.h>
#endif
+#ifdef HAVE_JOURNAL
+#include <systemd/sd-journal.h>
+#endif
+
#include <pulse/gccmacro.h>
#include <pulse/rtclock.h>
#include <pulse/utf8.h>
@@ -90,6 +94,18 @@ static const int level_to_syslog[] = {
};
#endif
+/* These are actually equivalent to the syslog ones
+ * but we don't want to depend on syslog.h */
+#ifdef HAVE_JOURNAL
+static const int level_to_journal[] = {
+ [PA_LOG_ERROR] = 3,
+ [PA_LOG_WARN] = 4,
+ [PA_LOG_NOTICE] = 5,
+ [PA_LOG_INFO] = 6,
+ [PA_LOG_DEBUG] = 7
+};
+#endif
+
static const char level_to_char[] = {
[PA_LOG_ERROR] = 'E',
[PA_LOG_WARN] = 'W',
@@ -129,6 +145,9 @@ int pa_log_set_target(pa_log_target *t) {
switch (t->type) {
case PA_LOG_STDERR:
case PA_LOG_SYSLOG:
+#ifdef HAVE_JOURNAL
+ case PA_LOG_JOURNAL:
+#endif
case PA_LOG_NULL:
break;
case PA_LOG_FILE:
@@ -318,6 +337,20 @@ static void init_defaults(void) {
} PA_ONCE_END;
}
+#ifdef HAVE_SYSLOG_H
+static void log_syslog(pa_log_level_t level, char *t, char *timestamp, char *location, char *bt) {
+ char *local_t;
+
+ openlog(ident, LOG_PID, LOG_USER);
+
+ if ((local_t = pa_utf8_to_locale(t)))
+ t = local_t;
+
+ syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, t, pa_strempty(bt));
+ pa_xfree(local_t);
+}
+#endif
+
void pa_log_levelv_meta(
pa_log_level_t level,
const char*file,
@@ -450,19 +483,35 @@ void pa_log_levelv_meta(
}
#ifdef HAVE_SYSLOG_H
- case PA_LOG_SYSLOG: {
- char *local_t;
-
- openlog(ident, LOG_PID, LOG_USER);
+ case PA_LOG_SYSLOG:
+ log_syslog(level, t, timestamp, location, bt);
+ break;
+#endif
- if ((local_t = pa_utf8_to_locale(t)))
- t = local_t;
+#ifdef HAVE_JOURNAL
+ case PA_LOG_JOURNAL:
+ if (sd_journal_send("MESSAGE=%s", t,
+ "PRIORITY=%i", level_to_journal[level],
+ "CODE_FILE=%s", file,
+ "CODE_FUNC=%s", func,
+ "CODE_LINE=%d", line,
+ NULL) < 0) {
+#ifdef HAVE_SYSLOG_H
+ pa_log_target new_target = { .type = PA_LOG_SYSLOG, .file = NULL };
- syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, t, pa_strempty(bt));
- pa_xfree(local_t);
+ syslog(level_to_syslog[PA_LOG_ERROR], "%s%s%s", timestamp, __FILE__,
+ "Error writing logs to the journal. Redirect log messages to syslog.");
+ log_syslog(level, t, timestamp, location, bt);
+#else
+ pa_log_target new_target = { .type = PA_LOG_STDERR, .file = NULL };
+ saved_errno = errno;
+ fprintf(stderr, "%s\n", "Error writing logs to the journal. Redirect log messages to console.");
+ fprintf(stderr, "%s %s\n", metadata, t);
+#endif
+ pa_log_set_target(&new_target);
+ }
break;
- }
#endif
case PA_LOG_FILE:
@@ -570,6 +619,10 @@ pa_log_target *pa_log_parse_target(const char *string) {
t = pa_log_target_new(PA_LOG_STDERR, NULL);
else if (pa_streq(string, "syslog"))
t = pa_log_target_new(PA_LOG_SYSLOG, NULL);
+#ifdef HAVE_JOURNAL
+ else if (pa_streq(string, "journal"))
+ t = pa_log_target_new(PA_LOG_JOURNAL, NULL);
+#endif
else if (pa_streq(string, "null"))
t = pa_log_target_new(PA_LOG_NULL, NULL);
else if (pa_startswith(string, "file:"))
@@ -594,6 +647,11 @@ char *pa_log_target_to_string(const pa_log_target *t) {
case PA_LOG_SYSLOG:
string = pa_xstrdup("syslog");
break;
+#ifdef HAVE_JOURNAL
+ case PA_LOG_JOURNAL:
+ string = pa_xstrdup("journal");
+ break;
+#endif
case PA_LOG_NULL:
string = pa_xstrdup("null");
break;
diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h
index e7dca88..5e9611d 100644
--- a/src/pulsecore/log.h
+++ b/src/pulsecore/log.h
@@ -35,6 +35,9 @@
typedef enum pa_log_target_type {
PA_LOG_STDERR, /* default */
PA_LOG_SYSLOG,
+#ifdef HAVE_JOURNAL
+ PA_LOG_JOURNAL, /* systemd journal */
+#endif
PA_LOG_NULL, /* to /dev/null */
PA_LOG_FILE, /* to a user specified file */
PA_LOG_NEWFILE, /* with an automatic suffix to avoid overwriting anything */
--
1.8.4.2
More information about the pulseaudio-discuss
mailing list