[PATCH v22 12/15] log: add optional support of syslog
Stephen Hemminger
stephen at networkplumber.org
Tue Sep 17 22:35:54 CEST 2024
Log to syslog only if option is specified. And if syslog is used
then normally only log to syslog, don't duplicate output.
Also enables syslog support on FreeBSD.
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
Acked-by: Morten Brørup <mb at smartsharesystems.com>
---
app/test/test_eal_flags.c | 5 +-
doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
doc/guides/prog_guide/log_lib.rst | 17 ++++
lib/eal/common/eal_common_options.c | 5 +-
lib/log/log.c | 28 +++---
lib/log/log_private.h | 3 +
lib/log/log_stubs.c | 28 ++++++
lib/log/log_syslog.c | 88 +++++++++++++++++++
lib/log/meson.build | 6 ++
9 files changed, 166 insertions(+), 41 deletions(-)
create mode 100644 lib/log/log_stubs.c
create mode 100644 lib/log/log_syslog.c
diff --git a/app/test/test_eal_flags.c b/app/test/test_eal_flags.c
index 40dd288d5f..06295030b2 100644
--- a/app/test/test_eal_flags.c
+++ b/app/test/test_eal_flags.c
@@ -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};
diff --git a/doc/guides/linux_gsg/linux_eal_parameters.rst b/doc/guides/linux_gsg/linux_eal_parameters.rst
index ea8f381391..d86f94d8a8 100644
--- a/doc/guides/linux_gsg/linux_eal_parameters.rst
+++ b/doc/guides/linux_gsg/linux_eal_parameters.rst
@@ -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
diff --git a/doc/guides/prog_guide/log_lib.rst b/doc/guides/prog_guide/log_lib.rst
index 504eefe1d2..abaedc7212 100644
--- a/doc/guides/prog_guide/log_lib.rst
+++ b/doc/guides/prog_guide/log_lib.rst
@@ -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
diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c
index 27627fe5e4..8d5a83d871 100644
--- a/lib/eal/common/eal_common_options.c
+++ b/lib/eal/common/eal_common_options.c
@@ -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 },
@@ -2220,6 +2220,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"
diff --git a/lib/log/log.c b/lib/log/log.c
index 6ab856272c..4374cc81ff 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -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,28 +497,33 @@ 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)
{
+#ifdef RTE_EXEC_ENV_WINDOWS
+ RTE_SET_USED(id);
+#else
+ bool is_terminal = isatty(STDERR_FILENO);
+
+ if (log_syslog_enabled(is_terminal)) {
+ log_syslog_open(id, is_terminal);
+ goto notice;
+ }
+#endif
if (log_timestamp_enabled())
rte_logs.print_func = log_print_with_timestamp;
else
rte_logs.print_func = vfprintf;
+notice:
#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
RTE_LOG(NOTICE, EAL,
"Debug dataplane logs available - lower performance\n");
#endif
+ return; /* needed for goto target */
}
/*
diff --git a/lib/log/log_private.h b/lib/log/log_private.h
index 67cfe72fc6..e9a7a8829a 100644
--- a/lib/log/log_private.h
+++ b/lib/log/log_private.h
@@ -17,4 +17,7 @@ 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);
+bool log_syslog_enabled(bool is_tty);
+void log_syslog_open(const char *id, bool is_terminal);
+
#endif /* LOG_PRIVATE_H */
diff --git a/lib/log/log_stubs.c b/lib/log/log_stubs.c
new file mode 100644
index 0000000000..cb34217af8
--- /dev/null
+++ b/lib/log/log_stubs.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <regex.h>
+#include <fnmatch.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <rte_os_shim.h>
+
+#include <rte_log.h>
+#include <rte_per_lcore.h>
+
+#include "log_internal.h"
+#include "log_private.h"
+
+/* Stubs for Windows */
+int
+eal_log_syslog(const char *str __rte_unused)
+{
+ return -1;
+}
diff --git a/lib/log/log_syslog.c b/lib/log/log_syslog.c
new file mode 100644
index 0000000000..fb69921e05
--- /dev/null
+++ b/lib/log/log_syslog.c
@@ -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);
+}
diff --git a/lib/log/meson.build b/lib/log/meson.build
index 04235f6ee5..a4ceed491d 100644
--- a/lib/log/meson.build
+++ b/lib/log/meson.build
@@ -7,4 +7,10 @@ sources = files(
'log_timestamp.c',
)
+if is_windows
+ sources += files('log_stubs.c')
+else
+ sources += files('log_syslog.c')
+endif
+
headers = files('rte_log.h')
--
2.45.2
More information about the dev
mailing list