mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
log: Add support for the systemd journal
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.
This commit is contained in:
parent
a8fea5c468
commit
d20ee7e7f2
8 changed files with 113 additions and 19 deletions
18
configure.ac
18
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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -687,6 +687,11 @@ libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(X11_CFLAGS)
|
|||
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(X11_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_SYSTEMD_JOURNAL
|
||||
libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(JOURNAL_FLAGS)
|
||||
libpulsecommon_@PA_MAJORMINOR@_la_LDFLAGS += $(JOURNAL_LIBS)
|
||||
endif
|
||||
|
||||
# proplist-util.h uses these header files, but not the library itself!
|
||||
libpulsecommon_@PA_MAJORMINOR@_la_CFLAGS += $(GLIB20_CFLAGS) $(GTK30_CFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
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);
|
||||
|
||||
case PA_LOG_SYSLOG:
|
||||
log_syslog(level, t, timestamp, location, bt);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#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[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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue