@@ -987,9 +987,10 @@ test_misc_flags(void)
/* With empty --syslog */
const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
/* With valid --syslog */
- const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
+ const char *argv4[] = {prgname, prefix, mp_flag, "--syslog=both"};
/* With invalid --syslog */
- const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+ const char *argv5[] = {prgname, prefix, mp_flag, "--syslog=invalid"};
+
/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
no_shconf, nosh_prefix, no_huge};
@@ -108,30 +108,3 @@ Memory-related options
* ``--match-allocations``
Free hugepages back to system exactly as they were originally allocated.
-
-Other options
-~~~~~~~~~~~~~
-
-* ``--syslog <syslog facility>``
-
- Set syslog facility. Valid syslog facilities are::
-
- auth
- cron
- daemon
- ftp
- kern
- lpr
- mail
- news
- syslog
- user
- uucp
- local0
- local1
- local2
- local3
- local4
- local5
- local6
- local7
@@ -83,6 +83,23 @@ To prefix all console messages with ISO format time the syntax is::
/path/to/app --log-timestamp=iso
+Log output
+~~~~~~~~~~
+
+If desired, messages can be redirected to syslog (on Linux and FreeBSD) with the ``--syslog``
+option. There are three possible settings for this option:
+
+*always*
+ Redirect all log output to syslog.
+
+*auto*
+ Use console if it is a terminal, and use syslog if is not.
+
+*both*
+ Print to both console and syslog.
+
+If ``--syslog`` option is not specified, then only console (stderr) will be used.
+
Using Logging APIs to Generate Log Messages
@@ -91,7 +91,7 @@ eal_long_options[] = {
{OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
{OPT_SOCKET_MEM, 1, NULL, OPT_SOCKET_MEM_NUM },
{OPT_SOCKET_LIMIT, 1, NULL, OPT_SOCKET_LIMIT_NUM },
- {OPT_SYSLOG, 1, NULL, OPT_SYSLOG_NUM },
+ {OPT_SYSLOG, 2, NULL, OPT_SYSLOG_NUM },
{OPT_VDEV, 1, NULL, OPT_VDEV_NUM },
{OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
{OPT_VFIO_VF_TOKEN, 1, NULL, OPT_VFIO_VF_TOKEN_NUM },
@@ -2215,6 +2215,9 @@ eal_common_usage(void)
" (can be used multiple times)\n"
" --"OPT_VMWARE_TSC_MAP" Use VMware TSC map instead of native RDTSC\n"
" --"OPT_PROC_TYPE" Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
+ " --"OPT_SYSLOG"[=<when>] Enable use of syslog\n"
+#endif
" --"OPT_LOG_LEVEL"=<level> Set global log level\n"
" --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
" Set specific log level\n"
@@ -12,18 +12,19 @@
#include <regex.h>
#include <fnmatch.h>
#include <sys/queue.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_log.h>
#include <rte_per_lcore.h>
-#include "log_internal.h"
-#include "log_private.h"
-
#ifdef RTE_EXEC_ENV_WINDOWS
#include <rte_os_shim.h>
#endif
+#include "log_internal.h"
+#include "log_private.h"
+
struct rte_log_dynamic_type {
const char *name;
uint32_t loglevel;
@@ -496,20 +497,23 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
return ret;
}
-/* Placeholder */
-int
-eal_log_syslog(const char *mode __rte_unused)
-{
- return -1;
-}
-
/*
* Called by rte_eal_init
*/
void
-eal_log_init(const char *id __rte_unused)
+eal_log_init(const char *id)
{
- if (log_timestamp_enabled())
+ bool is_terminal;
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+ is_terminal = _isatty(_fileno(stderr));
+#else
+ is_terminal = isatty(STDERR_FILENO);
+#endif
+
+ if (log_syslog_enabled(is_terminal))
+ log_syslog_open(id, is_terminal);
+ else if (log_timestamp_enabled())
rte_logs.print_func = log_print_with_timestamp;
else
rte_logs.print_func = vfprintf;
@@ -17,4 +17,21 @@ ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
__rte_format_printf(2, 0)
int log_print_with_timestamp(FILE *f, const char *format, va_list ap);
+#ifdef RTE_EXEC_ENV_WINDOWS
+static inline bool
+log_syslog_enabled(bool is_tty __rte_unused)
+{
+ return false;
+}
+
+static inline void
+log_syslog_open(const char *id __rte_unused, bool is_terminal __rte_unused)
+{
+}
+#else
+
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+#endif
+
#endif /* LOG_PRIVATE_H */
new file mode 100644
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+static enum {
+ LOG_SYSLOG_NONE = 0, /* do not use syslog */
+ LOG_SYSLOG_AUTO, /* use syslog only if not a terminal */
+ LOG_SYSLOG_ALWAYS, /* always use syslog */
+ LOG_SYSLOG_BOTH, /* log to both syslog and stderr */
+} log_syslog_opt;
+
+int
+eal_log_syslog(const char *str)
+{
+ if (str == NULL || strcmp(str, "auto") == 0)
+ log_syslog_opt = LOG_SYSLOG_AUTO;
+ else if (strcmp(str, "both") == 0)
+ log_syslog_opt = LOG_SYSLOG_BOTH;
+ else if (strcmp(str, "always") == 0)
+ log_syslog_opt = LOG_SYSLOG_ALWAYS;
+ else
+ return -1;
+ return 0;
+}
+
+bool
+log_syslog_enabled(bool is_terminal)
+{
+ switch (log_syslog_opt) {
+ default:
+ return false;
+
+ case LOG_SYSLOG_ALWAYS:
+ case LOG_SYSLOG_BOTH:
+ return true;
+
+ case LOG_SYSLOG_AUTO:
+ return !is_terminal;
+ }
+}
+
+/*
+ * When syslog is used, the log stream is redirected to a
+ * pseudo FILE handle that calls these functions.
+ */
+static ssize_t
+syslog_log_write(__rte_unused void *c, const char *buf, size_t size)
+{
+ /* Syslog error levels are from 0 to 7, so subtract 1 to convert */
+ syslog(rte_log_cur_msg_loglevel() - 1, "%.*s", (int)size, buf);
+ return size;
+}
+
+static int
+syslog_log_close(__rte_unused void *c)
+{
+ closelog();
+ return 0;
+}
+
+static cookie_io_functions_t syslog_log_func = {
+ .write = syslog_log_write,
+ .close = syslog_log_close,
+};
+
+void
+log_syslog_open(const char *id, bool is_terminal)
+{
+ int flags = LOG_NDELAY | LOG_PID;
+
+ if (log_syslog_opt == LOG_SYSLOG_BOTH)
+ flags |= LOG_PERROR;
+
+ openlog(id, flags, is_terminal ? LOG_USER : LOG_DAEMON);
+
+ /* redirect other log messages to syslog as well */
+ FILE *log_stream = fopencookie(NULL, "w", syslog_log_func);
+ if (log_stream != NULL)
+ rte_openlog_stream(log_stream);
+}
@@ -7,4 +7,8 @@ sources = files(
'log_timestamp.c',
)
+if not is_windows
+ sources += files('log_syslog.c')
+endif
+
headers = files('rte_log.h')
@@ -29,7 +29,7 @@ INTERNAL {
eal_log_level2str;
eal_log_save_pattern;
eal_log_save_regexp;
- eal_log_syslog;
+ eal_log_syslog; # WINDOWS_NO_EXPORT
eal_log_timestamp;
rte_eal_log_cleanup;
};